From bb10adef79b14d2c99d1491f5844629376cc5f59 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 28 Dec 2020 12:01:03 +0100 Subject: [PATCH 001/174] Initial commit --- .gitignore | 76 + .gitlab-ci.yml | 51 + CHANGELOG.md | 3 + CONTRIBUTING.md | 54 + LICENSE | 661 +++++ README.md | 22 + analysis_options.yaml | 14 + example/matrix_api_lite_example.dart | 9 + lib/matrix_api_lite.dart | 83 + lib/src/README.md | 0 lib/src/matrix_api.dart | 2126 ++++++++++++++++ lib/src/model/algorithm_types.dart | 27 + lib/src/model/auth/authentication_data.dart | 36 + .../model/auth/authentication_identifier.dart | 33 + .../model/auth/authentication_password.dart | 84 + .../auth/authentication_phone_identifier.dart | 42 + .../model/auth/authentication_recaptcha.dart | 42 + ...authentication_third_party_identifier.dart | 42 + .../auth/authentication_three_pid_creds.dart | 85 + lib/src/model/auth/authentication_token.dart | 45 + lib/src/model/auth/authentication_types.dart | 34 + .../auth/authentication_user_identifier.dart | 39 + lib/src/model/basic_event.dart | 38 + lib/src/model/basic_event_with_sender.dart | 39 + lib/src/model/basic_room_event.dart | 46 + lib/src/model/device.dart | 46 + lib/src/model/event_context.dart | 73 + lib/src/model/event_types.dart | 63 + .../secret_storage_default_key_content.dart | 22 + .../events/secret_storage_key_content.dart | 57 + lib/src/model/events/tombstone_content.dart | 23 + lib/src/model/events_sync_update.dart | 47 + lib/src/model/filter.dart | 222 ++ lib/src/model/keys_query_response.dart | 117 + lib/src/model/login_response.dart | 47 + lib/src/model/login_types.dart | 52 + lib/src/model/marked_unread.dart | 43 + .../model/matrix_connection_exception.dart | 26 + lib/src/model/matrix_event.dart | 72 + lib/src/model/matrix_exception.dart | 110 + lib/src/model/matrix_keys.dart | 115 + lib/src/model/message_types.dart | 31 + .../model/notifications_query_response.dart | 72 + .../model/one_time_keys_claim_response.dart | 38 + lib/src/model/open_graph_data.dart | 63 + lib/src/model/open_id_credentials.dart | 40 + lib/src/model/presence.dart | 32 + lib/src/model/presence_content.dart | 49 + lib/src/model/profile.dart | 44 + lib/src/model/public_rooms_response.dart | 97 + lib/src/model/push_rule_set.dart | 143 ++ lib/src/model/pusher.dart | 93 + lib/src/model/request_token_response.dart | 34 + lib/src/model/room_alias_informations.dart | 34 + lib/src/model/room_keys_info.dart | 69 + lib/src/model/room_keys_keys.dart | 101 + lib/src/model/room_summary.dart | 42 + lib/src/model/server_capabilities.dart | 89 + lib/src/model/stripped_state_event.dart | 39 + lib/src/model/supported_protocol.dart | 92 + lib/src/model/supported_versions.dart | 36 + lib/src/model/sync_update.dart | 333 +++ lib/src/model/tag.dart | 42 + lib/src/model/third_party_identifier.dart | 43 + lib/src/model/third_party_location.dart | 37 + lib/src/model/third_party_user.dart | 37 + lib/src/model/timeline_history_response.dart | 46 + lib/src/model/turn_server_credentials.dart | 40 + .../model/upload_key_signatures_response.dart | 55 + lib/src/model/user_search_result.dart | 41 + lib/src/model/well_known_informations.dart | 54 + lib/src/model/who_is_info.dart | 107 + lib/src/utils/logs.dart | 51 + lib/src/utils/try_get_map_extension.dart | 18 + pubspec.yaml | 15 + test/fake_matrix_api.dart | 2159 +++++++++++++++++ test/matrix_api_test.dart | 1915 +++++++++++++++ 77 files changed, 11097 insertions(+) create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 analysis_options.yaml create mode 100644 example/matrix_api_lite_example.dart create mode 100644 lib/matrix_api_lite.dart create mode 100644 lib/src/README.md create mode 100644 lib/src/matrix_api.dart create mode 100644 lib/src/model/algorithm_types.dart create mode 100644 lib/src/model/auth/authentication_data.dart create mode 100644 lib/src/model/auth/authentication_identifier.dart create mode 100644 lib/src/model/auth/authentication_password.dart create mode 100644 lib/src/model/auth/authentication_phone_identifier.dart create mode 100644 lib/src/model/auth/authentication_recaptcha.dart create mode 100644 lib/src/model/auth/authentication_third_party_identifier.dart create mode 100644 lib/src/model/auth/authentication_three_pid_creds.dart create mode 100644 lib/src/model/auth/authentication_token.dart create mode 100644 lib/src/model/auth/authentication_types.dart create mode 100644 lib/src/model/auth/authentication_user_identifier.dart create mode 100644 lib/src/model/basic_event.dart create mode 100644 lib/src/model/basic_event_with_sender.dart create mode 100644 lib/src/model/basic_room_event.dart create mode 100644 lib/src/model/device.dart create mode 100644 lib/src/model/event_context.dart create mode 100644 lib/src/model/event_types.dart create mode 100644 lib/src/model/events/secret_storage_default_key_content.dart create mode 100644 lib/src/model/events/secret_storage_key_content.dart create mode 100644 lib/src/model/events/tombstone_content.dart create mode 100644 lib/src/model/events_sync_update.dart create mode 100644 lib/src/model/filter.dart create mode 100644 lib/src/model/keys_query_response.dart create mode 100644 lib/src/model/login_response.dart create mode 100644 lib/src/model/login_types.dart create mode 100644 lib/src/model/marked_unread.dart create mode 100644 lib/src/model/matrix_connection_exception.dart create mode 100644 lib/src/model/matrix_event.dart create mode 100644 lib/src/model/matrix_exception.dart create mode 100644 lib/src/model/matrix_keys.dart create mode 100644 lib/src/model/message_types.dart create mode 100644 lib/src/model/notifications_query_response.dart create mode 100644 lib/src/model/one_time_keys_claim_response.dart create mode 100644 lib/src/model/open_graph_data.dart create mode 100644 lib/src/model/open_id_credentials.dart create mode 100644 lib/src/model/presence.dart create mode 100644 lib/src/model/presence_content.dart create mode 100644 lib/src/model/profile.dart create mode 100644 lib/src/model/public_rooms_response.dart create mode 100644 lib/src/model/push_rule_set.dart create mode 100644 lib/src/model/pusher.dart create mode 100644 lib/src/model/request_token_response.dart create mode 100644 lib/src/model/room_alias_informations.dart create mode 100644 lib/src/model/room_keys_info.dart create mode 100644 lib/src/model/room_keys_keys.dart create mode 100644 lib/src/model/room_summary.dart create mode 100644 lib/src/model/server_capabilities.dart create mode 100644 lib/src/model/stripped_state_event.dart create mode 100644 lib/src/model/supported_protocol.dart create mode 100644 lib/src/model/supported_versions.dart create mode 100644 lib/src/model/sync_update.dart create mode 100644 lib/src/model/tag.dart create mode 100644 lib/src/model/third_party_identifier.dart create mode 100644 lib/src/model/third_party_location.dart create mode 100644 lib/src/model/third_party_user.dart create mode 100644 lib/src/model/timeline_history_response.dart create mode 100644 lib/src/model/turn_server_credentials.dart create mode 100644 lib/src/model/upload_key_signatures_response.dart create mode 100644 lib/src/model/user_search_result.dart create mode 100644 lib/src/model/well_known_informations.dart create mode 100644 lib/src/model/who_is_info.dart create mode 100644 lib/src/utils/logs.dart create mode 100644 lib/src/utils/try_get_map_extension.dart create mode 100644 pubspec.yaml create mode 100644 test/fake_matrix_api.dart create mode 100644 test/matrix_api_test.dart diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0ab205ed --- /dev/null +++ b/.gitignore @@ -0,0 +1,76 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +native/ +test/.test_coverage.dart +coverage/ +coverage_badge.svg + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Visual Studio Code related +.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +build/ +pubspec.lock + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..b324a26a --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,51 @@ +stages: + - coverage + - builddocs + - deploy + +test: + tags: + - linux + stage: coverage + image: google/dart + script: + - pub get + - pub run test + +code_analyze: + tags: + - docker + stage: coverage + image: cirrusci/flutter + dependencies: [] + script: + - flutter format lib/ test/ test_driver/ --set-exit-if-changed + - flutter analyze + +build_api_doc: + tags: + - docker + stage: builddocs + image: cirrusci/flutter + script: + - dartdoc --exclude "dart:async,dart:collection,dart:convert,dart:core,dart:developer,dart:io,dart:isolate,dart:math,dart:typed_data,dart:ui" + artifacts: + paths: + - doc/api/ + only: + - main + +pages: + tags: + - linux + stage: deploy + image: alpine:latest + script: + - mv doc/api/ public + dependencies: + - build_api_doc + artifacts: + paths: + - public + only: + - main \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..687440ba --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version, created by Stagehand diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..a5c23f7a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,54 @@ +# Contributing code to famedly talk + +Everyone is welcome to contribute code to FamedlySDK, provided that they are willing to license their contributions under the same license as the project itself. +Please follow these rules when contributing code to famedly talk: + +## Merge Requests: +- Never ever just push something directly to the master branch! +- Create a new branch or fork this project and send a Merge Request. +- Only Merge Requests with a working CI can be merged. +- Only Merge Requests with at least one code reviewer can be merged. +- Merge Requests may be refused if they don't follow the rules below. +- A new Merge Request SHOULD never decrease the test coverage. + +## Branches +### Naming + +Branches should get named by this pattern: `[Module Name]-[Type]-[Detail]`. + +That means for example: "users-fix-attach-roles-issue#765". + +Modules are various parts of the App. This can for example be the directory list or the chat room. + +Types can be one of these: +- **feature** +- **enhance** +- **cleanup** +- **refactor** +- **fix** +- **hotfix** (should rarely get used) + +The Detail part of the pattern should be a short description of what the branch delivers. + +## Commit Messages + +Commit Messages should get written in this pattern: `[[Module Name]] [Commit Message]`. +That means for example: "[users] add fetch users endpoint". + + +## File structure: +- Every file must be named by the class and must be capitalized in the beginning. +- Directories need to be lowercase. + +## Code style: +Please use code formatting. You can use VSCode or Android Studio. On other editors you need to run: +``` +flutter format lib/**/*/*.dart +``` + +## Code quality: +- Don't repeat yourself! Use local variables, functions, classes. +- Don't mix UI and business logic in the same environment. +- Write tests for new classes, functions and widgets. +- Keep it simple stupid: https://en.wikipedia.org/wiki/KISS_principle +- Describe all of your classes, methods and attributes using **dartdoc** comments. Read this for more informations: https://dart.dev/guides/language/effective-dart/documentation \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..096ad991 --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + famedlySDK + Copyright (C) 2019 famedly + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/README.md b/README.md new file mode 100644 index 00000000..1b0a69b6 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +A library for Dart developers. + +Created from templates made available by Stagehand under a BSD-style +[license](https://github.com/dart-lang/stagehand/blob/master/LICENSE). + +## Usage + +A simple usage example: + +```dart +import 'package:matrix_api_lite/matrix_api_lite.dart'; + +main() { + var awesome = new Awesome(); +} +``` + +## Features and bugs + +Please file feature requests and bugs at the [issue tracker][tracker]. + +[tracker]: http://example.com/issues/replaceme diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 00000000..a686c1b4 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,14 @@ +# Defines a default set of lint rules enforced for +# projects at Google. For details and rationale, +# see https://github.com/dart-lang/pedantic#enabled-lints. +include: package:pedantic/analysis_options.yaml + +# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. +# Uncomment to specify additional rules. +# linter: +# rules: +# - camel_case_types + +analyzer: +# exclude: +# - path/to/excluded/files/** diff --git a/example/matrix_api_lite_example.dart b/example/matrix_api_lite_example.dart new file mode 100644 index 00000000..c588cf51 --- /dev/null +++ b/example/matrix_api_lite_example.dart @@ -0,0 +1,9 @@ +//import 'package:matrix_api_lite/matrix_api_lite.dart'; + +import 'package:matrix_api_lite/src/matrix_api.dart'; + +void main() async { + final api = MatrixApi(homeserver: Uri.parse('https://matrix.org')); + final capabilities = await api.requestServerCapabilities(); + print(capabilities.toJson()); +} diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart new file mode 100644 index 00000000..d90c0a1b --- /dev/null +++ b/lib/matrix_api_lite.dart @@ -0,0 +1,83 @@ +/* + * Matrix API Lite + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +library matrix_api_lite; + +export 'src/matrix_api.dart'; +export 'src/utils/logs.dart'; +export 'src/utils/try_get_map_extension.dart'; +export 'src/model/algorithm_types.dart'; +export 'src/model/basic_event.dart'; +export 'src/model/basic_event_with_sender.dart'; +export 'src/model/basic_room_event.dart'; +export 'src/model/device.dart'; +export 'src/model/event_context.dart'; +export 'src/model/event_types.dart'; +export 'src/model/events_sync_update.dart'; +export 'src/model/filter.dart'; +export 'src/model/keys_query_response.dart'; +export 'src/model/login_response.dart'; +export 'src/model/login_types.dart'; +export 'src/model/matrix_connection_exception.dart'; +export 'src/model/matrix_event.dart'; +export 'src/model/matrix_exception.dart'; +export 'src/model/matrix_keys.dart'; +export 'src/model/message_types.dart'; +export 'src/model/notifications_query_response.dart'; +export 'src/model/one_time_keys_claim_response.dart'; +export 'src/model/open_graph_data.dart'; +export 'src/model/open_id_credentials.dart'; +export 'src/model/presence.dart'; +export 'src/model/presence_content.dart'; +export 'src/model/profile.dart'; +export 'src/model/public_rooms_response.dart'; +export 'src/model/push_rule_set.dart'; +export 'src/model/pusher.dart'; +export 'src/model/request_token_response.dart'; +export 'src/model/room_alias_informations.dart'; +export 'src/model/room_keys_info.dart'; +export 'src/model/room_keys_keys.dart'; +export 'src/model/room_summary.dart'; +export 'src/model/server_capabilities.dart'; +export 'src/model/stripped_state_event.dart'; +export 'src/model/supported_protocol.dart'; +export 'src/model/supported_versions.dart'; +export 'src/model/sync_update.dart'; +export 'src/model/tag.dart'; +export 'src/model/third_party_identifier.dart'; +export 'src/model/third_party_location.dart'; +export 'src/model/third_party_user.dart'; +export 'src/model/timeline_history_response.dart'; +export 'src/model/turn_server_credentials.dart'; +export 'src/model/upload_key_signatures_response.dart'; +export 'src/model/user_search_result.dart'; +export 'src/model/well_known_informations.dart'; +export 'src/model/who_is_info.dart'; +export 'src/model/auth/authentication_data.dart'; +export 'src/model/auth/authentication_identifier.dart'; +export 'src/model/auth/authentication_password.dart'; +export 'src/model/auth/authentication_phone_identifier.dart'; +export 'src/model/auth/authentication_recaptcha.dart'; +export 'src/model/auth/authentication_third_party_identifier.dart'; +export 'src/model/auth/authentication_three_pid_creds.dart'; +export 'src/model/auth/authentication_token.dart'; +export 'src/model/auth/authentication_types.dart'; +export 'src/model/auth/authentication_user_identifier.dart'; +export 'src/model/events/secret_storage_default_key_content.dart'; +export 'src/model/events/secret_storage_key_content.dart'; +export 'src/model/events/tombstone_content.dart'; diff --git a/lib/src/README.md b/lib/src/README.md new file mode 100644 index 00000000..e69de29b diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart new file mode 100644 index 00000000..a1c055c4 --- /dev/null +++ b/lib/src/matrix_api.dart @@ -0,0 +1,2126 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'dart:async'; +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:http/http.dart' as http; +import 'package:mime/mime.dart'; + +import 'model/auth/authentication_data.dart'; +import 'model/auth/authentication_types.dart'; +import 'model/device.dart'; +import 'model/event_context.dart'; +import 'model/events_sync_update.dart'; +import 'model/filter.dart'; +import 'model/keys_query_response.dart'; +import 'model/login_response.dart'; +import 'model/login_types.dart'; +import 'model/matrix_connection_exception.dart'; +import 'model/matrix_event.dart'; +import 'model/matrix_exception.dart'; +import 'model/matrix_keys.dart'; +import 'model/notifications_query_response.dart'; +import 'model/one_time_keys_claim_response.dart'; +import 'model/open_graph_data.dart'; +import 'model/open_id_credentials.dart'; +import 'model/presence_content.dart'; +import 'model/profile.dart'; +import 'model/public_rooms_response.dart'; +import 'model/push_rule_set.dart'; +import 'model/pusher.dart'; +import 'model/request_token_response.dart'; +import 'model/room_alias_informations.dart'; +import 'model/room_keys_info.dart'; +import 'model/room_keys_keys.dart'; +import 'model/server_capabilities.dart'; +import 'model/supported_protocol.dart'; +import 'model/supported_versions.dart'; +import 'model/sync_update.dart'; +import 'model/tag.dart'; +import 'model/third_party_identifier.dart'; +import 'model/third_party_location.dart'; +import 'model/third_party_user.dart'; +import 'model/timeline_history_response.dart'; +import 'model/turn_server_credentials.dart'; +import 'model/upload_key_signatures_response.dart'; +import 'model/user_search_result.dart'; +import 'model/well_known_informations.dart'; +import 'model/who_is_info.dart'; + +enum RequestType { GET, POST, PUT, DELETE } +enum IdServerUnbindResult { success, no_success } +enum ThirdPartyIdentifierMedium { email, msisdn } +enum Membership { join, invite, leave, ban } +enum Direction { b, f } +enum Visibility { public, private } +enum CreateRoomPreset { private_chat, public_chat, trusted_private_chat } + +String describeEnum(Object enumEntry) { + final description = enumEntry.toString(); + final indexOfDot = description.indexOf('.'); + assert(indexOfDot != -1 && indexOfDot < description.length - 1); + return description.substring(indexOfDot + 1); +} + +class MatrixApi { + /// The homeserver this client is communicating with. + Uri homeserver; + + /// This is the access token for the matrix client. When it is undefined, then + /// the user needs to sign in first. + String accessToken; + + /// Matrix synchronisation is done with https long polling. This needs a + /// timeout which is usually 30 seconds. + int syncTimeoutSec; + + http.Client httpClient = http.Client(); + + bool get _testMode => + homeserver.toString() == 'https://fakeserver.notexisting'; + + int _timeoutFactor = 1; + + MatrixApi({ + this.homeserver, + this.accessToken, + http.Client httpClient, + this.syncTimeoutSec = 30, + }) { + if (httpClient != null) { + this.httpClient = httpClient; + } + } + + /// Used for all Matrix json requests using the [c2s API](https://matrix.org/docs/spec/client_server/r0.6.0.html). + /// + /// Throws: TimeoutException, FormatException, MatrixException + /// + /// You must first set [this.homeserver] and for some endpoints also + /// [this.accessToken] before you can use this! For example to send a + /// message to a Matrix room with the id '!fjd823j:example.com' you call: + /// ``` + /// final resp = await request( + /// RequestType.PUT, + /// '/r0/rooms/!fjd823j:example.com/send/m.room.message/$txnId', + /// data: { + /// 'msgtype': 'm.text', + /// 'body': 'hello' + /// } + /// ); + /// ``` + /// + Future> request( + RequestType type, + String action, { + dynamic data = '', + int timeout, + String contentType = 'application/json', + Map query, + }) async { + if (homeserver == null) { + throw ('No homeserver specified.'); + } + timeout ??= (_timeoutFactor * syncTimeoutSec) + 5; + dynamic json; + (!(data is String)) ? json = jsonEncode(data) : json = data; + if (data is List || action.startsWith('/media/r0/upload')) json = data; + + final queryPart = query?.entries + ?.where((x) => x.value != null) + ?.map((x) => [x.key, x.value].map(Uri.encodeQueryComponent).join('=')) + ?.join('&'); + final url = ['${homeserver.toString()}/_matrix${action}', queryPart] + .where((x) => x != null && x != '') + .join('?'); + + var headers = {}; + if (type == RequestType.PUT || type == RequestType.POST) { + headers['Content-Type'] = contentType; + } + if (accessToken != null) { + headers['Authorization'] = 'Bearer ${accessToken}'; + } + + http.Response resp; + var jsonResp = {}; + try { + switch (describeEnum(type)) { + case 'GET': + resp = await httpClient.get(url, headers: headers).timeout( + Duration(seconds: timeout), + ); + break; + case 'POST': + resp = + await httpClient.post(url, body: json, headers: headers).timeout( + Duration(seconds: timeout), + ); + break; + case 'PUT': + resp = + await httpClient.put(url, body: json, headers: headers).timeout( + Duration(seconds: timeout), + ); + break; + case 'DELETE': + resp = await httpClient.delete(url, headers: headers).timeout( + Duration(seconds: timeout), + ); + break; + } + var respBody = resp.body; + try { + respBody = utf8.decode(resp.bodyBytes); + } catch (_) { + // No-OP + } + if (resp.statusCode >= 500 && resp.statusCode < 600) { + throw Exception(respBody); + } + var jsonString = String.fromCharCodes(respBody.runes); + if (jsonString.startsWith('[') && jsonString.endsWith(']')) { + jsonString = '\{"chunk":$jsonString\}'; + } + jsonResp = jsonDecode(jsonString) + as Map; // May throw FormatException + + _timeoutFactor = 1; + } on TimeoutException catch (e, s) { + _timeoutFactor *= 2; + throw MatrixConnectionException(e, s); + } catch (e, s) { + throw MatrixConnectionException(e, s); + } + if (resp.statusCode >= 400 && resp.statusCode < 500) { + throw MatrixException(resp); + } + + return jsonResp; + } + + /// Gets the versions of the specification supported by the server. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-versions + Future requestSupportedVersions() async { + final response = await request( + RequestType.GET, + '/client/versions', + ); + return SupportedVersions.fromJson(response); + } + + /// Gets discovery information about the domain. The file may include additional keys. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-well-known-matrix-client + Future requestWellKnownInformations() async { + var baseUrl = homeserver.toString(); + if (baseUrl.endsWith('/')) { + baseUrl = baseUrl.substring(0, baseUrl.length - 1); + } + final response = await httpClient.get('$baseUrl/.well-known/matrix/client'); + final rawJson = json.decode(response.body); + return WellKnownInformations.fromJson(rawJson); + } + + Future requestLoginTypes() async { + final response = await request( + RequestType.GET, + '/client/r0/login', + ); + return LoginTypes.fromJson(response); + } + + /// Authenticates the user, and issues an access token they can use to authorize themself in subsequent requests. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-login + Future login({ + String type = AuthenticationTypes.password, + String userIdentifierType, + String user, + String medium, + String address, + String password, + String token, + String deviceId, + String initialDeviceDisplayName, + AuthenticationData auth, + }) async { + final response = await request(RequestType.POST, '/client/r0/login', data: { + 'type': type, + if (userIdentifierType != null) + 'identifier': { + 'type': userIdentifierType, + if (user != null) 'user': user, + }, + if (user != null) 'user': user, + if (medium != null) 'medium': medium, + if (address != null) 'address': address, + if (password != null) 'password': password, + if (token != null) 'token': token, + if (deviceId != null) 'device_id': deviceId, + if (initialDeviceDisplayName != null) + 'initial_device_display_name': initialDeviceDisplayName, + if (auth != null) 'auth': auth.toJson(), + }); + return LoginResponse.fromJson(response); + } + + /// Invalidates an existing access token, so that it can no longer be used for authorization. + /// The device associated with the access token is also deleted. Device keys for the device + /// are deleted alongside the device. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-logout + Future logout() async { + await request( + RequestType.POST, + '/client/r0/logout', + ); + return; + } + + /// Invalidates all access tokens for a user, so that they can no longer be used + /// for authorization. This includes the access token that made this request. All + /// devices for the user are also deleted. Device keys for the device are + /// deleted alongside the device. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-logout-all + Future logoutAll() async { + await request( + RequestType.POST, + '/client/r0/logout/all', + ); + return; + } + + /// Register for an account on this homeserver. + /// + /// There are two kinds of user account: + /// + /// user accounts. These accounts may use the full API described in this + /// specification. + /// guest accounts. These accounts may have limited permissions and may not + /// be supported by all servers. + /// + /// If registration is successful, this endpoint will issue an access token + /// the client can use to authorize itself in subsequent requests. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register + Future register({ + String username, + String password, + String deviceId, + String initialDeviceDisplayName, + bool inhibitLogin, + AuthenticationData auth, + String kind, + }) async { + var action = '/client/r0/register'; + if (kind != null) action += '?kind=${Uri.encodeQueryComponent(kind)}'; + final response = await request(RequestType.POST, action, data: { + if (username != null) 'username': username, + if (password != null) 'password': password, + if (deviceId != null) 'device_id': deviceId, + if (initialDeviceDisplayName != null) + 'initial_device_display_name': initialDeviceDisplayName, + if (inhibitLogin != null) 'inhibit_login': inhibitLogin, + if (auth != null) 'auth': auth.toJson(), + }); + return LoginResponse.fromJson(response); + } + + /// The homeserver must check that the given email address is not already associated + /// with an account on this homeserver. The homeserver should validate the email + /// itself, either by sending a validation email itself or by using a service it + /// has control over. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register-email-requesttoken + Future requestEmailToken( + String email, + String clientSecret, + int sendAttempt, { + String nextLink, + String idServer, + String idAccessToken, + }) async { + final response = await request( + RequestType.POST, '/client/r0/register/email/requestToken', + data: { + 'email': email, + 'send_attempt': sendAttempt, + 'client_secret': clientSecret, + if (nextLink != null) 'next_link': nextLink, + if (idServer != null) 'id_server': idServer, + if (idAccessToken != null) 'id_access_token': idAccessToken, + }); + return RequestTokenResponse.fromJson(response); + } + + /// The homeserver must check that the given phone number is not already associated with an + /// account on this homeserver. The homeserver should validate the phone number itself, + /// either by sending a validation message itself or by using a service it has control over. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register-msisdn-requesttoken + Future requestMsisdnToken( + String country, + String phoneNumber, + String clientSecret, + int sendAttempt, { + String nextLink, + String idServer, + String idAccessToken, + }) async { + final response = await request( + RequestType.POST, '/client/r0/register/msisdn/requestToken', + data: { + 'country': country, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + 'client_secret': clientSecret, + if (nextLink != null) 'next_link': nextLink, + if (idServer != null) 'id_server': idServer, + if (idAccessToken != null) 'id_access_token': idAccessToken, + }); + return RequestTokenResponse.fromJson(response); + } + + /// Changes the password for an account on this homeserver. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password + Future changePassword( + String newPassword, { + AuthenticationData auth, + }) async { + await request(RequestType.POST, '/client/r0/account/password', data: { + 'new_password': newPassword, + if (auth != null) 'auth': auth.toJson(), + }); + return; + } + + /// The homeserver must check that the given email address is associated with + /// an account on this homeserver. This API should be used to request + /// validation tokens when authenticating for the /account/password endpoint. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password-email-requesttoken + Future resetPasswordUsingEmail( + String email, + String clientSecret, + int sendAttempt, { + String nextLink, + String idServer, + String idAccessToken, + }) async { + final response = await request( + RequestType.POST, '/client/r0/account/password/email/requestToken', + data: { + 'email': email, + 'send_attempt': sendAttempt, + 'client_secret': clientSecret, + if (nextLink != null) 'next_link': nextLink, + if (idServer != null) 'id_server': idServer, + if (idAccessToken != null) 'id_access_token': idAccessToken, + }); + return RequestTokenResponse.fromJson(response); + } + + /// The homeserver must check that the given phone number is associated with + /// an account on this homeserver. This API should be used to request validation + /// tokens when authenticating for the /account/password endpoint. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password-msisdn-requesttoken + Future resetPasswordUsingMsisdn( + String country, + String phoneNumber, + String clientSecret, + int sendAttempt, { + String nextLink, + String idServer, + String idAccessToken, + }) async { + final response = await request( + RequestType.POST, '/client/r0/account/password/msisdn/requestToken', + data: { + 'country': country, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + 'client_secret': clientSecret, + if (nextLink != null) 'next_link': nextLink, + if (idServer != null) 'id_server': idServer, + if (idAccessToken != null) 'id_access_token': idAccessToken, + }); + return RequestTokenResponse.fromJson(response); + } + + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-deactivate + Future deactivateAccount({ + String idServer, + AuthenticationData auth, + }) async { + final response = + await request(RequestType.POST, '/client/r0/account/deactivate', data: { + if (idServer != null) 'id_server': idServer, + if (auth != null) 'auth': auth.toJson(), + }); + + return IdServerUnbindResult.values.firstWhere( + (i) => describeEnum(i) == response['id_server_unbind_result'], + ); + } + + Future usernameAvailable(String username) async { + final response = await request( + RequestType.GET, + '/client/r0/register/available?username=$username', + ); + return response['available']; + } + + /// Gets a list of the third party identifiers that the homeserver has + /// associated with the user's account. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-register-available + Future> requestThirdPartyIdentifiers() async { + final response = await request( + RequestType.GET, + '/client/r0/account/3pid', + ); + return (response['threepids'] as List) + .map((item) => ThirdPartyIdentifier.fromJson(item)) + .toList(); + } + + /// Adds contact information to the user's account. Homeservers + /// should use 3PIDs added through this endpoint for password resets + /// instead of relying on the identity server. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-add + Future addThirdPartyIdentifier( + String clientSecret, + String sid, { + AuthenticationData auth, + }) async { + await request(RequestType.POST, '/client/r0/account/3pid/add', data: { + 'sid': sid, + 'client_secret': clientSecret, + if (auth != null) 'auth': auth.toJson(), + }); + return; + } + + /// Binds a 3PID to the user's account through the specified identity server. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-bind + Future bindThirdPartyIdentifier( + String clientSecret, + String sid, + String idServer, + String idAccessToken, + ) async { + await request(RequestType.POST, '/client/r0/account/3pid/bind', data: { + 'sid': sid, + 'client_secret': clientSecret, + 'id_server': idServer, + 'id_access_token': idAccessToken, + }); + return; + } + + /// Removes a third party identifier from the user's account. This might not cause an unbind of the identifier from the identity server. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-delete + Future deleteThirdPartyIdentifier( + String address, + ThirdPartyIdentifierMedium medium, { + String idServer, + }) async { + final response = await request( + RequestType.POST, '/client/r0/account/3pid/delete', + data: { + 'address': address, + 'medium': describeEnum(medium), + if (idServer != null) 'id_server': idServer, + }); + return IdServerUnbindResult.values.firstWhere( + (i) => describeEnum(i) == response['id_server_unbind_result'], + ); + } + + /// Removes a user's third party identifier from the provided identity server without removing it from the homeserver. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-unbind + Future unbindThirdPartyIdentifier( + String address, + ThirdPartyIdentifierMedium medium, + String idServer, + ) async { + final response = await request( + RequestType.POST, '/client/r0/account/3pid/unbind', + data: { + 'address': address, + 'medium': describeEnum(medium), + 'id_server': idServer, + }); + return IdServerUnbindResult.values.firstWhere( + (i) => describeEnum(i) == response['id_server_unbind_result'], + ); + } + + /// This API should be used to request validation tokens when adding an email address to an account. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-email-requesttoken + Future requestEmailValidationToken( + String email, + String clientSecret, + int sendAttempt, { + String nextLink, + String idServer, + String idAccessToken, + }) async { + final response = await request( + RequestType.POST, '/client/r0/account/3pid/email/requestToken', + data: { + 'email': email, + 'send_attempt': sendAttempt, + 'client_secret': clientSecret, + if (nextLink != null) 'next_link': nextLink, + if (idServer != null) 'id_server': idServer, + if (idAccessToken != null) 'id_access_token': idAccessToken, + }); + return RequestTokenResponse.fromJson(response); + } + + /// This API should be used to request validation tokens when adding a phone number to an account. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-msisdn-requesttoken + Future requestMsisdnValidationToken( + String country, + String phoneNumber, + String clientSecret, + int sendAttempt, { + String nextLink, + String idServer, + String idAccessToken, + }) async { + final response = await request( + RequestType.POST, '/client/r0/account/3pid/msisdn/requestToken', + data: { + 'country': country, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + 'client_secret': clientSecret, + if (nextLink != null) 'next_link': nextLink, + if (idServer != null) 'id_server': idServer, + if (idAccessToken != null) 'id_access_token': idAccessToken, + }); + return RequestTokenResponse.fromJson(response); + } + + /// Gets information about the owner of a given access token. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-account-whoami + Future whoAmI() async { + final response = await request( + RequestType.GET, + '/client/r0/account/whoami', + ); + return response['user_id']; + } + + /// Gets information about the server's supported feature set and other relevant capabilities. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-capabilities + Future requestServerCapabilities() async { + final response = await request( + RequestType.GET, + '/client/r0/capabilities', + ); + return ServerCapabilities.fromJson(response['capabilities']); + } + + /// Uploads a new filter definition to the homeserver. Returns a filter ID that may be used + /// in future requests to restrict which events are returned to the client. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-filter + Future uploadFilter( + String userId, + Filter filter, + ) async { + final response = await request( + RequestType.POST, + '/client/r0/user/${Uri.encodeComponent(userId)}/filter', + data: filter.toJson(), + ); + return response['filter_id']; + } + + /// Download a filter + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-filter + Future downloadFilter(String userId, String filterId) async { + final response = await request( + RequestType.GET, + '/client/r0/user/${Uri.encodeComponent(userId)}/filter/${Uri.encodeComponent(filterId)}', + ); + return Filter.fromJson(response); + } + + /// Synchronise the client's state with the latest state on the server. Clients use this API when + /// they first log in to get an initial snapshot of the state on the server, and then continue to + /// call this API to get incremental deltas to the state, and to receive new messages. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-sync + Future sync({ + String filter, + String since, + bool fullState, + PresenceType setPresence, + int timeout, + }) async { + final response = await request( + RequestType.GET, + '/client/r0/sync', + query: { + if (filter != null) 'filter': filter, + if (since != null) 'since': since, + if (fullState != null) 'full_state': fullState.toString(), + if (setPresence != null) 'set_presence': describeEnum(setPresence), + if (timeout != null) 'timeout': timeout.toString(), + }, + ); + return SyncUpdate.fromJson(response); + } + + /// Get a single event based on roomId/eventId. You must have permission to + /// retrieve this event e.g. by being a member in the room for this event. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-event-eventid + Future requestEvent(String roomId, String eventId) async { + final response = await request( + RequestType.GET, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/event/${Uri.encodeComponent(eventId)}', + ); + return MatrixEvent.fromJson(response); + } + + /// Looks up the contents of a state event in a room. If the user is joined to the room then the + /// state is taken from the current state of the room. If the user has left the room then the + /// state is taken from the state of the room when they left. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey + Future> requestStateContent( + String roomId, String eventType, + [String stateKey]) async { + var url = + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/'; + if (stateKey != null) { + url += Uri.encodeComponent(stateKey); + } + final response = await request( + RequestType.GET, + url, + ); + return response; + } + + /// Get the state events for the current state of a room. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-state + Future> requestStates(String roomId) async { + final response = await request( + RequestType.GET, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state', + ); + return (response['chunk'] as List) + .map((i) => MatrixEvent.fromJson(i)) + .toList(); + } + + /// Get the list of members for this room. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-members + Future> requestMembers( + String roomId, { + String at, + Membership membership, + Membership notMembership, + }) async { + final response = await request( + RequestType.GET, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/members', + query: { + if (at != null) 'at': at, + if (membership != null) 'membership': describeEnum(membership), + if (notMembership != null) + 'not_membership': describeEnum(notMembership), + }, + ); + return (response['chunk'] as List) + .map((i) => MatrixEvent.fromJson(i)) + .toList(); + } + + /// This API returns a map of MXIDs to member info objects for members of the room. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-joined-members + Future> requestJoinedMembers(String roomId) async { + final response = await request( + RequestType.GET, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/joined_members', + ); + return (response['joined'] as Map).map( + (k, v) => MapEntry(k, Profile.fromJson(v)), + ); + } + + /// This API returns a list of message and state events for a room. It uses pagination query + /// parameters to paginate history in the room. + /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-messages + Future requestMessages( + String roomId, + String from, + Direction dir, { + String to, + int limit, + String filter, + }) async { + final response = await request(RequestType.GET, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/messages', + query: { + 'from': from, + 'dir': describeEnum(dir), + if (to != null) 'to': to, + if (limit != null) 'limit': limit.toString(), + if (filter != null) 'filter': filter, + }); + return TimelineHistoryResponse.fromJson(response); + } + + /// State events can be sent using this endpoint. + /// https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey + Future sendState( + String roomId, + String eventType, + Map content, [ + String stateKey = '', + ]) async { + final response = await request(RequestType.PUT, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}', + data: content); + return response['event_id']; + } + + /// This endpoint is used to send a message event to a room. + /// Message events allow access to historical events and pagination, + /// making them suited for "once-off" activity in a room. + /// https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid + Future sendMessage( + String roomId, + String eventType, + String txnId, + Map content, + ) async { + final response = await request(RequestType.PUT, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/send/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}', + data: content); + return response['event_id']; + } + + /// Strips all information out of an event which isn't critical to the integrity of + /// the server-side representation of the room. + /// https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid + Future redact( + String roomId, + String eventId, + String txnId, { + String reason, + }) async { + final response = await request(RequestType.PUT, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/redact/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(txnId)}', + data: { + if (reason != null) 'reason': reason, + }); + return response['event_id']; + } + + Future createRoom({ + Visibility visibility, + String roomAliasName, + String name, + String topic, + List invite, + List> invite3pid, + String roomVersion, + Map creationContent, + List> initialState, + CreateRoomPreset preset, + bool isDirect, + Map powerLevelContentOverride, + }) async { + final response = + await request(RequestType.POST, '/client/r0/createRoom', data: { + if (visibility != null) 'visibility': describeEnum(visibility), + if (roomAliasName != null) 'room_alias_name': roomAliasName, + if (name != null) 'name': name, + if (topic != null) 'topic': topic, + if (invite != null) 'invite': invite, + if (invite3pid != null) 'invite_3pid': invite3pid, + if (roomVersion != null) 'room_version': roomVersion, + if (creationContent != null) 'creation_content': creationContent, + if (initialState != null) 'initial_state': initialState, + if (preset != null) 'preset': describeEnum(preset), + if (isDirect != null) 'is_direct': isDirect, + if (powerLevelContentOverride != null) + 'power_level_content_override': powerLevelContentOverride, + }); + return response['room_id']; + } + + /// Create a new mapping from room alias to room ID. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-directory-room-roomalias + Future createRoomAlias(String alias, String roomId) async { + await request( + RequestType.PUT, + '/client/r0/directory/room/${Uri.encodeComponent(alias)}', + data: {'room_id': roomId}, + ); + return; + } + + /// Requests that the server resolve a room alias to a room ID. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-room-roomalias + Future requestRoomAliasInformations( + String alias) async { + final response = await request( + RequestType.GET, + '/client/r0/directory/room/${Uri.encodeComponent(alias)}', + ); + return RoomAliasInformations.fromJson(response); + } + + /// Remove a mapping of room alias to room ID. + /// https://matrix.org/docs/spec/client_server/r0.6.1#delete-matrix-client-r0-directory-room-roomalias + Future removeRoomAlias(String alias) async { + await request( + RequestType.DELETE, + '/client/r0/directory/room/${Uri.encodeComponent(alias)}', + ); + return; + } + + /// Get a list of aliases maintained by the local server for the given room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-aliases + Future> requestRoomAliases(String roomId) async { + final response = await request( + RequestType.GET, + '/client/r0/room/${Uri.encodeComponent(roomId)}/aliases', + ); + return List.from(response['aliases']); + } + + /// This API returns a list of the user's current rooms. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-joined-rooms + Future> requestJoinedRooms() async { + final response = await request( + RequestType.GET, + '/client/r0/joined_rooms', + ); + return List.from(response['joined_rooms']); + } + + /// This API invites a user to participate in a particular room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-invite + Future inviteToRoom(String roomId, String userId) async { + await request( + RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/invite', + data: { + 'user_id': userId, + }, + ); + return; + } + + /// This API starts a user participating in a particular room, if that user is allowed to participate in that room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-invite + Future joinRoom( + String roomId, { + String thirdPidSignedSender, + String thirdPidSignedmxid, + String thirdPidSignedToken, + Map thirdPidSignedSiganture, + }) async { + final response = await request( + RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/join', + data: { + if (thirdPidSignedSiganture != null) + 'third_party_signed': { + 'sender': thirdPidSignedSender, + 'mxid': thirdPidSignedmxid, + 'token': thirdPidSignedToken, + 'signatures': thirdPidSignedSiganture, + } + }, + ); + return response['room_id']; + } + + /// This API starts a user participating in a particular room, if that user is allowed to participate in that room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-join-roomidoralias + Future joinRoomOrAlias( + String roomIdOrAlias, { + List servers, + String thirdPidSignedSender, + String thirdPidSignedmxid, + String thirdPidSignedToken, + Map thirdPidSignedSiganture, + }) async { + var action = '/client/r0/join/${Uri.encodeComponent(roomIdOrAlias)}'; + final queryPart = servers + ?.map((x) => 'server_name=${Uri.encodeQueryComponent(x)}') + ?.join('&'); + if (queryPart != null && queryPart != '') { + action += '?' + queryPart; + } + final response = await request( + RequestType.POST, + action, + data: { + if (thirdPidSignedSiganture != null) + 'third_party_signed': { + 'sender': thirdPidSignedSender, + 'mxid': thirdPidSignedmxid, + 'token': thirdPidSignedToken, + 'signatures': thirdPidSignedSiganture, + } + }, + ); + return response['room_id']; + } + + /// This API stops a user participating in a particular room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-leave + Future leaveRoom(String roomId) async { + await request( + RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/leave', + ); + return; + } + + /// This API stops a user remembering about a particular room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-forget + Future forgetRoom(String roomId) async { + await request( + RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/forget', + ); + return; + } + + /// Kick a user from the room. + /// The caller must have the required power level in order to perform this operation. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-kick + Future kickFromRoom(String roomId, String userId, + {String reason}) async { + await request(RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/kick', + data: { + 'user_id': userId, + if (reason != null) 'reason': reason, + }); + return; + } + + /// Ban a user in the room. If the user is currently in the room, also kick them. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-ban + Future banFromRoom(String roomId, String userId, + {String reason}) async { + await request( + RequestType.POST, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/ban', + data: { + 'user_id': userId, + if (reason != null) 'reason': reason, + }); + return; + } + + /// Unban a user from the room. This allows them to be invited to the room, and join if they + /// would otherwise be allowed to join according to its join rules. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-unban + Future unbanInRoom(String roomId, String userId) async { + await request(RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/unban', + data: { + 'user_id': userId, + }); + return; + } + + /// Gets the visibility of a given room on the server's public room directory. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-list-room-roomid + Future requestRoomVisibility(String roomId) async { + final response = await request( + RequestType.GET, + '/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}', + ); + return Visibility.values + .firstWhere((v) => describeEnum(v) == response['visibility']); + } + + /// Sets the visibility of a given room in the server's public room directory. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-directory-list-room-roomid + Future setRoomVisibility(String roomId, Visibility visibility) async { + await request( + RequestType.PUT, + '/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}', + data: { + 'visibility': describeEnum(visibility), + }, + ); + return; + } + + /// Lists the public rooms on the server. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-publicrooms + Future requestPublicRooms({ + int limit, + String since, + String server, + }) async { + final response = await request( + RequestType.GET, + '/client/r0/publicRooms', + query: { + if (limit != null) 'limit': limit.toString(), + if (since != null) 'since': since, + if (server != null) 'server': server, + }, + ); + return PublicRoomsResponse.fromJson(response); + } + + /// Lists the public rooms on the server, with optional filter. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-publicrooms + Future searchPublicRooms({ + String genericSearchTerm, + int limit, + String since, + String server, + bool includeAllNetworks, + String thirdPartyInstanceId, + }) async { + final response = await request( + RequestType.POST, + '/client/r0/publicRooms', + query: { + if (server != null) 'server': server, + }, + data: { + if (limit != null) 'limit': limit, + if (since != null) 'since': since, + if (includeAllNetworks != null) + 'include_all_networks': includeAllNetworks, + if (thirdPartyInstanceId != null) + 'third_party_instance_id': thirdPartyInstanceId, + if (genericSearchTerm != null) + 'filter': { + 'generic_search_term': genericSearchTerm, + }, + }, + ); + return PublicRoomsResponse.fromJson(response); + } + + /// Performs a search for users. The homeserver may determine which subset of users are searched, + /// however the homeserver MUST at a minimum consider the users the requesting user shares a + /// room with and those who reside in public rooms (known to the homeserver). The search MUST + /// consider local users to the homeserver, and SHOULD query remote users as part of the search. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-user-directory-search + Future searchUser( + String searchTerm, { + int limit, + }) async { + final response = await request( + RequestType.POST, + '/client/r0/user_directory/search', + data: { + 'search_term': searchTerm, + if (limit != null) 'limit': limit, + }, + ); + return UserSearchResult.fromJson(response); + } + + /// This API sets the given user's display name. You must have permission to + /// set this user's display name, e.g. you need to have their access_token. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-profile-userid-displayname + Future setDisplayname(String userId, String displayname) async { + await request( + RequestType.PUT, + '/client/r0/profile/${Uri.encodeComponent(userId)}/displayname', + data: { + 'displayname': displayname, + }, + ); + return; + } + + /// Get the user's display name. This API may be used to fetch the user's own + /// displayname or to query the name of other users; either locally or on remote homeservers. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-displayname + Future requestDisplayname(String userId) async { + final response = await request( + RequestType.GET, + '/client/r0/profile/${Uri.encodeComponent(userId)}/displayname', + ); + return response['displayname']; + } + + /// This API sets the given user's avatar URL. You must have permission to set + /// this user's avatar URL, e.g. you need to have their access_token. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-profile-userid-avatar-url + Future setAvatarUrl(String userId, Uri avatarUrl) async { + await request( + RequestType.PUT, + '/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url', + data: { + 'avatar_url': avatarUrl.toString(), + }, + ); + return; + } + + /// Get the user's avatar URL. This API may be used to fetch the user's own avatar URL or to + /// query the URL of other users; either locally or on remote homeservers. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-avatar-url + Future requestAvatarUrl(String userId) async { + final response = await request( + RequestType.GET, + '/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url', + ); + return Uri.parse(response['avatar_url']); + } + + /// Get the combined profile information for this user. This API may be used to fetch the user's + /// own profile information or other users; either locally or on remote homeservers. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-avatar-url + Future requestProfile(String userId) async { + final response = await request( + RequestType.GET, + '/client/r0/profile/${Uri.encodeComponent(userId)}', + ); + return Profile.fromJson(response); + } + + /// This API provides credentials for the client to use when initiating calls. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-voip-turnserver + Future requestTurnServerCredentials() async { + final response = await request( + RequestType.GET, + '/client/r0/voip/turnServer', + ); + return TurnServerCredentials.fromJson(response); + } + + /// This tells the server that the user is typing for the next N milliseconds + /// where N is the value specified in the timeout key. Alternatively, if typing is false, + /// it tells the server that the user has stopped typing. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-typing-userid + Future sendTypingNotification( + String userId, + String roomId, + bool typing, { + int timeout, + }) async { + await request(RequestType.PUT, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/typing/${Uri.encodeComponent(userId)}', + data: { + 'typing': typing, + if (timeout != null) 'timeout': timeout, + }); + return; + } + + /// This API updates the marker for the given receipt type to the event ID specified. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-receipt-receipttype-eventid + /// + Future sendReceiptMarker(String roomId, String eventId) async { + await request( + RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/receipt/m.read/${Uri.encodeComponent(eventId)}', + ); + return; + } + + /// Sets the position of the read marker for a given room, and optionally the read receipt's location. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-read-markers + Future sendReadMarker(String roomId, String eventId, + {String readReceiptLocationEventId}) async { + await request( + RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/read_markers', + data: { + 'm.fully_read': eventId, + if (readReceiptLocationEventId != null) + 'm.read': readReceiptLocationEventId, + }, + ); + return; + } + + /// This API sets the given user's presence state. When setting the status, + /// the activity time is updated to reflect that activity; the client does not need + /// to specify the last_active_ago field. You cannot set the presence state of another user. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-presence-userid-status + Future sendPresence( + String userId, + PresenceType presenceType, { + String statusMsg, + }) async { + await request( + RequestType.PUT, + '/client/r0/presence/${Uri.encodeComponent(userId)}/status', + data: { + 'presence': describeEnum(presenceType), + if (statusMsg != null) 'status_msg': statusMsg, + }, + ); + return; + } + + /// Get the given user's presence state. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-presence-userid-status + Future requestPresence(String userId) async { + final response = await request( + RequestType.GET, + '/client/r0/presence/${Uri.encodeComponent(userId)}/status', + ); + return PresenceContent.fromJson(response); + } + + /// Uploads a file with the name [fileName] as base64 encoded to the server + /// and returns the mxc url as a string. + /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-media-r0-upload + Future upload(Uint8List file, String fileName, + {String contentType}) async { + fileName = fileName.split('/').last; + var headers = {}; + headers['Authorization'] = 'Bearer $accessToken'; + headers['Content-Type'] = + contentType ?? lookupMimeType(fileName, headerBytes: file); + fileName = Uri.encodeQueryComponent(fileName); + final url = + '${homeserver.toString()}/_matrix/media/r0/upload?filename=$fileName'; + final streamedRequest = http.StreamedRequest('POST', Uri.parse(url)) + ..headers.addAll(headers); + streamedRequest.contentLength = await file.length; + streamedRequest.sink.add(file); + streamedRequest.sink.close(); + var streamedResponse = _testMode ? null : await streamedRequest.send(); + Map jsonResponse = json.decode( + String.fromCharCodes(_testMode + ? ((fileName == 'file.jpeg') + ? '{"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"}' + : '{"errcode":"M_FORBIDDEN","error":"Cannot upload this content"}') + .codeUnits + : await streamedResponse.stream.first), + ); + if (!(jsonResponse['content_uri'] is String)) { + throw MatrixException.fromJson(jsonResponse); + } + return jsonResponse['content_uri']; + } + + /// Get information about a URL for the client. Typically this is called when a client sees a + /// URL in a message and wants to render a preview for the user. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-preview-url + Future requestOpenGraphDataForUrl(Uri url, {int ts}) async { + var action = + '${homeserver.toString()}/_matrix/media/r0/preview_url?url=${Uri.encodeQueryComponent(url.toString())}'; + if (ts != null) { + action += '&ts=${Uri.encodeQueryComponent(ts.toString())}'; + } + final response = await httpClient.get(action); + final rawJson = json.decode(response.body.isEmpty ? '{}' : response.body); + return OpenGraphData.fromJson(rawJson); + } + + /// This endpoint allows clients to retrieve the configuration of the content repository, such as upload limitations. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-config + Future requestMaxUploadSize() async { + var action = '${homeserver.toString()}/_matrix/media/r0/config'; + final response = await httpClient.get(action); + final rawJson = json.decode(response.body.isEmpty ? '{}' : response.body); + return rawJson['m.upload.size']; + } + + /// This endpoint is used to send send-to-device events to a set of client devices. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-sendtodevice-eventtype-txnid + Future sendToDevice( + String eventType, + String txnId, + Map>> messages, + ) async { + await request( + RequestType.PUT, + '/client/r0/sendToDevice/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}', + data: { + 'messages': messages, + }, + ); + return; + } + + /// Gets information about all devices for the current user. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-devices + Future> requestDevices() async { + final response = await request( + RequestType.GET, + '/client/r0/devices', + ); + return (response['devices'] as List) + .map((i) => Device.fromJson(i)) + .toList(); + } + + /// Gets information on a single device, by device id. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-devices-deviceid + Future requestDevice(String deviceId) async { + final response = await request( + RequestType.GET, + '/client/r0/devices/${Uri.encodeComponent(deviceId)}', + ); + return Device.fromJson(response); + } + + /// Updates the metadata on the given device. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-devices-deviceid + Future setDeviceMetadata(String deviceId, {String displayName}) async { + await request( + RequestType.PUT, '/client/r0/devices/${Uri.encodeComponent(deviceId)}', + data: { + if (displayName != null) 'display_name': displayName, + }); + return; + } + + /// Deletes the given device, and invalidates any access token associated with it. + /// https://matrix.org/docs/spec/client_server/r0.6.1#delete-matrix-client-r0-devices-deviceid + Future deleteDevice(String deviceId, {AuthenticationData auth}) async { + await request(RequestType.DELETE, + '/client/r0/devices/${Uri.encodeComponent(deviceId)}', + data: { + if (auth != null) 'auth': auth.toJson(), + }); + return; + } + + /// Deletes the given devices, and invalidates any access token associated with them. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-delete-devices + Future deleteDevices(List deviceIds, + {AuthenticationData auth}) async { + await request(RequestType.POST, '/client/r0/delete_devices', data: { + 'devices': deviceIds, + if (auth != null) 'auth': auth.toJson(), + }); + return; + } + + /// Publishes end-to-end encryption keys for the device. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query + Future> uploadDeviceKeys( + {MatrixDeviceKeys deviceKeys, Map oneTimeKeys}) async { + final response = await request( + RequestType.POST, + '/client/r0/keys/upload', + data: { + if (deviceKeys != null) 'device_keys': deviceKeys.toJson(), + if (oneTimeKeys != null) 'one_time_keys': oneTimeKeys, + }, + ); + return Map.from(response['one_time_key_counts']); + } + + /// Returns the current devices and identity keys for the given users. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query + Future requestDeviceKeys( + Map deviceKeys, { + int timeout, + String token, + }) async { + final response = await request( + RequestType.POST, + '/client/r0/keys/query', + data: { + 'device_keys': deviceKeys, + if (timeout != null) 'timeout': timeout, + if (token != null) 'token': token, + }, + ); + return KeysQueryResponse.fromJson(response); + } + + /// Claims one-time keys for use in pre-key messages. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-claim + Future requestOneTimeKeys( + Map> oneTimeKeys, { + int timeout, + }) async { + final response = await request( + RequestType.POST, + '/client/r0/keys/claim', + data: { + 'one_time_keys': oneTimeKeys, + if (timeout != null) 'timeout': timeout, + }, + ); + return OneTimeKeysClaimResponse.fromJson(response); + } + + /// Gets a list of users who have updated their device identity keys since a previous sync token. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-upload + Future requestDeviceListsUpdate( + String from, String to) async { + final response = await request( + RequestType.GET, + '/client/r0/keys/changes?from=${Uri.encodeQueryComponent(from)}&to=${Uri.encodeQueryComponent(to)}', + ); + return DeviceListsUpdate.fromJson(response); + } + + /// Uploads your own cross-signing keys. + /// https://github.com/matrix-org/matrix-doc/pull/2536 + Future uploadDeviceSigningKeys({ + MatrixCrossSigningKey masterKey, + MatrixCrossSigningKey selfSigningKey, + MatrixCrossSigningKey userSigningKey, + AuthenticationData auth, + }) async { + await request( + RequestType.POST, + '/client/unstable/keys/device_signing/upload', + data: { + if (masterKey != null) 'master_key': masterKey.toJson(), + if (selfSigningKey != null) 'self_signing_key': selfSigningKey.toJson(), + if (userSigningKey != null) 'user_signing_key': userSigningKey.toJson(), + if (auth != null) 'auth': auth.toJson(), + }, + ); + } + + /// Uploads new signatures of keys + /// https://github.com/matrix-org/matrix-doc/pull/2536 + Future uploadKeySignatures( + List keys) async { + final payload = {}; + for (final key in keys) { + if (key.identifier == null || + key.signatures == null || + key.signatures.isEmpty) { + continue; + } + if (!payload.containsKey(key.userId)) { + payload[key.userId] = {}; + } + if (payload[key.userId].containsKey(key.identifier)) { + // we need to merge signature objects + payload[key.userId][key.identifier]['signatures'] + .addAll(key.signatures); + } else { + // we can just add signatures + payload[key.userId][key.identifier] = key.toJson(); + } + } + final response = await request( + RequestType.POST, + '/client/r0/keys/signatures/upload', + data: payload, + ); + return UploadKeySignaturesResponse.fromJson(response); + } + + /// Gets all currently active pushers for the authenticated user. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushers + Future> requestPushers() async { + final response = await request( + RequestType.GET, + '/client/r0/pushers', + ); + return (response['pushers'] as List) + .map((i) => Pusher.fromJson(i)) + .toList(); + } + + /// This endpoint allows the creation, modification and deletion of pushers + /// for this user ID. The behaviour of this endpoint varies depending on the + /// values in the JSON body. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-pushers-set + Future setPusher(Pusher pusher, {bool append}) async { + var data = pusher.toJson(); + if (append != null) { + data['append'] = append; + } + await request( + RequestType.POST, + '/client/r0/pushers/set', + data: data, + ); + return; + } + + /// This API is used to paginate through the list of events that the user has + /// been, or would have been notified about. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-notifications + Future requestNotifications({ + String from, + int limit, + String only, + }) async { + final response = await request( + RequestType.GET, + '/client/r0/notifications', + query: { + if (from != null) 'from': from, + if (limit != null) 'limit': limit.toString(), + if (only != null) 'only': only, + }, + ); + return NotificationsQueryResponse.fromJson(response); + } + + /// Retrieve all push rulesets for this user. Clients can "drill-down" + /// on the rulesets by suffixing a scope to this path e.g. /pushrules/global/. + /// This will return a subset of this data under the specified key e.g. the global key. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules + Future requestPushRules() async { + final response = await request( + RequestType.GET, + '/client/r0/pushrules', + ); + return PushRuleSet.fromJson(response['global']); + } + + /// Retrieve a single specified push rule. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid + Future requestPushRule( + String scope, + PushRuleKind kind, + String ruleId, + ) async { + final response = await request( + RequestType.GET, + '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}', + ); + return PushRule.fromJson(response); + } + + /// This endpoint removes the push rule defined in the path. + /// https://matrix.org/docs/spec/client_server/r0.6.1#delete-matrix-client-r0-pushrules-scope-kind-ruleid + Future deletePushRule( + String scope, + PushRuleKind kind, + String ruleId, + ) async { + await request( + RequestType.DELETE, + '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}', + ); + return; + } + + /// This endpoint allows the creation, modification and deletion of pushers for this user ID. + /// The behaviour of this endpoint varies depending on the values in the JSON body. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-pushrules-scope-kind-ruleid + Future setPushRule( + String scope, + PushRuleKind kind, + String ruleId, + List actions, { + String before, + String after, + List conditions, + String pattern, + }) async { + await request(RequestType.PUT, + '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}', + query: { + if (before != null) 'before': before, + if (after != null) 'after': after, + }, + data: { + 'actions': actions.map(describeEnum).toList(), + if (conditions != null) + 'conditions': conditions.map((c) => c.toJson()).toList(), + if (pattern != null) 'pattern': pattern, + }); + return; + } + + /// This endpoint gets whether the specified push rule is enabled. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid-enabled + Future requestPushRuleEnabled( + String scope, + PushRuleKind kind, + String ruleId, + ) async { + final response = await request( + RequestType.GET, + '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}/enabled', + ); + return response['enabled']; + } + + /// This endpoint allows clients to enable or disable the specified push rule. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-pushrules-scope-kind-ruleid-enabled + Future enablePushRule( + String scope, + PushRuleKind kind, + String ruleId, + bool enabled, + ) async { + await request( + RequestType.PUT, + '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}/enabled', + data: {'enabled': enabled}, + ); + return; + } + + /// This endpoint get the actions for the specified push rule. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid-actions + Future> requestPushRuleActions( + String scope, + PushRuleKind kind, + String ruleId, + ) async { + final response = await request( + RequestType.GET, + '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}/actions', + ); + return (response['actions'] as List) + .map((i) => + PushRuleAction.values.firstWhere((a) => describeEnum(a) == i)) + .toList(); + } + + /// This endpoint allows clients to change the actions of a push rule. This can be used to change the actions of builtin rules. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-pushrules-scope-kind-ruleid-actions + Future setPushRuleActions( + String scope, + PushRuleKind kind, + String ruleId, + List actions, + ) async { + await request( + RequestType.PUT, + '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}/actions', + data: {'actions': actions.map((a) => describeEnum(a)).toList()}, + ); + return; + } + + /// Performs a full text search across different categories. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-search + /// Please note: The specification is not 100% clear what it is expecting and sending here. + /// So we stick with pure json until we have more informations. + Future> globalSearch(Map query) async { + return await request( + RequestType.POST, + '/client/r0/search', + data: query, + ); + } + + /// This will listen for new events related to a particular room and return them to the + /// caller. This will block until an event is received, or until the timeout is reached. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-events + Future requestEvents({ + String from, + int timeout, + String roomId, + }) async { + final response = + await request(RequestType.GET, '/client/r0/events', query: { + if (from != null) 'from': from, + if (timeout != null) 'timeout': timeout.toString(), + if (roomId != null) 'roomId': roomId, + }); + return EventsSyncUpdate.fromJson(response); + } + + /// List the tags set by a user on a room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-rooms-roomid-tags + Future> requestRoomTags(String userId, String roomId) async { + final response = await request( + RequestType.GET, + '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags', + ); + return (response['tags'] as Map).map( + (k, v) => MapEntry(k, Tag.fromJson(v)), + ); + } + + /// Add a tag to the room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-tags-tag + Future addRoomTag( + String userId, + String roomId, + String tag, { + double order, + }) async { + await request(RequestType.PUT, + '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}', + data: { + if (order != null) 'order': order, + }); + return; + } + + /// Remove a tag from the room. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-tags-tag + Future removeRoomTag(String userId, String roomId, String tag) async { + await request( + RequestType.DELETE, + '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}', + ); + return; + } + + /// Set some account_data for the client. This config is only visible to the user that set the account_data. + /// The config will be synced to clients in the top-level account_data. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-account-data-type + Future setAccountData( + String userId, + String type, + Map content, + ) async { + await request( + RequestType.PUT, + '/client/r0/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}', + data: content, + ); + return; + } + + /// Get some account_data for the client. This config is only visible to the user that set the account_data. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-account-data-type + Future> requestAccountData( + String userId, + String type, + ) async { + return await request( + RequestType.GET, + '/client/r0/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}', + ); + } + + /// Set some account_data for the client on a given room. This config is only visible to the user that set + /// the account_data. The config will be synced to clients in the per-room account_data. + /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-account-data-type + Future setRoomAccountData( + String userId, + String roomId, + String type, + Map content, + ) async { + await request( + RequestType.PUT, + '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}', + data: content, + ); + return; + } + + /// Get some account_data for the client on a given room. This config is only visible to the user that set the account_data. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-rooms-roomid-account-data-type + Future> requestRoomAccountData( + String userId, + String roomId, + String type, + ) async { + return await request( + RequestType.GET, + '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}', + ); + } + + /// Gets information about a particular user. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-admin-whois-userid + Future requestWhoIsInfo(String userId) async { + final response = await request( + RequestType.GET, + '/client/r0/admin/whois/${Uri.encodeComponent(userId)}', + ); + return WhoIsInfo.fromJson(response); + } + + /// This API returns a number of events that happened just before and after the specified event. + /// This allows clients to get the context surrounding an event. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-context-eventid + Future requestEventContext( + String roomId, + String eventId, { + int limit, + String filter, + }) async { + final response = await request(RequestType.GET, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/context/${Uri.encodeComponent(eventId)}', + query: { + if (filter != null) 'filter': filter, + if (limit != null) 'limit': limit.toString(), + }); + return EventContext.fromJson(response); + } + + /// Reports an event as inappropriate to the server, which may then notify the appropriate people. + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-report-eventid + Future reportEvent( + String roomId, + String eventId, + String reason, + int score, + ) async { + await request(RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/report/${Uri.encodeComponent(eventId)}', + data: { + 'reason': reason, + 'score': score, + }); + return; + } + + /// Fetches the overall metadata about protocols supported by the homeserver. Includes + /// both the available protocols and all fields required for queries against each protocol. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-protocols + Future> requestSupportedProtocols() async { + final response = await request( + RequestType.GET, + '/client/r0/thirdparty/protocols', + ); + return response.map((k, v) => MapEntry(k, SupportedProtocol.fromJson(v))); + } + + /// Fetches the metadata from the homeserver about a particular third party protocol. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-protocol-protocol + Future requestSupportedProtocol(String protocol) async { + final response = await request( + RequestType.GET, + '/client/r0/thirdparty/protocol/${Uri.encodeComponent(protocol)}', + ); + return SupportedProtocol.fromJson(response); + } + + /// Requesting this endpoint with a valid protocol name results in a list of successful + /// mapping results in a JSON array. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-location-protocol + Future> requestThirdPartyLocations( + String protocol) async { + final response = await request( + RequestType.GET, + '/client/r0/thirdparty/location/${Uri.encodeComponent(protocol)}', + ); + return (response['chunk'] as List) + .map((i) => ThirdPartyLocation.fromJson(i)) + .toList(); + } + + /// Retrieve a Matrix User ID linked to a user on the third party service, given a set of + /// user parameters. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-user-protocol + Future> requestThirdPartyUsers(String protocol) async { + final response = await request( + RequestType.GET, + '/client/r0/thirdparty/user/${Uri.encodeComponent(protocol)}', + ); + return (response['chunk'] as List) + .map((i) => ThirdPartyUser.fromJson(i)) + .toList(); + } + + /// Retrieve an array of third party network locations from a Matrix room alias. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-location + Future> requestThirdPartyLocationsByAlias( + String alias) async { + final response = await request( + RequestType.GET, + '/client/r0/thirdparty/location?alias=${Uri.encodeComponent(alias)}', + ); + return (response['chunk'] as List) + .map((i) => ThirdPartyLocation.fromJson(i)) + .toList(); + } + + /// Retrieve an array of third party users from a Matrix User ID. + /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-user + Future> requestThirdPartyUsersByUserId( + String userId) async { + final response = await request( + RequestType.GET, + '/client/r0/thirdparty/user?userid=${Uri.encodeComponent(userId)}', + ); + return (response['chunk'] as List) + .map((i) => ThirdPartyUser.fromJson(i)) + .toList(); + } + + Future requestOpenIdCredentials(String userId) async { + final response = await request( + RequestType.POST, + '/client/r0/user/${Uri.encodeComponent(userId)}/openid/request_token', + data: {}, + ); + return OpenIdCredentials.fromJson(response); + } + + Future upgradeRoom(String roomId, String version) async { + await request( + RequestType.POST, + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/upgrade', + data: {'new_version': version}, + ); + return; + } + + /// Create room keys backup + /// https://matrix.org/docs/spec/client_server/unstable#post-matrix-client-r0-room-keys-version + Future createRoomKeysBackup( + RoomKeysAlgorithmType algorithm, Map authData) async { + final ret = await request( + RequestType.POST, + '/client/unstable/room_keys/version', + data: { + 'algorithm': algorithm.algorithmString, + 'auth_data': authData, + }, + ); + return ret['version']; + } + + /// Gets a room key backup + /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-version + Future getRoomKeysBackup([String version]) async { + var url = '/client/unstable/room_keys/version'; + if (version != null) { + url += '/${Uri.encodeComponent(version)}'; + } + final ret = await request( + RequestType.GET, + url, + ); + return RoomKeysVersionResponse.fromJson(ret); + } + + /// Updates a room key backup + /// https://matrix.org/docs/spec/client_server/unstable#put-matrix-client-r0-room-keys-version-version + Future updateRoomKeysBackup(String version, + RoomKeysAlgorithmType algorithm, Map authData) async { + await request( + RequestType.PUT, + '/client/unstable/room_keys/version/${Uri.encodeComponent(version)}', + data: { + 'algorithm': algorithm.algorithmString, + 'auth_data': authData, + 'version': version, + }, + ); + } + + /// Deletes a room key backup + /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-version-version + Future deleteRoomKeysBackup(String version) async { + await request( + RequestType.DELETE, + '/client/unstable/room_keys/version/${Uri.encodeComponent(version)}', + ); + } + + /// Stores a single room key + /// https://matrix.org/docs/spec/client_server/unstable#put-matrix-client-r0-room-keys-keys-roomid-sessionid + Future storeRoomKeysSingleKey(String roomId, + String sessionId, String version, RoomKeysSingleKey session) async { + final ret = await request( + RequestType.PUT, + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}?version=${Uri.encodeComponent(version)}', + data: session.toJson(), + ); + return RoomKeysUpdateResponse.fromJson(ret); + } + + /// Gets a single room key + /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys-roomid-sessionid + Future getRoomKeysSingleKey( + String roomId, String sessionId, String version) async { + final ret = await request( + RequestType.GET, + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}?version=${Uri.encodeComponent(version)}', + ); + return RoomKeysSingleKey.fromJson(ret); + } + + /// Deletes a single room key + /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys-roomid-sessionid + Future deleteRoomKeysSingleKey( + String roomId, String sessionId, String version) async { + final ret = await request( + RequestType.DELETE, + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}?version=${Uri.encodeComponent(version)}', + ); + return RoomKeysUpdateResponse.fromJson(ret); + } + + /// Stores room keys for a room + /// https://matrix.org/docs/spec/client_server/unstable#put-matrix-client-r0-room-keys-keys-roomid + Future storeRoomKeysRoom( + String roomId, String version, RoomKeysRoom keys) async { + final ret = await request( + RequestType.PUT, + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}?version=${Uri.encodeComponent(version)}', + data: keys.toJson(), + ); + return RoomKeysUpdateResponse.fromJson(ret); + } + + /// Gets room keys for a room + /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys-roomid + Future getRoomKeysRoom(String roomId, String version) async { + final ret = await request( + RequestType.GET, + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}?version=${Uri.encodeComponent(version)}', + ); + return RoomKeysRoom.fromJson(ret); + } + + /// Deletes room keys for a room + /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys-roomid + Future deleteRoomKeysRoom( + String roomId, String version) async { + final ret = await request( + RequestType.DELETE, + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}?version=${Uri.encodeComponent(version)}', + ); + return RoomKeysUpdateResponse.fromJson(ret); + } + + /// Store multiple room keys + /// https://matrix.org/docs/spec/client_server/unstable#put-matrix-client-r0-room-keys-keys + Future storeRoomKeys( + String version, RoomKeys keys) async { + final ret = await request( + RequestType.PUT, + '/client/unstable/room_keys/keys?version=${Uri.encodeComponent(version)}', + data: keys.toJson(), + ); + return RoomKeysUpdateResponse.fromJson(ret); + } + + /// get all room keys + /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys + Future getRoomKeys(String version) async { + final ret = await request( + RequestType.GET, + '/client/unstable/room_keys/keys?version=${Uri.encodeComponent(version)}', + ); + return RoomKeys.fromJson(ret); + } + + /// delete all room keys + /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys + Future deleteRoomKeys(String version) async { + final ret = await request( + RequestType.DELETE, + '/client/unstable/room_keys/keys?version=${Uri.encodeComponent(version)}', + ); + return RoomKeysUpdateResponse.fromJson(ret); + } +} diff --git a/lib/src/model/algorithm_types.dart b/lib/src/model/algorithm_types.dart new file mode 100644 index 00000000..cc657d7b --- /dev/null +++ b/lib/src/model/algorithm_types.dart @@ -0,0 +1,27 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +abstract class AlgorithmTypes { + static const String olmV1Curve25519AesSha2 = 'm.olm.v1.curve25519-aes-sha2'; + static const String megolmV1AesSha2 = 'm.megolm.v1.aes-sha2'; + static const String secretStorageV1AesHmcSha2 = + 'm.secret_storage.v1.aes-hmac-sha2'; + static const String megolmBackupV1Curve25519AesSha2 = + 'm.megolm_backup.v1.curve25519-aes-sha2'; + static const String pbkdf2 = 'm.pbkdf2'; +} diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart new file mode 100644 index 00000000..ad340400 --- /dev/null +++ b/lib/src/model/auth/authentication_data.dart @@ -0,0 +1,36 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class AuthenticationData { + String type; + String session; + + AuthenticationData({this.type, this.session}); + + AuthenticationData.fromJson(Map json) { + type = json['type']; + session = json['session']; + } + + Map toJson() { + final data = {}; + if (type != null) data['type'] = type; + if (session != null) data['session'] = session; + return data; + } +} diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart new file mode 100644 index 00000000..be5a4bfa --- /dev/null +++ b/lib/src/model/auth/authentication_identifier.dart @@ -0,0 +1,33 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class AuthenticationIdentifier { + String type; + + AuthenticationIdentifier({this.type}); + + AuthenticationIdentifier.fromJson(Map json) { + type = json['type']; + } + + Map toJson() { + final data = {}; + data['type'] = type; + return data; + } +} diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart new file mode 100644 index 00000000..fe28d1c8 --- /dev/null +++ b/lib/src/model/auth/authentication_password.dart @@ -0,0 +1,84 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'authentication_user_identifier.dart'; +import 'authentication_data.dart'; +import 'authentication_identifier.dart'; +import 'authentication_phone_identifier.dart'; +import 'authentication_third_party_identifier.dart'; +import 'authentication_types.dart'; + +class AuthenticationPassword extends AuthenticationData { + String user; + String password; + + /// You may want to cast this as [AuthenticationUserIdentifier] or other + /// Identifier classes extending AuthenticationIdentifier. + AuthenticationIdentifier identifier; + + AuthenticationPassword( + {String session, this.password, this.user, this.identifier}) + : super( + type: AuthenticationTypes.password, + session: session, + ); + + AuthenticationPassword.fromJson(Map json) + : super.fromJson(json) { + user = json['user']; + password = json['password']; + identifier = AuthenticationIdentifier.fromJson(json['identifier']); + switch (identifier.type) { + case AuthenticationIdentifierTypes.userId: + identifier = AuthenticationUserIdentifier.fromJson(json['identifier']); + break; + case AuthenticationIdentifierTypes.phone: + identifier = AuthenticationPhoneIdentifier.fromJson(json['identifier']); + break; + case AuthenticationIdentifierTypes.thirdParty: + identifier = + AuthenticationThirdPartyIdentifier.fromJson(json['identifier']); + break; + } + } + + @override + Map toJson() { + final data = super.toJson(); + if (user != null) data['user'] = user; + data['password'] = password; + switch (identifier.type) { + case AuthenticationIdentifierTypes.userId: + data['identifier'] = + (identifier as AuthenticationUserIdentifier).toJson(); + break; + case AuthenticationIdentifierTypes.phone: + data['identifier'] = + (identifier as AuthenticationPhoneIdentifier).toJson(); + break; + case AuthenticationIdentifierTypes.thirdParty: + data['identifier'] = + (identifier as AuthenticationThirdPartyIdentifier).toJson(); + break; + default: + data['identifier'] = identifier.toJson(); + break; + } + return data; + } +} diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart new file mode 100644 index 00000000..452f01c2 --- /dev/null +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -0,0 +1,42 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'authentication_identifier.dart'; +import 'authentication_types.dart'; + +class AuthenticationPhoneIdentifier extends AuthenticationIdentifier { + String country; + String phone; + + AuthenticationPhoneIdentifier({this.country, this.phone}) + : super(type: AuthenticationIdentifierTypes.phone); + + AuthenticationPhoneIdentifier.fromJson(Map json) + : super.fromJson(json) { + country = json['country']; + phone = json['phone']; + } + + @override + Map toJson() { + final data = super.toJson(); + data['country'] = country; + data['phone'] = phone; + return data; + } +} diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart new file mode 100644 index 00000000..3d0816ad --- /dev/null +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -0,0 +1,42 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'authentication_data.dart'; +import 'authentication_types.dart'; + +class AuthenticationRecaptcha extends AuthenticationData { + String response; + + AuthenticationRecaptcha({String session, this.response}) + : super( + type: AuthenticationTypes.recaptcha, + session: session, + ); + + AuthenticationRecaptcha.fromJson(Map json) + : super.fromJson(json) { + response = json['response']; + } + + @override + Map toJson() { + final data = super.toJson(); + data['response'] = response; + return data; + } +} diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart new file mode 100644 index 00000000..5a4ab496 --- /dev/null +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -0,0 +1,42 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'authentication_identifier.dart'; +import 'authentication_types.dart'; + +class AuthenticationThirdPartyIdentifier extends AuthenticationIdentifier { + String medium; + String address; + + AuthenticationThirdPartyIdentifier({this.medium, this.address}) + : super(type: AuthenticationIdentifierTypes.thirdParty); + + AuthenticationThirdPartyIdentifier.fromJson(Map json) + : super.fromJson(json) { + medium = json['medium']; + address = json['address']; + } + + @override + Map toJson() { + final data = super.toJson(); + data['medium'] = medium; + data['address'] = address; + return data; + } +} diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart new file mode 100644 index 00000000..1ddb45e7 --- /dev/null +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -0,0 +1,85 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'authentication_data.dart'; + +/// For email based identity: +/// https://matrix.org/docs/spec/client_server/r0.6.1#email-based-identity-homeserver +/// Or phone number based identity: +/// https://matrix.org/docs/spec/client_server/r0.6.1#phone-number-msisdn-based-identity-homeserver +class AuthenticationThreePidCreds extends AuthenticationData { + List threepidCreds; + + AuthenticationThreePidCreds({String session, String type, this.threepidCreds}) + : super( + type: type, + session: session, + ); + + AuthenticationThreePidCreds.fromJson(Map json) + : super.fromJson(json) { + if (json['threepidCreds'] != null) { + threepidCreds = (json['threepidCreds'] as List) + .map((item) => ThreepidCreds.fromJson(item)) + .toList(); + } + + // This is so extremly stupid... kill it with fire! + if (json['threepid_creds'] != null) { + threepidCreds = (json['threepid_creds'] as List) + .map((item) => ThreepidCreds.fromJson(item)) + .toList(); + } + } + + @override + Map toJson() { + final data = super.toJson(); + data['threepidCreds'] = threepidCreds.map((t) => t.toJson()).toList(); + // Help me! I'm prisoned in a developer factory against my will, + // where we are forced to work with json like this!! + data['threepid_creds'] = threepidCreds.map((t) => t.toJson()).toList(); + return data; + } +} + +class ThreepidCreds { + String sid; + String clientSecret; + String idServer; + String idAccessToken; + + ThreepidCreds( + {this.sid, this.clientSecret, this.idServer, this.idAccessToken}); + + ThreepidCreds.fromJson(Map json) { + sid = json['sid']; + clientSecret = json['client_secret']; + idServer = json['id_server']; + idAccessToken = json['id_access_token']; + } + + Map toJson() { + final data = {}; + data['sid'] = sid; + data['client_secret'] = clientSecret; + data['id_server'] = idServer; + data['id_access_token'] = idAccessToken; + return data; + } +} diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart new file mode 100644 index 00000000..23db3755 --- /dev/null +++ b/lib/src/model/auth/authentication_token.dart @@ -0,0 +1,45 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'authentication_data.dart'; +import 'authentication_types.dart'; + +class AuthenticationToken extends AuthenticationData { + String token; + String txnId; + + AuthenticationToken({String session, this.token, this.txnId}) + : super( + type: AuthenticationTypes.token, + session: session, + ); + + AuthenticationToken.fromJson(Map json) + : super.fromJson(json) { + token = json['token']; + txnId = json['txn_id']; + } + + @override + Map toJson() { + final data = super.toJson(); + data['token'] = token; + data['txn_id'] = txnId; + return data; + } +} diff --git a/lib/src/model/auth/authentication_types.dart b/lib/src/model/auth/authentication_types.dart new file mode 100644 index 00000000..34e357f3 --- /dev/null +++ b/lib/src/model/auth/authentication_types.dart @@ -0,0 +1,34 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +abstract class AuthenticationTypes { + static const String password = 'm.login.password'; + static const String recaptcha = 'm.login.recaptcha'; + static const String token = 'm.login.token'; + static const String oauth2 = 'm.login.oauth2'; + static const String sso = 'm.login.sso'; + static const String emailIdentity = 'm.login.email.identity'; + static const String msisdn = 'm.login.msisdn'; + static const String dummy = 'm.login.dummy'; +} + +abstract class AuthenticationIdentifierTypes { + static const String userId = 'm.id.user'; + static const String thirdParty = 'm.id.thirdparty'; + static const String phone = 'm.id.phone'; +} diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart new file mode 100644 index 00000000..66e6091e --- /dev/null +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -0,0 +1,39 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'authentication_identifier.dart'; +import 'authentication_types.dart'; + +class AuthenticationUserIdentifier extends AuthenticationIdentifier { + String user; + + AuthenticationUserIdentifier({this.user}) + : super(type: AuthenticationIdentifierTypes.userId); + + AuthenticationUserIdentifier.fromJson(Map json) + : super.fromJson(json) { + user = json['user']; + } + + @override + Map toJson() { + final data = super.toJson(); + data['user'] = user; + return data; + } +} diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart new file mode 100644 index 00000000..095b2b21 --- /dev/null +++ b/lib/src/model/basic_event.dart @@ -0,0 +1,38 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class BasicEvent { + String type; + Map content; + + BasicEvent({ + this.type, + this.content, + }); + + BasicEvent.fromJson(Map json) { + type = json['type']; + content = Map.from(json['content']); + } + Map toJson() { + final data = {}; + data['type'] = type; + data['content'] = content; + return data; + } +} diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart new file mode 100644 index 00000000..0e50bd86 --- /dev/null +++ b/lib/src/model/basic_event_with_sender.dart @@ -0,0 +1,39 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'basic_event.dart'; + +class BasicEventWithSender extends BasicEvent { + String senderId; + + BasicEventWithSender(); + + BasicEventWithSender.fromJson(Map json) { + final basicEvent = BasicEvent.fromJson(json); + type = basicEvent.type; + content = basicEvent.content; + senderId = json['sender']; + } + + @override + Map toJson() { + final data = super.toJson(); + data['sender'] = senderId; + return data; + } +} diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart new file mode 100644 index 00000000..de8ee75c --- /dev/null +++ b/lib/src/model/basic_room_event.dart @@ -0,0 +1,46 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'basic_event.dart'; + +class BasicRoomEvent extends BasicEvent { + String roomId; + + BasicRoomEvent({ + this.roomId, + Map content, + String type, + }) : super( + content: content, + type: type, + ); + + BasicRoomEvent.fromJson(Map json) { + final basicEvent = BasicEvent.fromJson(json); + content = basicEvent.content; + type = basicEvent.type; + roomId = json['room_id']; + } + + @override + Map toJson() { + final data = super.toJson(); + if (roomId != null) data['room_id'] = roomId; + return data; + } +} diff --git a/lib/src/model/device.dart b/lib/src/model/device.dart new file mode 100644 index 00000000..aa089a4b --- /dev/null +++ b/lib/src/model/device.dart @@ -0,0 +1,46 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class Device { + String deviceId; + String displayName; + String lastSeenIp; + DateTime lastSeenTs; + + Device.fromJson(Map json) { + deviceId = json['device_id']; + displayName = json['display_name']; + lastSeenIp = json['last_seen_ip']; + lastSeenTs = DateTime.fromMillisecondsSinceEpoch(json['last_seen_ts'] ?? 0); + } + + Map toJson() { + final data = {}; + data['device_id'] = deviceId; + if (displayName != null) { + data['display_name'] = displayName; + } + if (lastSeenIp != null) { + data['last_seen_ip'] = lastSeenIp; + } + if (lastSeenTs != null) { + data['last_seen_ts'] = lastSeenTs.millisecondsSinceEpoch; + } + return data; + } +} diff --git a/lib/src/model/event_context.dart b/lib/src/model/event_context.dart new file mode 100644 index 00000000..9d23961c --- /dev/null +++ b/lib/src/model/event_context.dart @@ -0,0 +1,73 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'matrix_event.dart'; + +class EventContext { + String end; + List eventsAfter; + MatrixEvent event; + List eventsBefore; + String start; + List state; + + EventContext.fromJson(Map json) { + end = json['end']; + if (json['events_after'] != null) { + eventsAfter = []; + json['events_after'].forEach((v) { + eventsAfter.add(MatrixEvent.fromJson(v)); + }); + } + event = json['event'] != null ? MatrixEvent.fromJson(json['event']) : null; + if (json['events_before'] != null) { + eventsBefore = []; + json['events_before'].forEach((v) { + eventsBefore.add(MatrixEvent.fromJson(v)); + }); + } + start = json['start']; + if (json['state'] != null) { + state = []; + json['state'].forEach((v) { + state.add(MatrixEvent.fromJson(v)); + }); + } + } + + Map toJson() { + final data = {}; + if (end != null) { + data['end'] = end; + } + if (eventsAfter != null) { + data['events_after'] = eventsAfter.map((v) => v.toJson()).toList(); + } + if (event != null) { + data['event'] = event.toJson(); + } + if (eventsBefore != null) { + data['events_before'] = eventsBefore.map((v) => v.toJson()).toList(); + } + data['start'] = start; + if (state != null) { + data['state'] = state.map((v) => v.toJson()).toList(); + } + return data; + } +} diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart new file mode 100644 index 00000000..36b63a7d --- /dev/null +++ b/lib/src/model/event_types.dart @@ -0,0 +1,63 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +abstract class EventTypes { + // Room timeline and state event types + static const String Message = 'm.room.message'; + static const String Sticker = 'm.sticker'; + static const String Reaction = 'm.reaction'; + static const String Redaction = 'm.room.redaction'; + static const String RoomAliases = 'm.room.aliases'; + static const String RoomCanonicalAlias = 'm.room.canonical_alias'; + static const String RoomCreate = 'm.room.create'; + static const String RoomJoinRules = 'm.room.join_rules'; + static const String RoomMember = 'm.room.member'; + static const String RoomPowerLevels = 'm.room.power_levels'; + static const String RoomName = 'm.room.name'; + static const String RoomPinnedEvents = 'm.room.pinned_events'; + static const String RoomTopic = 'm.room.topic'; + static const String RoomAvatar = 'm.room.avatar'; + static const String RoomTombstone = 'm.room.tombstone'; + static const String GuestAccess = 'm.room.guest_access'; + static const String HistoryVisibility = 'm.room.history_visibility'; + static const String Encryption = 'm.room.encryption'; + static const String Encrypted = 'm.room.encrypted'; + static const String CallInvite = 'm.call.invite'; + static const String CallAnswer = 'm.call.answer'; + static const String CallCandidates = 'm.call.candidates'; + static const String CallHangup = 'm.call.hangup'; + static const String Unknown = 'm.unknown'; + + // To device event types + static const String RoomKey = 'm.room_key'; + static const String ForwardedRoomKey = 'm.forwarded_room_key'; + static const String RoomKeyRequest = 'm.room_key_request'; + static const String KeyVerificationRequest = 'm.key.verification.request'; + static const String KeyVerificationStart = 'm.key.verification.start'; + static const String KeyVerificationDone = 'm.key.verification.done'; + static const String KeyVerificationCancel = 'm.key.verification.cancel'; + static const String KeyVerificationAccept = 'm.key.verification.accept'; + static const String SecretRequest = 'm.secret.request'; + static const String SecretSend = 'm.secret.send'; + static const String CrossSigningSelfSigning = 'm.cross_signing.self_signing'; + static const String CrossSigningUserSigning = 'm.cross_signing.user_signing'; + static const String CrossSigningMasterKey = 'm.cross_signing.master'; + static const String MegolmBackup = 'm.megolm_backup.v1'; + static const String SecretStorageDefaultKey = 'm.secret_storage.default_key'; + static String secretStorageKey(String keyId) => 'm.secret_storage.key.$keyId'; +} diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/src/model/events/secret_storage_default_key_content.dart new file mode 100644 index 00000000..2e40ddf5 --- /dev/null +++ b/lib/src/model/events/secret_storage_default_key_content.dart @@ -0,0 +1,22 @@ +import '../basic_event.dart'; +import '../../utils/try_get_map_extension.dart'; + +extension SecretStorageDefaultKeyContentBasicEventExtension on BasicEvent { + SecretStorageDefaultKeyContent get parsedSecretStorageDefaultKeyContent => + SecretStorageDefaultKeyContent.fromJson(content); +} + +class SecretStorageDefaultKeyContent { + String key; + + SecretStorageDefaultKeyContent(); + + SecretStorageDefaultKeyContent.fromJson(Map json) + : key = json.tryGet('key'); + + Map toJson() { + final data = {}; + if (key != null) data['key'] = key; + return data; + } +} diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart new file mode 100644 index 00000000..29050834 --- /dev/null +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -0,0 +1,57 @@ +import '../basic_event.dart'; +import '../../utils/try_get_map_extension.dart'; + +extension SecretStorageKeyContentBasicEventExtension on BasicEvent { + SecretStorageKeyContent get parsedSecretStorageKeyContent => + SecretStorageKeyContent.fromJson(content); +} + +class SecretStorageKeyContent { + PassphraseInfo passphrase; + String iv; + String mac; + String algorithm; + + SecretStorageKeyContent(); + + SecretStorageKeyContent.fromJson(Map json) + : passphrase = json['passphrase'] is Map + ? PassphraseInfo.fromJson(json['passphrase']) + : null, + iv = json.tryGet('iv'), + mac = json.tryGet('mac'), + algorithm = json.tryGet('algorithm'); + + Map toJson() { + final data = {}; + if (passphrase != null) data['passphrase'] = passphrase.toJson(); + if (iv != null) data['iv'] = iv; + if (mac != null) data['mac'] = mac; + if (algorithm != null) data['algorithm'] = algorithm; + return data; + } +} + +class PassphraseInfo { + String algorithm; + String salt; + int iterations; + int bits; + + PassphraseInfo(); + + PassphraseInfo.fromJson(Map json) + : algorithm = json.tryGet('algorithm'), + salt = json.tryGet('salt'), + iterations = json.tryGet('iterations'), + bits = json.tryGet('bits'); + + Map toJson() { + final data = {}; + if (algorithm != null) data['algorithm'] = algorithm; + if (salt != null) data['salt'] = salt; + if (iterations != null) data['iterations'] = iterations; + if (bits != null) data['bits'] = bits; + return data; + } +} diff --git a/lib/src/model/events/tombstone_content.dart b/lib/src/model/events/tombstone_content.dart new file mode 100644 index 00000000..efddba3c --- /dev/null +++ b/lib/src/model/events/tombstone_content.dart @@ -0,0 +1,23 @@ +import '../basic_event.dart'; +import '../../utils/try_get_map_extension.dart'; + +extension TombstoneContentBasicEventExtension on BasicEvent { + TombstoneContent get parsedTombstoneContent => + TombstoneContent.fromJson(content); +} + +class TombstoneContent { + String body; + String replacementRoom; + + TombstoneContent.fromJson(Map json) + : body = json.tryGet('body', ''), + replacementRoom = json.tryGet('replacement_room', ''); + + Map toJson() { + final data = {}; + data['body'] = body; + data['replacement_room'] = replacementRoom; + return data; + } +} diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart new file mode 100644 index 00000000..46b0fb3f --- /dev/null +++ b/lib/src/model/events_sync_update.dart @@ -0,0 +1,47 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'matrix_event.dart'; + +class EventsSyncUpdate { + String start; + String end; + List chunk; + + EventsSyncUpdate.fromJson(Map json) { + start = json['start']; + end = json['end']; + chunk = json['chunk'] != null + ? (json['chunk'] as List).map((i) => MatrixEvent.fromJson(i)).toList() + : null; + } + + Map toJson() { + final data = {}; + if (start != null) { + data['start'] = start; + } + if (end != null) { + data['end'] = end; + } + if (chunk != null) { + data['chunk'] = chunk.map((i) => i.toJson()).toList(); + } + return data; + } +} diff --git a/lib/src/model/filter.dart b/lib/src/model/filter.dart new file mode 100644 index 00000000..b1e18a7d --- /dev/null +++ b/lib/src/model/filter.dart @@ -0,0 +1,222 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +enum EventFormat { client, federation } + +class Filter { + RoomFilter room; + EventFilter presence; + EventFilter accountData; + EventFormat eventFormat; + List eventFields; + + Filter({ + this.room, + this.presence, + this.accountData, + this.eventFormat, + this.eventFields, + }); + + Filter.fromJson(Map json) { + room = json['room'] != null ? RoomFilter.fromJson(json['room']) : null; + presence = json['presence'] != null + ? EventFilter.fromJson(json['presence']) + : null; + accountData = json['account_data'] != null + ? EventFilter.fromJson(json['account_data']) + : null; + eventFormat = json['event_format'] != null + ? EventFormat.values.firstWhere( + (e) => e.toString().split('.').last == json['event_format']) + : null; + eventFields = json['event_fields'] != null + ? json['event_fields'].cast() + : null; + } + + Map toJson() { + final data = {}; + if (room != null) { + data['room'] = room.toJson(); + } + if (presence != null) { + data['presence'] = presence.toJson(); + } + if (eventFormat != null) { + data['event_format'] = eventFormat.toString().split('.').last; + } + if (eventFields != null) { + data['event_fields'] = eventFields; + } + if (accountData != null) { + data['account_data'] = accountData.toJson(); + } + return data; + } +} + +class RoomFilter { + List notRooms; + List rooms; + StateFilter ephemeral; + bool includeLeave; + StateFilter state; + StateFilter timeline; + StateFilter accountData; + + RoomFilter({ + this.notRooms, + this.rooms, + this.ephemeral, + this.includeLeave, + this.state, + this.timeline, + this.accountData, + }); + + RoomFilter.fromJson(Map json) { + notRooms = json['not_rooms']?.cast(); + rooms = json['rooms']?.cast(); + state = json['state'] != null ? StateFilter.fromJson(json['state']) : null; + includeLeave = json['include_leave']; + timeline = json['timeline'] != null + ? StateFilter.fromJson(json['timeline']) + : null; + ephemeral = json['ephemeral'] != null + ? StateFilter.fromJson(json['ephemeral']) + : null; + accountData = json['account_data'] != null + ? StateFilter.fromJson(json['account_data']) + : null; + } + + Map toJson() { + final data = {}; + if (notRooms != null) { + data['not_rooms'] = notRooms; + } + if (rooms != null) { + data['rooms'] = rooms; + } + if (ephemeral != null) { + data['ephemeral'] = ephemeral.toJson(); + } + if (includeLeave != null) { + data['include_leave'] = includeLeave; + } + if (state != null) { + data['state'] = state.toJson(); + } + if (timeline != null) { + data['timeline'] = timeline.toJson(); + } + if (accountData != null) { + data['account_data'] = accountData.toJson(); + } + return data; + } +} + +class EventFilter { + int limit; + List senders; + List types; + List notRooms; + List notSenders; + + EventFilter( + {this.limit, this.senders, this.types, this.notRooms, this.notSenders}); + + EventFilter.fromJson(Map json) { + limit = json['limit']; + types = json['senders']?.cast(); + types = json['types']?.cast(); + notRooms = json['not_rooms']?.cast(); + notSenders = json['not_senders']?.cast(); + } + + Map toJson() { + final data = {}; + if (limit != null) data['limit'] = limit; + if (types != null) data['types'] = types; + if (notRooms != null) data['not_rooms'] = notRooms; + if (notSenders != null) data['not_senders'] = notSenders; + return data; + } +} + +class StateFilter extends EventFilter { + List notTypes; + bool lazyLoadMembers; + bool includeRedundantMembers; + bool containsUrl; + + StateFilter({ + this.notTypes, + this.lazyLoadMembers, + this.includeRedundantMembers, + this.containsUrl, + int limit, + List senders, + List types, + List notRooms, + List notSenders, + }) : super( + limit: limit, + senders: senders, + types: types, + notRooms: notRooms, + notSenders: notSenders, + ); + + StateFilter.fromJson(Map json) { + final eventFilter = EventFilter.fromJson(json); + limit = eventFilter.limit; + senders = eventFilter.senders; + types = eventFilter.types; + notRooms = eventFilter.notRooms; + notSenders = eventFilter.notSenders; + + notTypes = json['not_types']?.cast(); + lazyLoadMembers = json['lazy_load_members']; + includeRedundantMembers = json['include_redundant_members']; + containsUrl = json['contains_url']; + } + + @override + Map toJson() { + final data = super.toJson(); + if (limit != null) { + data['limit'] = limit; + } + if (notTypes != null) { + data['not_types'] = notTypes; + } + if (lazyLoadMembers != null) { + data['lazy_load_members'] = notTypes; + } + if (includeRedundantMembers != null) { + data['include_redundant_members'] = notTypes; + } + if (containsUrl != null) { + data['contains_url'] = notTypes; + } + return data; + } +} diff --git a/lib/src/model/keys_query_response.dart b/lib/src/model/keys_query_response.dart new file mode 100644 index 00000000..b368b4f1 --- /dev/null +++ b/lib/src/model/keys_query_response.dart @@ -0,0 +1,117 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'matrix_keys.dart'; + +class KeysQueryResponse { + Map failures; + Map> deviceKeys; + Map masterKeys; + Map selfSigningKeys; + Map userSigningKeys; + + KeysQueryResponse.fromJson(Map json) { + failures = json['failures'] != null + ? Map.from(json['failures']) + : null; + deviceKeys = json['device_keys'] != null + ? (json['device_keys'] as Map).map( + (k, v) => MapEntry( + k, + (v as Map).map( + (k, v) => MapEntry( + k, + MatrixDeviceKeys.fromJson(v), + ), + ), + ), + ) + : null; + masterKeys = json['master_keys'] != null + ? (json['master_keys'] as Map).map( + (k, v) => MapEntry( + k, + MatrixCrossSigningKey.fromJson(v), + ), + ) + : null; + + selfSigningKeys = json['self_signing_keys'] != null + ? (json['self_signing_keys'] as Map).map( + (k, v) => MapEntry( + k, + MatrixCrossSigningKey.fromJson(v), + ), + ) + : null; + + userSigningKeys = json['user_signing_keys'] != null + ? (json['user_signing_keys'] as Map).map( + (k, v) => MapEntry( + k, + MatrixCrossSigningKey.fromJson(v), + ), + ) + : null; + } + + Map toJson() { + final data = {}; + if (failures != null) { + data['failures'] = failures; + } + if (deviceKeys != null) { + data['device_keys'] = deviceKeys.map( + (k, v) => MapEntry( + k, + v.map( + (k, v) => MapEntry( + k, + v.toJson(), + ), + ), + ), + ); + } + if (masterKeys != null) { + data['master_keys'] = masterKeys.map( + (k, v) => MapEntry( + k, + v.toJson(), + ), + ); + } + if (selfSigningKeys != null) { + data['self_signing_keys'] = selfSigningKeys.map( + (k, v) => MapEntry( + k, + v.toJson(), + ), + ); + } + if (userSigningKeys != null) { + data['user_signing_keys'] = userSigningKeys.map( + (k, v) => MapEntry( + k, + v.toJson(), + ), + ); + } + return data; + } +} diff --git a/lib/src/model/login_response.dart b/lib/src/model/login_response.dart new file mode 100644 index 00000000..a29627ad --- /dev/null +++ b/lib/src/model/login_response.dart @@ -0,0 +1,47 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'well_known_informations.dart'; + +class LoginResponse { + String userId; + String accessToken; + String deviceId; + WellKnownInformations wellKnownInformations; + + LoginResponse.fromJson(Map json) { + userId = json['user_id']; + accessToken = json['access_token']; + deviceId = json['device_id']; + if (json['well_known'] is Map) { + wellKnownInformations = + WellKnownInformations.fromJson(json['well_known']); + } + } + + Map toJson() { + final data = {}; + if (userId != null) data['user_id'] = userId; + if (accessToken != null) data['access_token'] = accessToken; + if (deviceId != null) data['device_id'] = deviceId; + if (wellKnownInformations != null) { + data['well_known'] = wellKnownInformations.toJson(); + } + return data; + } +} diff --git a/lib/src/model/login_types.dart b/lib/src/model/login_types.dart new file mode 100644 index 00000000..5cb67d22 --- /dev/null +++ b/lib/src/model/login_types.dart @@ -0,0 +1,52 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class LoginTypes { + List flows; + + LoginTypes.fromJson(Map json) { + if (json['flows'] != null) { + flows = []; + json['flows'].forEach((v) { + flows.add(Flows.fromJson(v)); + }); + } + } + + Map toJson() { + final data = {}; + if (flows != null) { + data['flows'] = flows.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Flows { + String type; + + Flows.fromJson(Map json) { + type = json['type']; + } + + Map toJson() { + final data = {}; + data['type'] = type; + return data; + } +} diff --git a/lib/src/model/marked_unread.dart b/lib/src/model/marked_unread.dart new file mode 100644 index 00000000..c3223c78 --- /dev/null +++ b/lib/src/model/marked_unread.dart @@ -0,0 +1,43 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +mixin EventType { + static const String MarkedUnread = 'com.famedly.marked_unread'; +} + +class MarkedUnread { + bool unread; + + MarkedUnread(this.unread); + + MarkedUnread.fromJson(Map json) { + if (!(json['unread'] is bool)) { + unread = false; + } else { + unread = json['unread']; + } + } + + Map toJson() { + final data = {}; + if (unread != null) { + data['unread'] = unread; + } + return data; + } +} diff --git a/lib/src/model/matrix_connection_exception.dart b/lib/src/model/matrix_connection_exception.dart new file mode 100644 index 00000000..b45192e0 --- /dev/null +++ b/lib/src/model/matrix_connection_exception.dart @@ -0,0 +1,26 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class MatrixConnectionException implements Exception { + final dynamic original; + final StackTrace stackTrace; + MatrixConnectionException(this.original, this.stackTrace); + + @override + String toString() => original.toString(); +} diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart new file mode 100644 index 00000000..2f5f35f0 --- /dev/null +++ b/lib/src/model/matrix_event.dart @@ -0,0 +1,72 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'stripped_state_event.dart'; + +class MatrixEvent extends StrippedStateEvent { + String eventId; + String roomId; + DateTime originServerTs; + Map unsigned; + Map prevContent; + String redacts; + + MatrixEvent(); + + MatrixEvent.fromJson(Map json) { + final strippedStateEvent = StrippedStateEvent.fromJson(json); + content = strippedStateEvent.content; + type = strippedStateEvent.type; + senderId = strippedStateEvent.senderId; + stateKey = strippedStateEvent.stateKey; + eventId = json['event_id']; + roomId = json['room_id']; + originServerTs = + DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']); + unsigned = json['unsigned'] != null + ? Map.from(json['unsigned']) + : null; + prevContent = json['prev_content'] != null + ? Map.from(json['prev_content']) + : null; + redacts = json['redacts']; + } + + @override + Map toJson() { + final data = super.toJson(); + data['event_id'] = eventId; + data['origin_server_ts'] = originServerTs.millisecondsSinceEpoch; + if (unsigned != null) { + data['unsigned'] = unsigned; + } + if (prevContent != null) { + data['prev_content'] = prevContent; + } + if (roomId != null) { + data['room_id'] = roomId; + } + if (data['state_key'] == null) { + data.remove('state_key'); + } + if (redacts != null) { + data['redacts'] = redacts; + } + return data; + } +} diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart new file mode 100644 index 00000000..fa292c9c --- /dev/null +++ b/lib/src/model/matrix_exception.dart @@ -0,0 +1,110 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'dart:convert'; + +import 'package:http/http.dart' as http; + +enum MatrixError { + M_UNKNOWN, + M_UNKNOWN_TOKEN, + M_NOT_FOUND, + M_FORBIDDEN, + M_LIMIT_EXCEEDED, + M_USER_IN_USE, + M_THREEPID_IN_USE, + M_THREEPID_DENIED, + M_THREEPID_NOT_FOUND, + M_THREEPID_AUTH_FAILED, + M_TOO_LARGE, + M_MISSING_PARAM, + M_UNSUPPORTED_ROOM_VERSION, + M_UNRECOGNIZED, +} + +/// Represents a special response from the Homeserver for errors. +class MatrixException implements Exception { + final Map raw; + + /// The unique identifier for this error. + String get errcode => + raw['errcode'] ?? + (requireAdditionalAuthentication ? 'M_FORBIDDEN' : 'M_UNKNOWN'); + + /// A human readable error description. + String get errorMessage => + raw['error'] ?? + (requireAdditionalAuthentication + ? 'Require additional authentication' + : 'Unknown error'); + + /// The frozen request which triggered this Error + http.Response response; + + MatrixException(this.response) : raw = json.decode(response.body); + MatrixException.fromJson(Map content) : raw = content; + + @override + String toString() => '$errcode: $errorMessage'; + + /// Returns the [ResponseError]. Is ResponseError.NONE if there wasn't an error. + MatrixError get error => MatrixError.values.firstWhere( + (e) => e.toString() == 'MatrixError.${(raw["errcode"] ?? "")}', + orElse: () => MatrixError.M_UNKNOWN); + + int get retryAfterMs => raw['retry_after_ms']; + + /// This is a session identifier that the client must pass back to the homeserver, if one is provided, + /// in subsequent attempts to authenticate in the same API call. + String get session => raw['session']; + + /// Returns true if the server requires additional authentication. + bool get requireAdditionalAuthentication => response != null + ? response.statusCode == 401 + : authenticationFlows != null; + + /// For each endpoint, a server offers one or more 'flows' that the client can use + /// to authenticate itself. Each flow comprises a series of stages. If this request + /// doesn't need additional authentication, then this is null. + List get authenticationFlows { + if (!raw.containsKey('flows') || !(raw['flows'] is List)) return null; + var flows = []; + for (Map flow in raw['flows']) { + if (flow['stages'] is List) { + flows.add(AuthenticationFlow(List.from(flow['stages']))); + } + } + return flows; + } + + /// This section contains any information that the client will need to know in order to use a given type + /// of authentication. For each authentication type presented, that type may be present as a key in this + /// dictionary. For example, the public part of an OAuth client ID could be given here. + Map get authenticationParams => raw['params']; + + /// Returns the list of already completed authentication flows from previous requests. + List get completedAuthenticationFlows => + List.from(raw['completed'] ?? []); +} + +/// For each endpoint, a server offers one or more 'flows' that the client can use +/// to authenticate itself. Each flow comprises a series of stages +class AuthenticationFlow { + final List stages; + const AuthenticationFlow(this.stages); +} diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart new file mode 100644 index 00000000..c0f00386 --- /dev/null +++ b/lib/src/model/matrix_keys.dart @@ -0,0 +1,115 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class MatrixSignableKey { + String userId; + String identifier; + Map keys; + Map> signatures; + Map unsigned; + + MatrixSignableKey(this.userId, this.identifier, this.keys, this.signatures, + {this.unsigned}); + + // This object is used for signing so we need the raw json too + Map _json; + + MatrixSignableKey.fromJson(Map json) { + _json = json; + userId = json['user_id']; + keys = Map.from(json['keys']); + signatures = json['signatures'] is Map + ? Map>.from((json['signatures'] as Map) + .map((k, v) => MapEntry(k, Map.from(v)))) + : null; + unsigned = json['unsigned'] is Map + ? Map.from(json['unsigned']) + : null; + } + + Map toJson() { + final data = _json ?? {}; + data['user_id'] = userId; + data['keys'] = keys; + + if (signatures != null) { + data['signatures'] = signatures; + } + if (unsigned != null) { + data['unsigned'] = unsigned; + } + return data; + } +} + +class MatrixCrossSigningKey extends MatrixSignableKey { + List usage; + String get publicKey => identifier; + + MatrixCrossSigningKey( + String userId, + this.usage, + Map keys, + Map> signatures, { + Map unsigned, + }) : super(userId, keys?.values?.first, keys, signatures, unsigned: unsigned); + + @override + MatrixCrossSigningKey.fromJson(Map json) + : super.fromJson(json) { + usage = List.from(json['usage']); + identifier = keys?.values?.first; + } + + @override + Map toJson() { + final data = super.toJson(); + data['usage'] = usage; + return data; + } +} + +class MatrixDeviceKeys extends MatrixSignableKey { + String get deviceId => identifier; + List algorithms; + String get deviceDisplayName => + unsigned != null ? unsigned['device_display_name'] : null; + + MatrixDeviceKeys( + String userId, + String deviceId, + this.algorithms, + Map keys, + Map> signatures, { + Map unsigned, + }) : super(userId, deviceId, keys, signatures, unsigned: unsigned); + + @override + MatrixDeviceKeys.fromJson(Map json) : super.fromJson(json) { + identifier = json['device_id']; + algorithms = json['algorithms'].cast(); + } + + @override + Map toJson() { + final data = super.toJson(); + data['device_id'] = deviceId; + data['algorithms'] = algorithms; + return data; + } +} diff --git a/lib/src/model/message_types.dart b/lib/src/model/message_types.dart new file mode 100644 index 00000000..90fe2d08 --- /dev/null +++ b/lib/src/model/message_types.dart @@ -0,0 +1,31 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +abstract class MessageTypes { + static const String Text = 'm.text'; + static const String Emote = 'm.emote'; + static const String Notice = 'm.notice'; + static const String Image = 'm.image'; + static const String Video = 'm.video'; + static const String Audio = 'm.audio'; + static const String File = 'm.file'; + static const String Location = 'm.location'; + static const String Sticker = 'm.sticker'; + static const String BadEncrypted = 'm.bad.encrypted'; + static const String None = 'm.none'; +} diff --git a/lib/src/model/notifications_query_response.dart b/lib/src/model/notifications_query_response.dart new file mode 100644 index 00000000..f9eff6b9 --- /dev/null +++ b/lib/src/model/notifications_query_response.dart @@ -0,0 +1,72 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'matrix_event.dart'; + +class NotificationsQueryResponse { + String nextToken; + List notifications; + + NotificationsQueryResponse.fromJson(Map json) { + nextToken = json['next_token']; + notifications = []; + json['notifications'].forEach((v) { + notifications.add(Notification.fromJson(v)); + }); + } + + Map toJson() { + final data = {}; + if (nextToken != null) { + data['next_token'] = nextToken; + } + data['notifications'] = notifications.map((v) => v.toJson()).toList(); + return data; + } +} + +class Notification { + List actions; + String profileTag; + bool read; + String roomId; + int ts; + MatrixEvent event; + + Notification.fromJson(Map json) { + actions = json['actions'].cast(); + profileTag = json['profile_tag']; + read = json['read']; + roomId = json['room_id']; + ts = json['ts']; + event = MatrixEvent.fromJson(json['event']); + } + + Map toJson() { + final data = {}; + data['actions'] = actions; + if (profileTag != null) { + data['profile_tag'] = profileTag; + } + data['read'] = read; + data['room_id'] = roomId; + data['ts'] = ts; + data['event'] = event.toJson(); + return data; + } +} diff --git a/lib/src/model/one_time_keys_claim_response.dart b/lib/src/model/one_time_keys_claim_response.dart new file mode 100644 index 00000000..7834211c --- /dev/null +++ b/lib/src/model/one_time_keys_claim_response.dart @@ -0,0 +1,38 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class OneTimeKeysClaimResponse { + Map failures; + Map> oneTimeKeys; + + OneTimeKeysClaimResponse.fromJson(Map json) { + failures = Map.from(json['failures'] ?? {}); + oneTimeKeys = Map>.from(json['one_time_keys']); + } + + Map toJson() { + final data = {}; + if (failures != null) { + data['failures'] = failures; + } + if (oneTimeKeys != null) { + data['one_time_keys'] = oneTimeKeys; + } + return data; + } +} diff --git a/lib/src/model/open_graph_data.dart b/lib/src/model/open_graph_data.dart new file mode 100644 index 00000000..d2d8eb60 --- /dev/null +++ b/lib/src/model/open_graph_data.dart @@ -0,0 +1,63 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class OpenGraphData { + String ogTitle; + String ogDescription; + String ogImage; + String ogImageType; + int ogImageHeight; + int ogImageWidth; + int matrixImageSize; + + OpenGraphData.fromJson(Map json) { + ogTitle = json['og:title']; + ogDescription = json['og:description']; + ogImage = json['og:image']; + ogImageType = json['og:image:type']; + ogImageHeight = json['og:image:height']; + ogImageWidth = json['og:image:width']; + matrixImageSize = json['matrix:image:size']; + } + + Map toJson() { + final data = {}; + if (ogTitle != null) { + data['og:title'] = ogTitle; + } + if (ogDescription != null) { + data['og:description'] = ogDescription; + } + if (ogImage != null) { + data['og:image'] = ogImage; + } + if (ogImageType != null) { + data['og:image:type'] = ogImageType; + } + if (ogImageHeight != null) { + data['og:image:height'] = ogImageHeight; + } + if (ogImageWidth != null) { + data['og:image:width'] = ogImageWidth; + } + if (matrixImageSize != null) { + data['matrix:image:size'] = matrixImageSize; + } + return data; + } +} diff --git a/lib/src/model/open_id_credentials.dart b/lib/src/model/open_id_credentials.dart new file mode 100644 index 00000000..1d2902bd --- /dev/null +++ b/lib/src/model/open_id_credentials.dart @@ -0,0 +1,40 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class OpenIdCredentials { + String accessToken; + String tokenType; + String matrixServerName; + double expiresIn; + + OpenIdCredentials.fromJson(Map json) { + accessToken = json['access_token']; + tokenType = json['token_type']; + matrixServerName = json['matrix_server_name']; + expiresIn = json['expires_in']; + } + + Map toJson() { + final data = {}; + data['access_token'] = accessToken; + data['token_type'] = tokenType; + data['matrix_server_name'] = matrixServerName; + data['expires_in'] = expiresIn; + return data; + } +} diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart new file mode 100644 index 00000000..c8044063 --- /dev/null +++ b/lib/src/model/presence.dart @@ -0,0 +1,32 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'basic_event_with_sender.dart'; +import 'presence_content.dart'; + +class Presence extends BasicEventWithSender { + PresenceContent presence; + + Presence.fromJson(Map json) { + final basicEvent = BasicEventWithSender.fromJson(json); + type = basicEvent.type; + content = basicEvent.content; + senderId = basicEvent.senderId; + presence = PresenceContent.fromJson(content); + } +} diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart new file mode 100644 index 00000000..df9d2f08 --- /dev/null +++ b/lib/src/model/presence_content.dart @@ -0,0 +1,49 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +enum PresenceType { online, offline, unavailable } + +class PresenceContent { + PresenceType presence; + int lastActiveAgo; + String statusMsg; + bool currentlyActive; + + PresenceContent.fromJson(Map json) { + presence = PresenceType.values + .firstWhere((p) => p.toString().split('.').last == json['presence']); + lastActiveAgo = json['last_active_ago']; + statusMsg = json['status_msg']; + currentlyActive = json['currently_active']; + } + + Map toJson() { + final data = {}; + data['presence'] = presence.toString().split('.').last; + if (lastActiveAgo != null) { + data['last_active_ago'] = lastActiveAgo; + } + if (statusMsg != null) { + data['status_msg'] = statusMsg; + } + if (currentlyActive != null) { + data['currently_active'] = currentlyActive; + } + return data; + } +} diff --git a/lib/src/model/profile.dart b/lib/src/model/profile.dart new file mode 100644 index 00000000..37eace57 --- /dev/null +++ b/lib/src/model/profile.dart @@ -0,0 +1,44 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class Profile { + /// The user's avatar URL if they have set one, otherwise null. + Uri avatarUrl; + + /// The user's display name if they have set one, otherwise null. + String displayname; + + /// The matrix ID of this user. May be omitted. + String userId; + + Map additionalContent; + + Profile(this.displayname, this.avatarUrl, + {this.additionalContent = const {}}); + + Profile.fromJson(Map json) + : avatarUrl = + json['avatar_url'] != null ? Uri.parse(json['avatar_url']) : null, + displayname = json['display_name'] ?? json['displayname'], + userId = json['user_id'], + additionalContent = json; + + Map toJson() { + return additionalContent; + } +} diff --git a/lib/src/model/public_rooms_response.dart b/lib/src/model/public_rooms_response.dart new file mode 100644 index 00000000..f227dfb7 --- /dev/null +++ b/lib/src/model/public_rooms_response.dart @@ -0,0 +1,97 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class PublicRoomsResponse { + List chunk; + String nextBatch; + String prevBatch; + int totalRoomCountEstimate; + + PublicRoomsResponse.fromJson(Map json) { + chunk = []; + json['chunk'].forEach((v) { + chunk.add(PublicRoom.fromJson(v)); + }); + nextBatch = json['next_batch']; + prevBatch = json['prev_batch']; + totalRoomCountEstimate = json['total_room_count_estimate']; + } + + Map toJson() { + final data = {}; + data['chunk'] = chunk.map((v) => v.toJson()).toList(); + if (nextBatch != null) { + data['next_batch'] = nextBatch; + } + if (prevBatch != null) { + data['prev_batch'] = prevBatch; + } + if (totalRoomCountEstimate != null) { + data['total_room_count_estimate'] = totalRoomCountEstimate; + } + return data; + } +} + +class PublicRoom { + List aliases; + String avatarUrl; + bool guestCanJoin; + String name; + int numJoinedMembers; + String roomId; + String topic; + bool worldReadable; + String canonicalAlias; + + PublicRoom.fromJson(Map json) { + aliases = json['aliases']?.cast(); + avatarUrl = json['avatar_url']; + guestCanJoin = json['guest_can_join']; + canonicalAlias = json['canonical_alias']; + name = json['name']; + numJoinedMembers = json['num_joined_members']; + roomId = json['room_id']; + topic = json['topic']; + worldReadable = json['world_readable']; + } + + Map toJson() { + final data = {}; + if (aliases != null) { + data['aliases'] = aliases; + } + if (canonicalAlias != null) { + data['canonical_alias'] = canonicalAlias; + } + if (avatarUrl != null) { + data['avatar_url'] = avatarUrl; + } + data['guest_can_join'] = guestCanJoin; + if (name != null) { + data['name'] = name; + } + data['num_joined_members'] = numJoinedMembers; + data['room_id'] = roomId; + if (topic != null) { + data['topic'] = topic; + } + data['world_readable'] = worldReadable; + return data; + } +} diff --git a/lib/src/model/push_rule_set.dart b/lib/src/model/push_rule_set.dart new file mode 100644 index 00000000..2c9682b5 --- /dev/null +++ b/lib/src/model/push_rule_set.dart @@ -0,0 +1,143 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +enum PushRuleKind { content, override, room, sender, underride } +enum PushRuleAction { notify, dont_notify, coalesce, set_tweak } + +class PushRuleSet { + List content; + List override; + List room; + List sender; + List underride; + + PushRuleSet.fromJson(Map json) { + if (json['content'] != null) { + content = + (json['content'] as List).map((i) => PushRule.fromJson(i)).toList(); + } + if (json['override'] != null) { + override = + (json['override'] as List).map((i) => PushRule.fromJson(i)).toList(); + } + if (json['room'] != null) { + room = (json['room'] as List).map((i) => PushRule.fromJson(i)).toList(); + } + if (json['sender'] != null) { + sender = + (json['sender'] as List).map((i) => PushRule.fromJson(i)).toList(); + } + if (json['underride'] != null) { + underride = + (json['underride'] as List).map((i) => PushRule.fromJson(i)).toList(); + } + } + + Map toJson() { + final data = {}; + if (content != null) { + data['content'] = content.map((v) => v.toJson()).toList(); + } + if (override != null) { + data['override'] = override.map((v) => v.toJson()).toList(); + } + if (room != null) { + data['room'] = room.map((v) => v.toJson()).toList(); + } + if (sender != null) { + data['sender'] = sender.map((v) => v.toJson()).toList(); + } + if (underride != null) { + data['underride'] = underride.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class PushRule { + List actions; + List conditions; + bool isDefault; + bool enabled; + String pattern; + String ruleId; + + PushRule.fromJson(Map json) { + actions = json['actions']; + isDefault = json['default']; + enabled = json['enabled']; + pattern = json['pattern']; + ruleId = json['rule_id']; + conditions = json['conditions'] != null + ? (json['conditions'] as List) + .map((i) => PushConditions.fromJson(i)) + .toList() + : null; + } + + Map toJson() { + final data = {}; + data['actions'] = actions; + data['default'] = isDefault; + data['enabled'] = enabled; + if (pattern != null) { + data['pattern'] = pattern; + } + if (conditions != null) { + data['conditions'] = conditions.map((i) => i.toJson()).toList(); + } + data['rule_id'] = ruleId; + return data; + } +} + +class PushConditions { + String key; + String kind; + String pattern; + String isOperator; + + PushConditions( + this.kind, { + this.key, + this.pattern, + this.isOperator, + }); + + PushConditions.fromJson(Map json) { + key = json['key']; + kind = json['kind']; + pattern = json['pattern']; + isOperator = json['is']; + } + + Map toJson() { + final data = {}; + if (key != null) { + data['key'] = key; + } + data['kind'] = kind; + if (pattern != null) { + data['pattern'] = pattern; + } + if (isOperator != null) { + data['is'] = isOperator; + } + return data; + } +} diff --git a/lib/src/model/pusher.dart b/lib/src/model/pusher.dart new file mode 100644 index 00000000..00bc2803 --- /dev/null +++ b/lib/src/model/pusher.dart @@ -0,0 +1,93 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class Pusher { + String pushkey; + String kind; + String appId; + String appDisplayName; + String deviceDisplayName; + String profileTag; + String lang; + PusherData data; + + Pusher( + this.pushkey, + this.appId, + this.appDisplayName, + this.deviceDisplayName, + this.lang, + this.data, { + this.profileTag, + this.kind, + }); + + Pusher.fromJson(Map json) { + pushkey = json['pushkey']; + kind = json['kind']; + appId = json['app_id']; + appDisplayName = json['app_display_name']; + deviceDisplayName = json['device_display_name']; + profileTag = json['profile_tag']; + lang = json['lang']; + data = PusherData.fromJson(json['data']); + } + + Map toJson() { + final data = {}; + data['pushkey'] = pushkey; + data['kind'] = kind; + data['app_id'] = appId; + data['app_display_name'] = appDisplayName; + data['device_display_name'] = deviceDisplayName; + if (profileTag != null) { + data['profile_tag'] = profileTag; + } + data['lang'] = lang; + data['data'] = this.data.toJson(); + return data; + } +} + +class PusherData { + Uri url; + String format; + + PusherData({ + this.url, + this.format, + }); + + PusherData.fromJson(Map json) { + if (json.containsKey('url')) { + url = Uri.parse(json['url']); + } + format = json['format']; + } + + Map toJson() { + final data = {}; + if (url != null) { + data['url'] = url.toString(); + } + if (format != null) { + data['format'] = format; + } + return data; + } +} diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart new file mode 100644 index 00000000..ee264be6 --- /dev/null +++ b/lib/src/model/request_token_response.dart @@ -0,0 +1,34 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class RequestTokenResponse { + String sid; + String submitUrl; + + RequestTokenResponse.fromJson(Map json) { + sid = json['sid']; + submitUrl = json['submit_url']; + } + + Map toJson() { + final data = {}; + data['sid'] = sid; + data['submit_url'] = submitUrl; + return data; + } +} diff --git a/lib/src/model/room_alias_informations.dart b/lib/src/model/room_alias_informations.dart new file mode 100644 index 00000000..d6b81640 --- /dev/null +++ b/lib/src/model/room_alias_informations.dart @@ -0,0 +1,34 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class RoomAliasInformations { + String roomId; + List servers; + + RoomAliasInformations.fromJson(Map json) { + roomId = json['room_id']; + servers = json['servers'].cast(); + } + + Map toJson() { + final data = {}; + data['room_id'] = roomId; + data['servers'] = servers; + return data; + } +} diff --git a/lib/src/model/room_keys_info.dart b/lib/src/model/room_keys_info.dart new file mode 100644 index 00000000..2ac7ac3c --- /dev/null +++ b/lib/src/model/room_keys_info.dart @@ -0,0 +1,69 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'algorithm_types.dart'; + +enum RoomKeysAlgorithmType { v1Curve25519AesSha2 } + +extension RoomKeysAlgorithmTypeExtension on RoomKeysAlgorithmType { + String get algorithmString { + switch (this) { + case RoomKeysAlgorithmType.v1Curve25519AesSha2: + return AlgorithmTypes.megolmBackupV1Curve25519AesSha2; + default: + return null; + } + } + + static RoomKeysAlgorithmType fromAlgorithmString(String s) { + switch (s) { + case AlgorithmTypes.megolmBackupV1Curve25519AesSha2: + return RoomKeysAlgorithmType.v1Curve25519AesSha2; + default: + return null; + } + } +} + +class RoomKeysVersionResponse { + RoomKeysAlgorithmType algorithm; + Map authData; + int count; + String etag; + String version; + + RoomKeysVersionResponse.fromJson(Map json) { + algorithm = + RoomKeysAlgorithmTypeExtension.fromAlgorithmString(json['algorithm']); + authData = json['auth_data']; + count = json['count']; + etag = + json['etag'].toString(); // synapse replies an int but docs say string? + version = json['version']; + } + + Map toJson() { + final data = {}; + data['algorithm'] = algorithm?.algorithmString; + data['auth_data'] = authData; + data['count'] = count; + data['etag'] = etag; + data['version'] = version; + return data; + } +} diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart new file mode 100644 index 00000000..69870665 --- /dev/null +++ b/lib/src/model/room_keys_keys.dart @@ -0,0 +1,101 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class RoomKeysSingleKey { + int firstMessageIndex; + int forwardedCount; + bool isVerified; + Map sessionData; + + RoomKeysSingleKey( + {this.firstMessageIndex, + this.forwardedCount, + this.isVerified, + this.sessionData}); + + RoomKeysSingleKey.fromJson(Map json) { + firstMessageIndex = json['first_message_index']; + forwardedCount = json['forwarded_count']; + isVerified = json['is_verified']; + sessionData = json['session_data']; + } + + Map toJson() { + final data = {}; + data['first_message_index'] = firstMessageIndex; + data['forwarded_count'] = forwardedCount; + data['is_verified'] = isVerified; + data['session_data'] = sessionData; + return data; + } +} + +class RoomKeysRoom { + Map sessions; + + RoomKeysRoom({this.sessions}) { + sessions ??= {}; + } + + RoomKeysRoom.fromJson(Map json) { + sessions = (json['sessions'] as Map) + .map((k, v) => MapEntry(k, RoomKeysSingleKey.fromJson(v))); + } + + Map toJson() { + final data = {}; + data['sessions'] = sessions.map((k, v) => MapEntry(k, v.toJson())); + return data; + } +} + +class RoomKeys { + Map rooms; + + RoomKeys({this.rooms}) { + rooms ??= {}; + } + + RoomKeys.fromJson(Map json) { + rooms = (json['rooms'] as Map) + .map((k, v) => MapEntry(k, RoomKeysRoom.fromJson(v))); + } + + Map toJson() { + final data = {}; + data['rooms'] = rooms.map((k, v) => MapEntry(k, v.toJson())); + return data; + } +} + +class RoomKeysUpdateResponse { + String etag; + int count; + + RoomKeysUpdateResponse.fromJson(Map json) { + etag = json['etag']; // synapse replies an int but docs say string? + count = json['count']; + } + + Map toJson() { + final data = {}; + data['etag'] = etag; + data['count'] = count; + return data; + } +} diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart new file mode 100644 index 00000000..67b6a8f3 --- /dev/null +++ b/lib/src/model/room_summary.dart @@ -0,0 +1,42 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class RoomSummary { + List mHeroes; + int mJoinedMemberCount; + int mInvitedMemberCount; + RoomSummary.fromJson(Map json) { + mHeroes = + json['m.heroes'] != null ? List.from(json['m.heroes']) : null; + mJoinedMemberCount = json['m.joined_member_count']; + mInvitedMemberCount = json['m.invited_member_count']; + } + Map toJson() { + final data = {}; + if (mHeroes != null) { + data['m.heroes'] = mHeroes; + } + if (mJoinedMemberCount != null) { + data['m.joined_member_count'] = mJoinedMemberCount; + } + if (mInvitedMemberCount != null) { + data['m.invited_member_count'] = mInvitedMemberCount; + } + return data; + } +} diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart new file mode 100644 index 00000000..0e449e9d --- /dev/null +++ b/lib/src/model/server_capabilities.dart @@ -0,0 +1,89 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +enum RoomVersionStability { stable, unstable } + +class ServerCapabilities { + MChangePassword mChangePassword; + MRoomVersions mRoomVersions; + Map customCapabilities; + + ServerCapabilities.fromJson(Map json) { + mChangePassword = json['m.change_password'] != null + ? MChangePassword.fromJson(json['m.change_password']) + : null; + mRoomVersions = json['m.room_versions'] != null + ? MRoomVersions.fromJson(json['m.room_versions']) + : null; + customCapabilities = Map.from(json); + customCapabilities.remove('m.change_password'); + customCapabilities.remove('m.room_versions'); + } + + Map toJson() { + final data = {}; + if (mChangePassword != null) { + data['m.change_password'] = mChangePassword.toJson(); + } + if (mRoomVersions != null) { + data['m.room_versions'] = mRoomVersions.toJson(); + } + for (final entry in customCapabilities.entries) { + data[entry.key] = entry.value; + } + return data; + } +} + +class MChangePassword { + bool enabled; + + MChangePassword.fromJson(Map json) { + enabled = json['enabled']; + } + + Map toJson() { + final data = {}; + data['enabled'] = enabled; + return data; + } +} + +class MRoomVersions { + String defaultVersion; + Map available; + + MRoomVersions.fromJson(Map json) { + defaultVersion = json['default']; + available = (json['available'] as Map).map( + (k, v) => MapEntry( + k, + RoomVersionStability.values + .firstWhere((r) => r.toString().split('.').last == v), + ), + ); + } + + Map toJson() { + final data = {}; + data['default'] = defaultVersion; + data['available'] = available.map( + (k, v) => MapEntry(k, v.toString().split('.').last)); + return data; + } +} diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart new file mode 100644 index 00000000..29c0740a --- /dev/null +++ b/lib/src/model/stripped_state_event.dart @@ -0,0 +1,39 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'basic_event_with_sender.dart'; + +class StrippedStateEvent extends BasicEventWithSender { + String stateKey; + + StrippedStateEvent(); + StrippedStateEvent.fromJson(Map json) { + final basicEvent = BasicEventWithSender.fromJson(json); + content = basicEvent.content; + type = basicEvent.type; + senderId = basicEvent.senderId; + stateKey = json['state_key']; + } + + @override + Map toJson() { + final data = super.toJson(); + data['state_key'] = stateKey; + return data; + } +} diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart new file mode 100644 index 00000000..736b7d6d --- /dev/null +++ b/lib/src/model/supported_protocol.dart @@ -0,0 +1,92 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class SupportedProtocol { + List userFields; + List locationFields; + String icon; + Map fieldTypes; + List instances; + + SupportedProtocol.fromJson(Map json) { + userFields = json['user_fields'].cast(); + locationFields = json['location_fields'].cast(); + icon = json['icon']; + fieldTypes = (json['field_types'] as Map) + .map((k, v) => MapEntry(k, ProtocolFieldType.fromJson(v))); + instances = []; + json['instances'].forEach((v) { + instances.add(ProtocolInstance.fromJson(v)); + }); + } + + Map toJson() { + final data = {}; + data['user_fields'] = userFields; + data['location_fields'] = locationFields; + data['icon'] = icon; + data['field_types'] = fieldTypes.map((k, v) => MapEntry(k, v.toJson())); + + data['instances'] = instances.map((v) => v.toJson()).toList(); + + return data; + } +} + +class ProtocolFieldType { + String regexp; + String placeholder; + + ProtocolFieldType.fromJson(Map json) { + regexp = json['regexp']; + placeholder = json['placeholder']; + } + + Map toJson() { + final data = {}; + data['regexp'] = regexp; + data['placeholder'] = placeholder; + return data; + } +} + +class ProtocolInstance { + String networkId; + String desc; + String icon; + dynamic fields; + + ProtocolInstance.fromJson(Map json) { + networkId = json['network_id']; + desc = json['desc']; + icon = json['icon']; + fields = json['fields']; + } + + Map toJson() { + final data = {}; + data['network_id'] = networkId; + data['desc'] = desc; + if (icon != null) { + data['icon'] = icon; + } + data['fields'] = fields; + + return data; + } +} diff --git a/lib/src/model/supported_versions.dart b/lib/src/model/supported_versions.dart new file mode 100644 index 00000000..33ab8c49 --- /dev/null +++ b/lib/src/model/supported_versions.dart @@ -0,0 +1,36 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class SupportedVersions { + List versions; + Map unstableFeatures; + + SupportedVersions.fromJson(Map json) { + versions = json['versions'].cast(); + unstableFeatures = Map.from(json['unstable_features'] ?? {}); + } + + Map toJson() { + final data = {}; + data['versions'] = versions; + if (unstableFeatures != null) { + data['unstable_features'] = unstableFeatures; + } + return data; + } +} diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart new file mode 100644 index 00000000..c36c09e1 --- /dev/null +++ b/lib/src/model/sync_update.dart @@ -0,0 +1,333 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'basic_event.dart'; +import 'basic_event_with_sender.dart'; +import 'basic_room_event.dart'; +import 'matrix_event.dart'; +import 'presence.dart'; +import 'room_summary.dart'; +import 'stripped_state_event.dart'; + +class SyncUpdate { + String nextBatch; + RoomsUpdate rooms; + List presence; + List accountData; + List toDevice; + DeviceListsUpdate deviceLists; + Map deviceOneTimeKeysCount; + + SyncUpdate(); + + SyncUpdate.fromJson(Map json) { + nextBatch = json['next_batch']; + rooms = json['rooms'] != null ? RoomsUpdate.fromJson(json['rooms']) : null; + presence = (json['presence'] != null && json['presence']['events'] != null) + ? (json['presence']['events'] as List) + .map((i) => Presence.fromJson(i)) + .toList() + : null; + accountData = + (json['account_data'] != null && json['account_data']['events'] != null) + ? (json['account_data']['events'] as List) + .map((i) => BasicEvent.fromJson(i)) + .toList() + : null; + toDevice = + (json['to_device'] != null && json['to_device']['events'] != null) + ? (json['to_device']['events'] as List) + .map((i) => BasicEventWithSender.fromJson(i)) + .toList() + : null; + deviceLists = json['device_lists'] != null + ? DeviceListsUpdate.fromJson(json['device_lists']) + : null; + deviceOneTimeKeysCount = json['device_one_time_keys_count'] != null + ? Map.from(json['device_one_time_keys_count']) + : null; + } + + Map toJson() { + final data = {}; + data['next_batch'] = nextBatch; + if (rooms != null) { + data['rooms'] = rooms.toJson(); + } + if (presence != null) { + data['presence'] = { + 'events': presence.map((i) => i.toJson()).toList(), + }; + } + if (accountData != null) { + data['account_data'] = { + 'events': accountData.map((i) => i.toJson()).toList(), + }; + } + if (toDevice != null) { + data['to_device'] = { + 'events': toDevice.map((i) => i.toJson()).toList(), + }; + } + if (deviceLists != null) { + data['device_lists'] = deviceLists.toJson(); + } + if (deviceOneTimeKeysCount != null) { + data['device_one_time_keys_count'] = deviceOneTimeKeysCount; + } + return data; + } +} + +class RoomsUpdate { + Map join; + Map invite; + Map leave; + + RoomsUpdate(); + + RoomsUpdate.fromJson(Map json) { + join = json['join'] != null + ? (json['join'] as Map) + .map((k, v) => MapEntry(k, JoinedRoomUpdate.fromJson(v))) + : null; + invite = json['invite'] != null + ? (json['invite'] as Map) + .map((k, v) => MapEntry(k, InvitedRoomUpdate.fromJson(v))) + : null; + leave = json['leave'] != null + ? (json['leave'] as Map) + .map((k, v) => MapEntry(k, LeftRoomUpdate.fromJson(v))) + : null; + } + Map toJson() { + final data = {}; + if (join != null) { + data['join'] = join.map((k, v) => MapEntry(k, v.toJson())); + } + if (invite != null) { + data['invite'] = invite.map((k, v) => MapEntry(k, v.toJson())); + } + if (leave != null) { + data['leave'] = leave.map((k, v) => MapEntry(k, v.toJson())); + } + return data; + } +} + +abstract class SyncRoomUpdate {} + +class JoinedRoomUpdate extends SyncRoomUpdate { + RoomSummary summary; + List state; + TimelineUpdate timeline; + List ephemeral; + List accountData; + UnreadNotificationCounts unreadNotifications; + + JoinedRoomUpdate(); + + JoinedRoomUpdate.fromJson(Map json) { + summary = + json['summary'] != null ? RoomSummary.fromJson(json['summary']) : null; + state = (json['state'] != null && json['state']['events'] != null) + ? (json['state']['events'] as List) + .map((i) => MatrixEvent.fromJson(i)) + .toList() + : null; + timeline = json['timeline'] != null + ? TimelineUpdate.fromJson(json['timeline']) + : null; + + ephemeral = + (json['ephemeral'] != null && json['ephemeral']['events'] != null) + ? (json['ephemeral']['events'] as List) + .map((i) => BasicRoomEvent.fromJson(i)) + .toList() + : null; + accountData = + (json['account_data'] != null && json['account_data']['events'] != null) + ? (json['account_data']['events'] as List) + .map((i) => BasicRoomEvent.fromJson(i)) + .toList() + : null; + unreadNotifications = json['unread_notifications'] != null + ? UnreadNotificationCounts.fromJson(json['unread_notifications']) + : null; + } + + Map toJson() { + final data = {}; + if (summary != null) { + data['summary'] = summary.toJson(); + } + if (state != null) { + data['state'] = { + 'events': state.map((i) => i.toJson()).toList(), + }; + } + if (timeline != null) { + data['timeline'] = timeline.toJson(); + } + if (ephemeral != null) { + data['ephemeral'] = { + 'events': ephemeral.map((i) => i.toJson()).toList(), + }; + } + if (accountData != null) { + data['account_data'] = { + 'events': accountData.map((i) => i.toJson()).toList(), + }; + } + if (unreadNotifications != null) { + data['unread_notifications'] = unreadNotifications.toJson(); + } + return data; + } +} + +class InvitedRoomUpdate extends SyncRoomUpdate { + List inviteState; + InvitedRoomUpdate.fromJson(Map json) { + inviteState = + (json['invite_state'] != null && json['invite_state']['events'] != null) + ? (json['invite_state']['events'] as List) + .map((i) => StrippedStateEvent.fromJson(i)) + .toList() + : null; + } + Map toJson() { + final data = {}; + if (inviteState != null) { + data['invite_state'] = { + 'events': inviteState.map((i) => i.toJson()).toList(), + }; + } + return data; + } +} + +class LeftRoomUpdate extends SyncRoomUpdate { + List state; + TimelineUpdate timeline; + List accountData; + + LeftRoomUpdate(); + + LeftRoomUpdate.fromJson(Map json) { + state = (json['state'] != null && json['state']['events'] != null) + ? (json['state']['events'] as List) + .map((i) => MatrixEvent.fromJson(i)) + .toList() + : null; + timeline = json['timeline'] != null + ? TimelineUpdate.fromJson(json['timeline']) + : null; + accountData = + (json['account_data'] != null && json['account_data']['events'] != null) + ? (json['account_data']['events'] as List) + .map((i) => BasicRoomEvent.fromJson(i)) + .toList() + : null; + } + Map toJson() { + final data = {}; + if (state != null) { + data['state'] = { + 'events': state.map((i) => i.toJson()).toList(), + }; + } + if (timeline != null) { + data['timeline'] = timeline.toJson(); + } + if (accountData != null) { + data['account_data'] = { + 'events': accountData.map((i) => i.toJson()).toList(), + }; + } + return data; + } +} + +class TimelineUpdate { + List events; + bool limited; + String prevBatch; + + TimelineUpdate(); + + TimelineUpdate.fromJson(Map json) { + events = json['events'] != null + ? (json['events'] as List).map((i) => MatrixEvent.fromJson(i)).toList() + : null; + limited = json['limited']; + prevBatch = json['prev_batch']; + } + + Map toJson() { + final data = {}; + if (events != null) { + data['events'] = events.map((i) => i.toJson()).toList(); + } + if (limited != null) { + data['limited'] = limited; + } + if (prevBatch != null) { + data['prev_batch'] = prevBatch; + } + return data; + } +} + +class UnreadNotificationCounts { + int highlightCount; + int notificationCount; + UnreadNotificationCounts.fromJson(Map json) { + highlightCount = json['highlight_count']; + notificationCount = json['notification_count']; + } + Map toJson() { + final data = {}; + if (highlightCount != null) { + data['highlight_count'] = highlightCount; + } + if (notificationCount != null) { + data['notification_count'] = notificationCount; + } + return data; + } +} + +class DeviceListsUpdate { + List changed; + List left; + DeviceListsUpdate.fromJson(Map json) { + changed = List.from(json['changed'] ?? []); + left = List.from(json['left'] ?? []); + } + Map toJson() { + final data = {}; + if (changed != null) { + data['changed'] = changed; + } + if (left != null) { + data['left'] = left; + } + return data; + } +} diff --git a/lib/src/model/tag.dart b/lib/src/model/tag.dart new file mode 100644 index 00000000..f63d6e57 --- /dev/null +++ b/lib/src/model/tag.dart @@ -0,0 +1,42 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class Tag { + double order; + + Tag.fromJson(Map json) { + order = double.tryParse(json['order'].toString()); + } + + Map toJson() { + final data = {}; + if (order != null) { + data['order'] = order; + } + return data; + } +} + +abstract class TagType { + static const String Favourite = 'm.favourite'; + static const String LowPriority = 'm.lowpriority'; + static const String ServerNotice = 'm.server_notice'; + static bool isValid(String tag) => tag.startsWith('m.') + ? [Favourite, LowPriority, ServerNotice].contains(tag) + : true; +} diff --git a/lib/src/model/third_party_identifier.dart b/lib/src/model/third_party_identifier.dart new file mode 100644 index 00000000..14fe31d8 --- /dev/null +++ b/lib/src/model/third_party_identifier.dart @@ -0,0 +1,43 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import '../../matrix_api_lite.dart'; + +class ThirdPartyIdentifier { + ThirdPartyIdentifierMedium medium; + String address; + int validatedAt; + int addedAt; + + ThirdPartyIdentifier.fromJson(Map json) { + medium = ThirdPartyIdentifierMedium.values + .firstWhere((medium) => describeEnum(medium) == json['medium']); + address = json['address']; + validatedAt = json['validated_at']; + addedAt = json['added_at']; + } + + Map toJson() { + final data = {}; + data['medium'] = describeEnum(medium); + data['address'] = address; + data['validated_at'] = validatedAt; + data['added_at'] = addedAt; + return data; + } +} diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart new file mode 100644 index 00000000..68083805 --- /dev/null +++ b/lib/src/model/third_party_location.dart @@ -0,0 +1,37 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class ThirdPartyLocation { + String alias; + String protocol; + Map fields; + + ThirdPartyLocation.fromJson(Map json) { + alias = json['alias']; + protocol = json['protocol']; + fields = Map.from(json['fields']); + } + + Map toJson() { + final data = {}; + data['alias'] = alias; + data['protocol'] = protocol; + data['fields'] = fields; + return data; + } +} diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart new file mode 100644 index 00000000..fd84f907 --- /dev/null +++ b/lib/src/model/third_party_user.dart @@ -0,0 +1,37 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class ThirdPartyUser { + String userId; + String protocol; + Map fields; + + ThirdPartyUser.fromJson(Map json) { + userId = json['userid']; + protocol = json['protocol']; + fields = Map.from(json['fields']); + } + + Map toJson() { + final data = {}; + data['userid'] = userId; + data['protocol'] = protocol; + data['fields'] = fields; + return data; + } +} diff --git a/lib/src/model/timeline_history_response.dart b/lib/src/model/timeline_history_response.dart new file mode 100644 index 00000000..e5752762 --- /dev/null +++ b/lib/src/model/timeline_history_response.dart @@ -0,0 +1,46 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'matrix_event.dart'; + +class TimelineHistoryResponse { + String start; + String end; + List chunk; + List state; + + TimelineHistoryResponse.fromJson(Map json) { + start = json['start']; + end = json['end']; + chunk = json['chunk'] != null + ? (json['chunk'] as List).map((i) => MatrixEvent.fromJson(i)).toList() + : null; + state = json['state'] != null + ? (json['state'] as List).map((i) => MatrixEvent.fromJson(i)).toList() + : null; + } + + Map toJson() { + final data = {}; + if (start != null) data['start'] = start; + if (end != null) data['end'] = end; + if (chunk != null) data['chunk'] = chunk.map((i) => i.toJson()); + if (state != null) data['state'] = state.map((i) => i.toJson()); + return data; + } +} diff --git a/lib/src/model/turn_server_credentials.dart b/lib/src/model/turn_server_credentials.dart new file mode 100644 index 00000000..bf350f50 --- /dev/null +++ b/lib/src/model/turn_server_credentials.dart @@ -0,0 +1,40 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class TurnServerCredentials { + String username; + String password; + List uris; + num ttl; + + TurnServerCredentials.fromJson(Map json) { + username = json['username']; + password = json['password']; + uris = json['uris'].cast(); + ttl = json['ttl']; + } + + Map toJson() { + final data = {}; + data['username'] = username; + data['password'] = password; + data['uris'] = uris; + data['ttl'] = ttl; + return data; + } +} diff --git a/lib/src/model/upload_key_signatures_response.dart b/lib/src/model/upload_key_signatures_response.dart new file mode 100644 index 00000000..325aa5e7 --- /dev/null +++ b/lib/src/model/upload_key_signatures_response.dart @@ -0,0 +1,55 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'matrix_exception.dart'; + +class UploadKeySignaturesResponse { + Map> failures; + + UploadKeySignaturesResponse.fromJson(Map json) { + failures = json['failures'] != null + ? (json['failures'] as Map).map( + (k, v) => MapEntry( + k, + (v as Map).map((k, v) => MapEntry( + k, + MatrixException.fromJson(v), + )), + ), + ) + : null; + } + + Map toJson() { + final data = {}; + if (failures != null) { + data['failures'] = failures.map( + (k, v) => MapEntry( + k, + v.map( + (k, v) => MapEntry( + k, + v.raw, + ), + ), + ), + ); + } + return data; + } +} diff --git a/lib/src/model/user_search_result.dart b/lib/src/model/user_search_result.dart new file mode 100644 index 00000000..1d498083 --- /dev/null +++ b/lib/src/model/user_search_result.dart @@ -0,0 +1,41 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'profile.dart'; + +class UserSearchResult { + List results; + bool limited; + + UserSearchResult.fromJson(Map json) { + results = []; + json['results'].forEach((v) { + results.add(Profile.fromJson(v)); + }); + + limited = json['limited']; + } + + Map toJson() { + final data = {}; + data['results'] = results.map((v) => v.toJson()).toList(); + + data['limited'] = limited; + return data; + } +} diff --git a/lib/src/model/well_known_informations.dart b/lib/src/model/well_known_informations.dart new file mode 100644 index 00000000..feba960c --- /dev/null +++ b/lib/src/model/well_known_informations.dart @@ -0,0 +1,54 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class WellKnownInformations { + MHomeserver mHomeserver; + MHomeserver mIdentityServer; + Map content; + + WellKnownInformations.fromJson(Map json) { + content = json; + mHomeserver = json['m.homeserver'] != null + ? MHomeserver.fromJson(json['m.homeserver']) + : null; + mIdentityServer = json['m.identity_server'] != null + ? MHomeserver.fromJson(json['m.identity_server']) + : null; + } + + Map toJson() { + final data = content; + data['m.homeserver'] = mHomeserver.toJson(); + data['m.identity_server'] = mIdentityServer.toJson(); + return data; + } +} + +class MHomeserver { + String baseUrl; + + MHomeserver.fromJson(Map json) { + baseUrl = json['base_url']; + } + + Map toJson() { + final data = {}; + data['base_url'] = baseUrl; + return data; + } +} diff --git a/lib/src/model/who_is_info.dart b/lib/src/model/who_is_info.dart new file mode 100644 index 00000000..6a266852 --- /dev/null +++ b/lib/src/model/who_is_info.dart @@ -0,0 +1,107 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +class WhoIsInfo { + String userId; + Map devices; + + WhoIsInfo.fromJson(Map json) { + userId = json['user_id']; + devices = json['devices'] != null + ? (json['devices'] as Map) + .map((k, v) => MapEntry(k, DeviceInfo.fromJson(v))) + : null; + } + + Map toJson() { + final data = {}; + data['user_id'] = userId; + if (devices != null) { + data['devices'] = devices.map((k, v) => MapEntry(k, v.toJson())); + } + return data; + } +} + +class DeviceInfo { + List sessions; + + DeviceInfo.fromJson(Map json) { + if (json['sessions'] != null) { + sessions = []; + json['sessions'].forEach((v) { + sessions.add(Sessions.fromJson(v)); + }); + } + } + + Map toJson() { + final data = {}; + if (sessions != null) { + data['sessions'] = sessions.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Sessions { + List connections; + + Sessions.fromJson(Map json) { + if (json['connections'] != null) { + connections = []; + json['connections'].forEach((v) { + connections.add(Connections.fromJson(v)); + }); + } + } + + Map toJson() { + final data = {}; + if (connections != null) { + data['connections'] = connections.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Connections { + String ip; + int lastSeen; + String userAgent; + + Connections.fromJson(Map json) { + ip = json['ip']; + lastSeen = json['last_seen']; + userAgent = json['user_agent']; + } + + Map toJson() { + final data = {}; + if (ip != null) { + data['ip'] = ip; + } + if (lastSeen != null) { + data['last_seen'] = lastSeen; + } + if (userAgent != null) { + data['user_agent'] = userAgent; + } + return data; + } +} diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart new file mode 100644 index 00000000..7e15f379 --- /dev/null +++ b/lib/src/utils/logs.dart @@ -0,0 +1,51 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'package:logger/logger.dart'; + +class Logs extends Logger { + static final Logs _singleton = Logs._internal(); + + factory Logs() { + return _singleton; + } + + set level(Level newLevel) => Logger.level = newLevel; + + final List outputEvents = []; + + Logs._internal() + : super( + printer: PrettyPrinter(methodCount: 0, lineLength: 100), + filter: _MatrixSdkFilter(), + output: _CacheOutput(), + ); +} + +class _MatrixSdkFilter extends LogFilter { + @override + bool shouldLog(LogEvent event) => event.level.index >= Logger.level.index; +} + +class _CacheOutput extends ConsoleOutput { + @override + void output(OutputEvent event) { + Logs().outputEvents.add(event); + super.output(event); + } +} diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart new file mode 100644 index 00000000..fe8f306c --- /dev/null +++ b/lib/src/utils/try_get_map_extension.dart @@ -0,0 +1,18 @@ +import 'logs.dart'; + +extension TryGetMapExtension on Map { + T tryGet(String key, [T fallbackValue]) { + final value = this[key]; + if (value != null && !(value is T)) { + Logs().w( + 'Expected "${T.runtimeType}" in event content for the Key "$key" but got "${value.runtimeType}".'); + return fallbackValue; + } + if (value == null && fallbackValue != null) { + Logs().w( + 'Required field in event content for the Key "$key" is null. Set to "$fallbackValue".'); + return fallbackValue; + } + return value; + } +} diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 00000000..f796df2b --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,15 @@ +name: matrix_api_lite +description: A starting point for Dart libraries or applications. +# version: 1.0.0 +# homepage: https://www.example.com + +environment: + sdk: '>=2.10.0 <3.0.0' + +dependencies: + http: ^0.12.2 + logger: ^0.9.4 + +dev_dependencies: + pedantic: ^1.9.0 + test: ^1.14.4 diff --git a/test/fake_matrix_api.dart b/test/fake_matrix_api.dart new file mode 100644 index 00000000..8c980a4f --- /dev/null +++ b/test/fake_matrix_api.dart @@ -0,0 +1,2159 @@ +/* + * Ansible inventory script used at Famedly GmbH for managing many hosts + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'dart:convert'; +import 'dart:core'; +import 'dart:math'; + +import 'package:http/http.dart'; +import 'package:http/testing.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; + +Map decodeJson(dynamic data) { + if (data is String) { + return json.decode(data); + } + if (data.isEmpty) { + return {}; + } + return data; +} + +class FakeMatrixApi extends MockClient { + static final calledEndpoints = >{}; + static int eventCounter = 0; + + FakeMatrixApi() + : super((request) async { + // Collect data from Request + var action = request.url.path; + if (request.url.path.contains('/_matrix')) { + action = request.url.path.split('/_matrix').last + + '?' + + request.url.query; + } + + if (action.endsWith('?')) { + action = action.substring(0, action.length - 1); + } + if (action.endsWith('/')) { + action = action.substring(0, action.length - 1); + } + final method = request.method; + final dynamic data = + method == 'GET' ? request.url.queryParameters : request.body; + dynamic res = {}; + var statusCode = 200; + + //print('\$method request to $action with Data: $data'); + + // Sync requests with timeout + if (data is Map && data['timeout'] is String) { + await Future.delayed(Duration(seconds: 5)); + } + + if (request.url.origin != 'https://fakeserver.notexisting') { + return Response( + 'Not found...', 404); + } + + // Call API + if (!calledEndpoints.containsKey(action)) { + calledEndpoints[action] = []; + } + calledEndpoints[action].add(data); + if (api.containsKey(method) && api[method].containsKey(action)) { + res = api[method][action](data); + if (res is Map && res.containsKey('errcode')) { + statusCode = 405; + } + } else if (method == 'PUT' && + action.contains('/client/r0/sendToDevice/')) { + res = {}; + } else if (method == 'GET' && + action.contains('/client/r0/rooms/') && + action.contains('/state/m.room.member/')) { + res = {'displayname': ''}; + } else if (method == 'PUT' && + action.contains( + '/client/r0/rooms/!1234%3AfakeServer.notExisting/send/')) { + res = {'event_id': '\$event${FakeMatrixApi.eventCounter++}'}; + } else if (action.contains('/client/r0/sync')) { + res = { + 'next_batch': DateTime.now().millisecondsSinceEpoch.toString + }; + } else { + res = { + 'errcode': 'M_UNRECOGNIZED', + 'error': 'Unrecognized request' + }; + statusCode = 405; + } + + return Response.bytes(utf8.encode(json.encode(res)), statusCode); + }); + + static Map messagesResponse = { + 'start': 't47429-4392820_219380_26003_2265', + 'end': 't47409-4357353_219380_26003_2265', + 'chunk': [ + { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' + }, + 'type': 'm.room.message', + 'event_id': '3143273582443PhrSn:example.org', + 'room_id': '!1234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + }, + { + 'content': {'name': 'The room name'}, + 'type': 'm.room.name', + 'event_id': '2143273582443PhrSn:example.org', + 'room_id': '!1234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' + }, + { + 'content': { + 'body': 'Gangnam Style', + 'url': 'mxc://example.org/a526eYUSFFxlgbQYZmo442', + 'info': { + 'thumbnail_url': 'mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe', + 'thumbnail_info': { + 'mimetype': 'image/jpeg', + 'size': 46144, + 'w': 300, + 'h': 300 + }, + 'w': 480, + 'h': 320, + 'duration': 2140786, + 'size': 1563685, + 'mimetype': 'video/mp4' + }, + 'msgtype': 'm.video' + }, + 'type': 'm.room.message', + 'event_id': '1143273582443PhrSn:example.org', + 'room_id': '!1234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + } + ], + 'state': [], + }; + + static Map syncResponse = { + 'next_batch': Random().nextDouble().toString(), + 'rooms': { + 'join': { + '!726s6s6q:example.com': { + 'summary': { + 'm.heroes': ['@alice:example.com', '@bob:example.com'], + 'm.joined_member_count': 2, + 'm.invited_member_count': 0 + }, + 'unread_notifications': { + 'highlight_count': 2, + 'notification_count': 2, + }, + 'state': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'm.room.member', + 'state_key': '@alice:example.com', + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid', + }, + 'origin_server_ts': 1417731086795, + 'event_id': '66697273743031:example.com' + }, + { + 'sender': '@alice:example.com', + 'type': 'm.room.canonical_alias', + 'content': { + 'alias': '#famedlyContactDiscovery:fakeServer.notExisting' + }, + 'state_key': '', + 'origin_server_ts': 1417731086796, + 'event_id': '66697273743032:example.com' + }, + { + 'sender': '@alice:example.com', + 'type': 'm.room.encryption', + 'state_key': '', + 'content': {'algorithm': AlgorithmTypes.megolmV1AesSha2}, + 'origin_server_ts': 1417731086795, + 'event_id': '666972737430353:example.com' + }, + { + 'content': { + 'pinned': ['1234:bla'] + }, + 'type': 'm.room.pinned_events', + 'event_id': '21432735824443PhrSn:example.org', + 'room_id': '!1234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' + }, + ] + }, + 'timeline': { + 'events': [ + { + 'sender': '@bob:example.com', + 'type': 'm.room.member', + 'state_key': '@bob:example.com', + 'content': {'membership': 'join'}, + 'prev_content': {'membership': 'invite'}, + 'origin_server_ts': 1417731086795, + 'event_id': '7365636s6r6432:example.com', + 'unsigned': {'foo': 'bar'} + }, + { + 'sender': '@alice:example.com', + 'type': 'm.room.message', + 'content': {'body': 'I am a fish', 'msgtype': 'm.text'}, + 'origin_server_ts': 1417731086797, + 'event_id': '74686972643033:example.com' + } + ], + 'limited': true, + 'prev_batch': 't34-23535_0_0' + }, + 'ephemeral': { + 'events': [ + { + 'type': 'm.typing', + 'content': { + 'user_ids': ['@alice:example.com'] + } + }, + { + 'content': { + '7365636s6r6432:example.com': { + 'm.read': { + '@alice:example.com': {'ts': 1436451550453} + } + } + }, + 'room_id': '!726s6s6q:example.com', + 'type': 'm.receipt' + } + ] + }, + 'account_data': { + 'events': [ + { + 'type': 'm.tag', + 'content': { + 'tags': { + 'work': {'order': 1} + } + } + }, + { + 'type': 'org.example.custom.room.config', + 'content': {'custom_config_key': 'custom_config_value'} + } + ] + } + } + }, + 'invite': { + '!696r7674:example.com': { + 'invite_state': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'm.room.name', + 'state_key': '', + 'content': {'name': 'My Room Name'} + }, + { + 'sender': '@alice:example.com', + 'type': 'm.room.member', + 'state_key': '@bob:example.com', + 'content': {'membership': 'invite'} + } + ] + } + } + }, + 'leave': { + '!726s6s6f:example.com': { + 'state': { + 'events': [ + { + 'sender': '@charley:example.com', + 'type': 'm.room.name', + 'state_key': '', + 'content': {'name': 'left room'}, + 'origin_server_ts': 1417731086795, + 'event_id': '66697273743031:example.com' + }, + ] + }, + 'timeline': { + 'events': [ + { + 'sender': '@bob:example.com', + 'type': 'm.room.message', + 'content': {'text': 'Hallo'}, + 'origin_server_ts': 1417731086795, + 'event_id': '7365636s6r64300:example.com', + 'unsigned': {'foo': 'bar'} + }, + ], + 'limited': true, + 'prev_batch': 't34-23535_0_0' + }, + 'account_data': { + 'events': [ + { + 'type': 'm.tag', + 'content': { + 'tags': { + 'work': {'order': 1} + } + } + }, + { + 'type': 'org.example.custom.room.config', + 'content': {'custom_config_key': 'custom_config_value'} + } + ] + } + } + }, + }, + 'presence': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'm.presence', + 'content': {'presence': 'online'} + } + ] + }, + 'account_data': { + 'events': [ + { + 'content': { + 'global': { + 'content': [ + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} + ], + 'default': true, + 'enabled': true, + 'pattern': 'alice', + 'rule_id': '.m.rule.contains_user_name' + } + ], + 'override': [ + { + 'actions': ['dont_notify'], + 'conditions': [], + 'default': true, + 'enabled': false, + 'rule_id': '.m.rule.master' + }, + { + 'actions': ['dont_notify'], + 'conditions': [ + { + 'key': 'content.msgtype', + 'kind': 'event_match', + 'pattern': 'm.notice' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.suppress_notices' + } + ], + 'room': [ + { + 'actions': ['dont_notify'], + 'conditions': [ + { + 'key': 'room_id', + 'kind': 'event_match', + 'pattern': '!localpart:server.abc', + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '!localpart:server.abc' + } + ], + 'sender': [], + 'underride': [ + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'ring'}, + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.call.invite' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.call' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} + ], + 'conditions': [ + {'kind': 'contains_display_name'} + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.contains_display_name' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + {'is': '2', 'kind': 'room_member_count'}, + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.message' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.room_one_to_one' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' + }, + { + 'key': 'content.membership', + 'kind': 'event_match', + 'pattern': 'invite' + }, + { + 'key': 'state_key', + 'kind': 'event_match', + 'pattern': '@alice:example.com' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.invite_for_me' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.member_event' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.message' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.message' + } + ] + } + }, + 'type': 'm.push_rules' + }, + { + 'type': 'org.example.custom.config', + 'content': {'custom_config_key': 'custom_config_value'} + }, + { + 'content': { + '@bob:example.com': [ + '!726s6s6q:example.com', + '!hgfedcba:example.com' + ] + }, + 'type': 'm.direct' + }, + { + 'type': EventTypes.SecretStorageDefaultKey, + 'content': {'key': '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3'} + }, + { + 'type': 'm.secret_storage.key.0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3', + 'content': { + 'algorithm': AlgorithmTypes.secretStorageV1AesHmcSha2, + 'passphrase': { + 'algorithm': AlgorithmTypes.pbkdf2, + 'iterations': 500000, + 'salt': 'F4jJ80mr0Fc8mRwU9JgA3lQDyjPuZXQL' + }, + 'iv': 'HjbTgIoQH2pI7jQo19NUzA==', + 'mac': 'QbJjQzDnAggU0cM4RBnDxw2XyarRGjdahcKukP9xVlk=' + } + }, + { + 'type': 'm.cross_signing.master', + 'content': { + 'encrypted': { + '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': { + 'iv': 'eIb2IITxtmcq+1TrT8D5eQ==', + 'ciphertext': + 'lWRTPo5qxf4LAVwVPzGHOyMcP181n7bb9/B0lvkLDC2Oy4DvAL0eLx2x3bY=', + 'mac': 'Ynx89tIxPkx0o6ljMgxszww17JOgB4tg4etmNnMC9XI=' + } + } + } + }, + { + 'type': EventTypes.CrossSigningSelfSigning, + 'content': { + 'encrypted': { + '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': { + 'iv': 'YqU2XIjYulYZl+bkZtGgVw==', + 'ciphertext': + 'kM2TSoy/jR/4d357ZoRPbpPypxQl6XRLo3FsEXz+f7vIOp82GeRp28RYb3k=', + 'mac': 'F+DZa5tAFmWsYSryw5EuEpzTmmABRab4GETkM85bGGo=' + } + } + } + }, + { + 'type': EventTypes.CrossSigningUserSigning, + 'content': { + 'encrypted': { + '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': { + 'iv': 'D7AM3LXFu7ZlyGOkR+OeqQ==', + 'ciphertext': + 'bYA2+OMgsO6QB1E31aY+ESAWrT0fUBTXqajy4qmL7bVDSZY4Uj64EXNbHuA=', + 'mac': 'j2UtyPo/UBSoiaQCWfzCiRZXp3IRt0ZZujuXgUMjnw4=' + } + } + } + }, + { + 'type': EventTypes.MegolmBackup, + 'content': { + 'encrypted': { + '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': { + 'iv': 'cL/0MJZaiEd3fNU+I9oJrw==', + 'ciphertext': + 'WL73Pzdk5wZdaaSpaeRH0uZYKcxkuV8IS6Qa2FEfA1+vMeRLuHcWlXbMX0w=', + 'mac': '+xozp909S6oDX8KRV8D8ZFVRyh7eEYQpPP76f+DOsnw=' + } + } + } + } + ] + }, + 'to_device': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'm.new_device', + 'content': { + 'device_id': 'XYZABCDE', + 'rooms': ['!726s6s6q:example.com'] + } + }, +// { +// 'sender': '@othertest:fakeServer.notExisting', +// 'content': { +// 'algorithm': AlgorithmTypes.megolmV1AesSha2, +// 'room_id': '!726s6s6q:example.com', +// 'session_id': 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU', +// 'session_key': +// 'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw' +// }, +// 'type': 'm.room_key' +// }, + { + // this is the commented out m.room_key event - only encrypted + 'sender': '@othertest:fakeServer.notExisting', + 'content': { + 'algorithm': AlgorithmTypes.olmV1Curve25519AesSha2, + 'sender_key': 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg', + 'ciphertext': { + '7rvl3jORJkBiK4XX1e5TnGnqz068XfYJ0W++Ml63rgk': { + 'type': 0, + 'body': + 'Awogyh7K4iLUQjcOxIfi7q7LhBBqv9w0mQ6JI9+U9tv7iF4SIHC6xb5YFWf9voRnmDBbd+0vxD/xDlVNRDlPIKliLGkYGiAkEbtlo+fng4ELtO4gSLKVbcFn7tZwZCEUE8H2miBsCCKABgMKIFrKDJwB7gM3lXPt9yVoh6gQksafKt7VFCNRN5KLKqsDEAAi0AX5EfTV7jJ1ZWAbxftjoSN6kCVIxzGclbyg1HjchmNCX7nxNCHWl+q5ZgqHYZVu2n2mCVmIaKD0kvoEZeY3tV1Itb6zf67BLaU0qgW/QzHCHg5a44tNLjucvL2mumHjIG8k0BY2uh+52HeiMCvSOvtDwHg7nzCASGdqPVCj9Kzw6z7F6nL4e3mYim8zvJd7f+mD9z3ARrypUOLGkTGYbB2PQOovf0Do8WzcaRzfaUCnuu/YVZWKK7DPgG8uhw/TjR6XtraAKZysF+4DJYMG9SQWx558r6s7Z5EUOF5CU2M35w1t1Xxllb3vrS83dtf9LPCrBhLsEBeYEUBE2+bTBfl0BDKqLiB0Cc0N0ixOcHIt6e40wAvW622/gMgHlpNSx8xG12u0s6h6EMWdCXXLWd9fy2q6glFUHvA67A35q7O+M8DVml7Y9xG55Y3DHkMDc9cwgwFkBDCAYQe6pQF1nlKytcVCGREpBs/gq69gHAStMQ8WEg38Lf8u8eBr2DFexrN4U+QAk+S//P3fJgf0bQx/Eosx4fvWSz9En41iC+ADCsWQpMbwHn4JWvtAbn3oW0XmL/OgThTkJMLiCymduYAa1Hnt7a3tP0KTL2/x11F02ggQHL28cCjq5W4zUGjWjl5wo2PsKB6t8aAvMg2ujGD2rCjb4yrv5VIzAKMOZLyj7K0vSK9gwDLQ/4vq+QnKUBG5zrcOze0hX+kz2909/tmAdeCH61Ypw7gbPUJAKnmKYUiB/UgwkJvzMJSsk/SEs5SXosHDI+HsJHJp4Mp4iKD0xRMst+8f9aTjaWwh8ZvELE1ZOhhCbF3RXhxi3x2Nu8ORIz+vhEQ1NOlMc7UIo98Fk/96T36vL/fviowT4C/0AlaapZDJBmKwhmwqisMjY2n1vY29oM2p5BzY1iwP7q9BYdRFst6xwo57TNSuRwQw7IhFsf0k+ABuPEZy5xB5nPHyIRTf/pr3Hw', + }, + }, + }, + 'type': 'm.room.encrypted', + }, + ] + }, + 'device_lists': { + 'changed': [ + '@alice:example.com', + ], + 'left': [ + '@bob:example.com', + ], + }, + 'device_one_time_keys_count': {'curve25519': 10, 'signed_curve25519': 20}, + }; + + static Map archiveSyncResponse = { + 'next_batch': Random().nextDouble().toString(), + 'presence': {'events': []}, + 'account_data': {'events': []}, + 'to_device': {'events': []}, + 'rooms': { + 'join': {}, + 'invite': {}, + 'leave': { + '!5345234234:example.com': { + 'timeline': { + 'events': [ + { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' + }, + 'type': 'm.room.message', + 'event_id': '143273582443PhrSn:example.org', + 'room_id': '!5345234234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + }, + ] + }, + 'state': { + 'events': [ + { + 'content': {'name': 'The room name'}, + 'type': 'm.room.name', + 'event_id': '2143273582443PhrSn:example.org', + 'room_id': '!5345234234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' + }, + ] + }, + 'account_data': { + 'events': [ + { + 'type': 'test.type.data', + 'content': {'foo': 'bar'}, + }, + ], + }, + }, + '!5345234235:example.com': { + 'timeline': {'events': []}, + 'state': { + 'events': [ + { + 'content': {'name': 'The room name 2'}, + 'type': 'm.room.name', + 'event_id': '2143273582443PhrSn:example.org', + 'room_id': '!5345234235:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' + }, + ] + } + }, + }, + } + }; + + static final Map> api = { + 'GET': { + '/path/to/auth/error': (var req) => { + 'errcode': 'M_FORBIDDEN', + 'error': 'Blabla', + }, + '/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10': (var req) => { + 'og:title': 'Matrix Blog Post', + 'og:description': 'This is a really cool blog post from matrix.org', + 'og:image': 'mxc://example.com/ascERGshawAWawugaAcauga', + 'og:image:type': 'image/png', + 'og:image:height': 48, + 'og:image:width': 48, + 'matrix:image:size': 102400 + }, + '/media/r0/config': (var req) => {'m.upload.size': 50000000}, + '/.well-known/matrix/client': (var req) => { + 'm.homeserver': {'base_url': 'https://matrix.example.com'}, + 'm.identity_server': {'base_url': 'https://identity.example.com'}, + 'org.example.custom.property': { + 'app_url': 'https://custom.app.example.org' + } + }, + '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags': + (var req) => { + 'tags': { + 'm.favourite': {'order': 0.1}, + 'u.Work': {'order': 0.7}, + 'u.Customers': {} + } + }, + '/client/r0/events?from=1234&timeout=10&roomId=%211234': (var req) => { + 'start': 's3456_9_0', + 'end': 's3457_9_0', + 'chunk': [ + { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' + }, + 'type': 'm.room.message', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!somewhere:over.the.rainbow', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + } + ] + }, + '/client/r0/thirdparty/location?alias=1234': (var req) => [ + { + 'alias': '#freenode_#matrix:matrix.org', + 'protocol': 'irc', + 'fields': {'network': 'freenode', 'channel': '#matrix'} + } + ], + '/client/r0/thirdparty/location/irc': (var req) => [ + { + 'alias': '#freenode_#matrix:matrix.org', + 'protocol': 'irc', + 'fields': {'network': 'freenode', 'channel': '#matrix'} + } + ], + '/client/r0/thirdparty/user/irc': (var req) => [ + { + 'userid': '@_gitter_jim:matrix.org', + 'protocol': 'gitter', + 'fields': {'user': 'jim'} + } + ], + '/client/r0/thirdparty/user?userid=1234': (var req) => [ + { + 'userid': '@_gitter_jim:matrix.org', + 'protocol': 'gitter', + 'fields': {'user': 'jim'} + } + ], + '/client/r0/thirdparty/protocol/irc': (var req) => { + 'user_fields': ['network', 'nickname'], + 'location_fields': ['network', 'channel'], + 'icon': 'mxc://example.org/aBcDeFgH', + 'field_types': { + 'network': { + 'regexp': '([a-z0-9]+\\.)*[a-z0-9]+', + 'placeholder': 'irc.example.org' + }, + 'nickname': {'regexp': '[^\\s#]+', 'placeholder': 'username'}, + 'channel': {'regexp': '#[^\\s]+', 'placeholder': '#foobar'} + }, + 'instances': [ + { + 'desc': 'Freenode', + 'icon': 'mxc://example.org/JkLmNoPq', + 'fields': {'network': 'freenode'}, + 'network_id': 'freenode' + } + ] + }, + '/client/r0/thirdparty/protocols': (var req) => { + 'irc': { + 'user_fields': ['network', 'nickname'], + 'location_fields': ['network', 'channel'], + 'icon': 'mxc://example.org/aBcDeFgH', + 'field_types': { + 'network': { + 'regexp': '([a-z0-9]+\\.)*[a-z0-9]+', + 'placeholder': 'irc.example.org' + }, + 'nickname': {'regexp': '[^\\s]+', 'placeholder': 'username'}, + 'channel': {'regexp': '#[^\\s]+', 'placeholder': '#foobar'} + }, + 'instances': [ + { + 'network_id': 'freenode', + 'desc': 'Freenode', + 'icon': 'mxc://example.org/JkLmNoPq', + 'fields': {'network': 'freenode.net'} + } + ] + }, + 'gitter': { + 'user_fields': ['username'], + 'location_fields': ['room'], + 'icon': 'mxc://example.org/aBcDeFgH', + 'field_types': { + 'username': {'regexp': '@[^\\s]+', 'placeholder': '@username'}, + 'room': { + 'regexp': '[^\\s]+\\/[^\\s]+', + 'placeholder': 'matrix-org/matrix-doc' + } + }, + 'instances': [ + { + 'network_id': 'gitter', + 'desc': 'Gitter', + 'icon': 'mxc://example.org/zXyWvUt', + 'fields': {} + } + ] + } + }, + '/client/r0/account/whoami': (var req) => + {'user_id': 'alice@example.com'}, + '/client/r0/capabilities': (var req) => { + 'capabilities': { + 'm.change_password': {'enabled': false}, + 'm.room_versions': { + 'default': '1', + 'available': { + '1': 'stable', + '2': 'stable', + '3': 'unstable', + 'test-version': 'unstable' + } + }, + 'com.example.custom.ratelimit': {'max_requests_per_hour': 600} + } + }, + '/client/r0/rooms/1234/context/1234?filter=%7B%7D&limit=10': (var req) => + { + 'end': 't29-57_2_0_2', + 'events_after': [ + { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' + }, + 'type': 'm.room.message', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + } + ], + 'event': { + 'content': { + 'body': 'filename.jpg', + 'info': { + 'h': 398, + 'w': 394, + 'mimetype': 'image/jpeg', + 'size': 31037 + }, + 'url': 'mxc://example.org/JWEIFJgwEIhweiWJE', + 'msgtype': 'm.image' + }, + 'type': 'm.room.message', + 'event_id': '\$f3h4d129462ha:example.com', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + }, + 'events_before': [ + { + 'content': { + 'body': 'something-important.doc', + 'filename': 'something-important.doc', + 'info': {'mimetype': 'application/msword', 'size': 46144}, + 'msgtype': 'm.file', + 'url': 'mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe' + }, + 'type': 'm.room.message', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + } + ], + 'start': 't27-54_2_0_2', + 'state': [ + { + 'content': { + 'creator': '@example:example.org', + 'room_version': '1', + 'm.federate': true, + 'predecessor': { + 'event_id': '\$something:example.org', + 'room_id': '!oldroom:example.org' + } + }, + 'type': 'm.room.create', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' + }, + { + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' + }, + 'type': 'm.room.member', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.org' + } + ] + }, + '/client/r0/admin/whois/%40alice%3Aexample.com': (var req) => { + 'user_id': '@peter:rabbit.rocks', + 'devices': { + 'teapot': { + 'sessions': [ + { + 'connections': [ + { + 'ip': '127.0.0.1', + 'last_seen': 1411996332123, + 'user_agent': 'curl/7.31.0-DEV' + }, + { + 'ip': '10.0.0.2', + 'last_seen': 1411996332123, + 'user_agent': + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36' + } + ] + } + ] + } + } + }, + '/client/r0/user/%40alice%3Aexample.com/account_data/test.account.data': + (var req) => {'foo': 'bar'}, + '/client/r0/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data': + (var req) => {'foo': 'bar'}, + '/client/r0/directory/room/%23testalias%3Aexample.com': (var reqI) => { + 'room_id': '!abnjk1jdasj98:capuchins.com', + 'servers': ['capuchins.com', 'matrix.org', 'another.com'] + }, + '/client/r0/account/3pid': (var req) => { + 'threepids': [ + { + 'medium': 'email', + 'address': 'monkey@banana.island', + 'validated_at': 1535176800000, + 'added_at': 1535336848756 + } + ] + }, + '/client/r0/devices': (var req) => { + 'devices': [ + { + 'device_id': 'QBUAZIFURK', + 'display_name': 'android', + 'last_seen_ip': '1.2.3.4', + 'last_seen_ts': 1474491775024 + } + ] + }, + '/client/r0/notifications?from=1234&limit=10&only=1234': (var req) => { + 'next_token': 'abcdef', + 'notifications': [ + { + 'actions': ['notify'], + 'profile_tag': 'hcbvkzxhcvb', + 'read': true, + 'room_id': '!abcdefg:example.com', + 'ts': 1475508881945, + 'event': { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' + }, + 'type': 'm.room.message', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!jEsUZKDJdhlrceRyVU:example.org', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + } + } + ] + }, + '/client/r0/devices/QBUAZIFURK': (var req) => { + 'device_id': 'QBUAZIFURK', + 'display_name': 'android', + 'last_seen_ip': '1.2.3.4', + 'last_seen_ts': 1474491775024 + }, + '/client/r0/profile/%40alice%3Aexample.com/displayname': (var reqI) => + {'displayname': 'Alice M'}, + '/client/r0/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => + {'avatar_url': 'mxc://test'}, + '/client/r0/profile/%40alice%3Aexample.com': (var reqI) => { + 'avatar_url': 'mxc://test', + 'displayname': 'Alice M', + }, + '/client/r0/voip/turnServer': (var req) => { + 'username': '1443779631:@user:example.com', + 'password': 'JlKfBy1QwLrO20385QyAtEyIv0=', + 'uris': [ + 'turn:turn.example.com:3478?transport=udp', + 'turn:10.20.30.40:3478?transport=tcp', + 'turns:10.20.30.40:443?transport=tcp' + ], + 'ttl': 86400 + }, + '/client/r0/presence/${Uri.encodeComponent('@alice:example.com')}/status': + (var req) => { + 'presence': 'unavailable', + 'last_active_ago': 420845, + 'status_msg': 'test', + 'currently_active': false + }, + '/client/r0/keys/changes?from=1234&to=1234': (var req) => { + 'changed': ['@alice:example.com', '@bob:example.org'], + 'left': ['@clara:example.com', '@doug:example.org'] + }, + '/client/r0/pushers': (var req) => { + 'pushers': [ + { + 'pushkey': 'Xp/MzCt8/9DcSNE9cuiaoT5Ac55job3TdLSSmtmYl4A=', + 'kind': 'http', + 'app_id': 'face.mcapp.appy.prod', + 'app_display_name': 'Appy McAppface', + 'device_display_name': 'Alices Phone', + 'profile_tag': 'xyz', + 'lang': 'en-US', + 'data': { + 'url': 'https://example.com/_matrix/push/v1/notify', + 'format': 'event_id_only', + } + } + ] + }, + '/client/r0/publicRooms?limit=10&since=1234&server=example.com': + (var req) => { + 'chunk': [ + { + 'aliases': ['#murrays:cheese.bar'], + 'canonical_alias': '#murrays:cheese.bar', + 'avatar_url': 'mxc://bleeker.street/CHEDDARandBRIE', + 'guest_can_join': false, + 'name': 'CHEESE', + 'num_joined_members': 37, + 'room_id': '!ol19s:bleecker.street', + 'topic': 'Tasty tasty cheese', + 'world_readable': true + } + ], + 'next_batch': 'p190q', + 'prev_batch': 'p1902', + 'total_room_count_estimate': 115 + }, + '/client/r0/room/!localpart%3Aexample.com/aliases': (var req) => { + 'aliases': [ + '#somewhere:example.com', + '#another:example.com', + '#hat_trick:example.com' + ] + }, + '/client/r0/joined_rooms': (var req) => { + 'joined_rooms': ['!foo:example.com'] + }, + '/client/r0/directory/list/room/!localpart%3Aexample.com': (var req) => + {'visibility': 'public'}, + '/client/r0/rooms/1/state/m.room.member/@alice:example.com': (var req) => + {'displayname': 'Alice'}, + '/client/r0/profile/%40getme%3Aexample.com': (var req) => { + 'avatar_url': 'mxc://test', + 'displayname': 'You got me', + }, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.member/@getme%3Aexample.com': + (var req) => { + 'avatar_url': 'mxc://test', + 'displayname': 'You got me', + }, + '/client/r0/rooms/!localpart%3Aserver.abc/state': (var req) => [ + { + 'content': {'join_rule': 'public'}, + 'type': 'm.room.join_rules', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' + }, + { + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' + }, + 'type': 'm.room.member', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.org' + }, + { + 'content': { + 'creator': '@example:example.org', + 'room_version': '1', + 'm.federate': true, + 'predecessor': { + 'event_id': '\$something:example.org', + 'room_id': '!oldroom:example.org' + } + }, + 'type': 'm.room.create', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' + }, + { + 'content': { + 'ban': 50, + 'events': {'m.room.name': 100, 'm.room.power_levels': 100}, + 'events_default': 0, + 'invite': 50, + 'kick': 50, + 'redact': 50, + 'state_default': 50, + 'users': {'@example:localhost': 100}, + 'users_default': 0, + 'notifications': {'room': 20} + }, + 'type': 'm.room.power_levels', + 'event_id': '\$143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' + } + ], + '/client/r0/rooms/!localpart:server.abc/state/m.room.member/@getme:example.com': + (var req) => { + 'avatar_url': 'mxc://test', + 'displayname': 'You got me', + }, + '/client/r0/rooms/!localpart:server.abc/event/1234': (var req) => { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' + }, + 'type': 'm.room.message', + 'event_id': '143273582443PhrSn:example.org', + 'room_id': '!localpart:server.abc', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + }, + '/client/r0/rooms/!localpart%3Aserver.abc/event/1234': (var req) => { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' + }, + 'type': 'm.room.message', + 'event_id': '143273582443PhrSn:example.org', + 'room_id': '!localpart:server.abc', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + }, + '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&dir=b&to=1234&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': + (var req) => messagesResponse, + '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': + (var req) => messagesResponse, + '/client/r0/rooms/!1234%3Aexample.com/messages?from=1234&dir=b&limit=100&filter=%7B%22lazy_load_members%22%3Atrue%7D': + (var req) => messagesResponse, + '/client/versions': (var req) => { + 'versions': [ + 'r0.0.1', + 'r0.1.0', + 'r0.2.0', + 'r0.3.0', + 'r0.4.0', + 'r0.5.0' + ], + 'unstable_features': {'m.lazy_load_members': true}, + }, + '/client/r0/login': (var req) => { + 'flows': [ + {'type': 'm.login.password'} + ] + }, + '/client/r0/rooms/!localpart%3Aserver.abc/joined_members': (var req) => { + 'joined': { + '@bar:example.com': { + 'display_name': 'Bar', + 'avatar_url': 'mxc://riot.ovh/printErCATzZijQsSDWorRaK' + } + } + }, + '/client/r0/rooms/!localpart%3Aserver.abc/members?at=1234&membership=join¬_membership=leave': + (var req) => { + 'chunk': [ + { + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' + }, + 'type': 'm.room.member', + 'event_id': '§143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@alice:example.com', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.com' + } + ] + }, + '/client/r0/rooms/!696r7674:example.com/members': (var req) => { + 'chunk': [ + { + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' + }, + 'type': 'm.room.member', + 'event_id': '§143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@alice:example.com', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.com' + } + ] + }, + '/client/r0/rooms/!726s6s6q:example.com/members': (var req) => { + 'chunk': [ + { + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' + }, + 'type': 'm.room.member', + 'event_id': '§143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@alice:example.com', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.com' + } + ] + }, + '/client/r0/rooms/!localpart%3Aserver.abc/members': (var req) => { + 'chunk': [ + { + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' + }, + 'type': 'm.room.member', + 'event_id': '§143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.org' + } + ] + }, + '/client/r0/pushrules/global/content/nocake': (var req) => { + 'actions': ['dont_notify'], + 'pattern': 'cake*lie', + 'rule_id': 'nocake', + 'enabled': true, + 'default': false + }, + '/client/r0/pushrules/global/content/nocake/enabled': (var req) => { + 'enabled': true, + }, + '/client/r0/pushrules/global/content/nocake/actions': (var req) => { + 'actions': ['notify'] + }, + '/client/r0/pushrules': (var req) => { + 'global': { + 'content': [ + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} + ], + 'default': true, + 'enabled': true, + 'pattern': 'alice', + 'rule_id': '.m.rule.contains_user_name' + } + ], + 'override': [ + { + 'actions': ['dont_notify'], + 'conditions': [], + 'default': true, + 'enabled': false, + 'rule_id': '.m.rule.master' + }, + { + 'actions': ['dont_notify'], + 'conditions': [ + { + 'key': 'content.msgtype', + 'kind': 'event_match', + 'pattern': 'm.notice' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.suppress_notices' + } + ], + 'room': [], + 'sender': [], + 'underride': [ + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'ring'}, + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.call.invite' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.call' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} + ], + 'conditions': [ + {'kind': 'contains_display_name'} + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.contains_display_name' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + {'is': '2', 'kind': 'room_member_count'} + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.room_one_to_one' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' + }, + { + 'key': 'content.membership', + 'kind': 'event_match', + 'pattern': 'invite' + }, + { + 'key': 'state_key', + 'kind': 'event_match', + 'pattern': '@alice:example.com' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.invite_for_me' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.member_event' + }, + { + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} + ], + 'conditions': [ + { + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.message' + } + ], + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.message' + } + ] + } + }, + '/client/r0/sync?filter=%7B%22room%22%3A%7B%22include_leave%22%3Atrue%2C%22timeline%22%3A%7B%22limit%22%3A10%7D%7D%7D&timeout=0': + (var req) => archiveSyncResponse, + '/client/r0/sync?filter=%7B%22room%22%3A%7B%22state%22%3A%7B%22lazy_load_members%22%3Atrue%7D%7D%7D': + (var req) => syncResponse, + '/client/r0/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15': + (var req) => syncResponse, + '/client/r0/register/available?username=testuser': (var req) => + {'available': true}, + '/client/r0/user/${Uri.encodeComponent('alice@example.com')}/filter/1234': + (var req) => { + 'room': { + 'state': { + 'types': ['m.room.*'], + 'not_rooms': ['!726s6s6q:example.com'] + }, + 'timeline': { + 'limit': 10, + 'types': ['m.room.message'], + 'not_rooms': ['!726s6s6q:example.com'], + 'not_senders': ['@spam:example.com'] + }, + 'ephemeral': { + 'types': ['m.receipt', 'm.typing'], + 'not_rooms': ['!726s6s6q:example.com'], + 'not_senders': ['@spam:example.com'] + }, + 'account_data': { + 'types': ['m.receipt', 'm.typing'], + 'not_rooms': ['!726s6s6q:example.com'], + 'not_senders': ['@spam:example.com'] + } + }, + 'presence': { + 'types': ['m.presence'], + 'not_senders': ['@alice:example.com'] + }, + 'event_format': 'client', + 'event_fields': ['type', 'content', 'sender'] + }, + '/client/unstable/room_keys/version': (var req) => { + 'algorithm': AlgorithmTypes.megolmBackupV1Curve25519AesSha2, + 'auth_data': { + 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', + 'signatures': {}, + }, + 'count': 0, + 'etag': '0', + 'version': '5', + }, + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': + (var req) => { + 'first_message_index': 0, + 'forwarded_count': 0, + 'is_verified': true, + 'session_data': { + 'ephemeral': 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', + 'ciphertext': + '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', + 'mac': 'QzKV/fgAs4U', + }, + }, + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': + (var req) => { + 'sessions': { + 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU': { + 'first_message_index': 0, + 'forwarded_count': 0, + 'is_verified': true, + 'session_data': { + 'ephemeral': + 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', + 'ciphertext': + '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', + 'mac': 'QzKV/fgAs4U', + }, + }, + }, + }, + '/client/unstable/room_keys/keys?version=5': (var req) => { + 'rooms': { + '!726s6s6q:example.com': { + 'sessions': { + 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU': { + 'first_message_index': 0, + 'forwarded_count': 0, + 'is_verified': true, + 'session_data': { + 'ephemeral': + 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', + 'ciphertext': + '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', + 'mac': 'QzKV/fgAs4U', + }, + }, + }, + }, + }, + }, + }, + 'POST': { + '/client/r0/delete_devices': (var req) => {}, + '/client/r0/account/3pid/add': (var req) => {}, + '/client/r0/account/3pid/bind': (var req) => {}, + '/client/r0/account/3pid/delete': (var req) => + {'id_server_unbind_result': 'success'}, + '/client/r0/account/3pid/unbind': (var req) => + {'id_server_unbind_result': 'success'}, + '/client/r0/account/password': (var req) => {}, + '/client/r0/rooms/1234/report/1234': (var req) => {}, + '/client/r0/search': (var req) => { + 'search_categories': { + 'room_events': { + 'groups': { + 'room_id': { + '!qPewotXpIctQySfjSy:localhost': { + 'order': 1, + 'next_batch': 'BdgFsdfHSf-dsFD', + 'results': ['\$144429830826TWwbB:localhost'] + } + } + }, + 'highlights': ['martians', 'men'], + 'next_batch': '5FdgFsd234dfgsdfFD', + 'count': 1224, + 'results': [ + { + 'rank': 0.00424866, + 'result': { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': + 'This is an example text message' + }, + 'type': 'm.room.message', + 'event_id': '\$144429830826TWwbB:localhost', + 'room_id': '!qPewotXpIctQySfjSy:localhost', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} + } + } + ] + } + } + }, + '/client/r0/account/deactivate': (var req) => + {'id_server_unbind_result': 'success'}, + '/client/r0/user_directory/search': (var req) => { + 'results': [ + { + 'user_id': '@foo:bar.com', + 'display_name': 'Foo', + 'avatar_url': 'mxc://bar.com/foo' + } + ], + 'limited': false + }, + '/client/r0/register/email/requestToken': (var req) => { + 'sid': '123abc', + 'submit_url': 'https://example.org/path/to/submitToken' + }, + '/client/r0/register/msisdn/requestToken': (var req) => { + 'sid': '123abc', + 'submit_url': 'https://example.org/path/to/submitToken' + }, + '/client/r0/account/password/email/requestToken': (var req) => { + 'sid': '123abc', + 'submit_url': 'https://example.org/path/to/submitToken' + }, + '/client/r0/account/password/msisdn/requestToken': (var req) => { + 'sid': '123abc', + 'submit_url': 'https://example.org/path/to/submitToken' + }, + '/client/r0/account/3pid/email/requestToken': (var req) => { + 'sid': '123abc', + 'submit_url': 'https://example.org/path/to/submitToken' + }, + '/client/r0/account/3pid/msisdn/requestToken': (var req) => { + 'sid': '123abc', + 'submit_url': 'https://example.org/path/to/submitToken' + }, + '/client/r0/rooms/!localpart%3Aexample.com/receipt/m.read/%241234%3Aexample.com': + (var req) => {}, + '/client/r0/rooms/!localpart%3Aexample.com/read_markers': (var req) => {}, + '/client/r0/user/${Uri.encodeComponent('alice@example.com')}/filter': + (var req) => {'filter_id': '1234'}, + '/client/r0/publicRooms?server=example.com': (var req) => { + 'chunk': [ + { + 'aliases': ['#murrays:cheese.bar'], + 'canonical_alias': '#murrays:cheese.bar', + 'avatar_url': 'mxc://bleeker.street/CHEDDARandBRIE', + 'guest_can_join': false, + 'name': 'CHEESE', + 'num_joined_members': 37, + 'room_id': '!ol19s:bleecker.street', + 'topic': 'Tasty tasty cheese', + 'world_readable': true + } + ], + 'next_batch': 'p190q', + 'prev_batch': 'p1902', + 'total_room_count_estimate': 115 + }, + '/client/r0/keys/claim': (var req) => { + 'failures': {}, + 'one_time_keys': { + if (decodeJson(req)['one_time_keys']['@alice:example.com'] != + null) + '@alice:example.com': { + 'JLAFKJWSCS': { + 'signed_curve25519:AAAAAQ': { + 'key': 'ikMXajRlkS7Xi9CROrAh3jXnbygk8mLBdSaY9/al0X0', + 'signatures': { + '@alice:example.com': { + 'ed25519:JLAFKJWSCS': + 'XdboCa0Ljoh0Y0i/IVnmMqy/+T1hJyu8BA/nRYniJMQ7QWh/pGS5AsWswdARD+MAX+r4u98Qzk0y27HUddZXDA' + } + } + } + } + }, + if (decodeJson(req)['one_time_keys'] + ['@test:fakeServer.notExisting'] != + null) + '@test:fakeServer.notExisting': { + 'GHTYAJCE': { + 'signed_curve25519:AAAAAQ': { + 'key': 'qc72ve94cA28iuE0fXa98QO3uls39DHWdQlYyvvhGh0', + 'signatures': { + '@test:fakeServer.notExisting': { + 'ed25519:GHTYAJCE': + 'dFwffr5kTKefO7sjnWLMhTzw7oV31nkPIDRxFy5OQT2OP5++Ao0KRbaBZ6qfuT7lW1owKK0Xk3s7QTBvc/eNDA', + }, + }, + }, + }, + }, + } + }, + '/client/r0/rooms/!localpart%3Aexample.com/invite': (var req) => {}, + '/client/r0/rooms/!localpart%3Aexample.com/leave': (var req) => {}, + '/client/r0/rooms/!localpart%3Aexample.com/forget': (var req) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/kick': (var req) => {}, + '/client/r0/rooms/!localpart%3Aexample.com/kick': (var req) => {}, + '/client/r0/rooms/!localpart%3Aexample.com/ban': (var req) => {}, + '/client/r0/rooms/!localpart%3Aexample.com/unban': (var req) => {}, + '/client/r0/rooms/!localpart%3Aexample.com/join': (var req) => + {'room_id': '!localpart:example.com'}, + '/client/r0/join/!localpart%3Aexample.com?server_name=example.com&server_name=example.abc': + (var req) => {'room_id': '!localpart:example.com'}, + '/client/r0/keys/upload': (var req) => { + 'one_time_key_counts': { + 'curve25519': 10, + 'signed_curve25519': + decodeJson(req)['one_time_keys']?.keys?.length ?? 0, + } + }, + '/client/r0/keys/query': (var req) => { + 'failures': {}, + 'device_keys': { + '@alice:example.com': { + 'JLAFKJWSCS': { + 'user_id': '@alice:example.com', + 'device_id': 'JLAFKJWSCS', + 'algorithms': [ + AlgorithmTypes.olmV1Curve25519AesSha2, + AlgorithmTypes.megolmV1AesSha2 + ], + 'keys': { + 'curve25519:JLAFKJWSCS': + 'L+4+JCl8MD63dgo8z5Ta+9QAHXiANyOVSfgbHA5d3H8', + 'ed25519:JLAFKJWSCS': + 'rUFJftIWpFF/jqqz3bexGGYiG8UobKhzkeabqw1v0zM' + }, + 'signatures': { + '@alice:example.com': { + 'ed25519:JLAFKJWSCS': + 'go3mi5o3Ile+Ik+lCEpHmBmyJmKWfnRDCBBvfaVlKsMyha5IORuYcxwEUrAeLyAeeeHvkWDFX+No5eY1jYeKBw' + } + }, + 'unsigned': {'device_display_name': 'Alices mobile phone'} + }, + 'OTHERDEVICE': { + 'user_id': '@alice:example.com', + 'device_id': 'OTHERDEVICE', + 'algorithms': [ + AlgorithmTypes.olmV1Curve25519AesSha2, + AlgorithmTypes.megolmV1AesSha2 + ], + 'keys': { + 'curve25519:OTHERDEVICE': + 'wMIDhiQl5jEXQrTB03ePOSQfR8sA/KMrW0CIfFfXKEE', + 'ed25519:OTHERDEVICE': + '2Lyaj5NB7HPqKZMjZpA/pECXuQ+9wi8AGFdw33y3DuQ' + }, + 'signatures': { + '@alice:example.com': { + 'ed25519:OTHERDEVICE': + 'bwHd6ylISP13AICdDPd0HQd4V6dvvd4vno8/OwUNdm9UAprr3YjkDqVw425I74u2UQAarq9bytBqVqFyD6trAw', + } + }, + }, + }, + '@test:fakeServer.notExisting': { + 'GHTYAJCE': { + 'user_id': '@test:fakeServer.notExisting', + 'device_id': 'GHTYAJCE', + 'algorithms': [ + AlgorithmTypes.olmV1Curve25519AesSha2, + AlgorithmTypes.megolmV1AesSha2 + ], + 'keys': { + 'curve25519:GHTYAJCE': + '7rvl3jORJkBiK4XX1e5TnGnqz068XfYJ0W++Ml63rgk', + 'ed25519:GHTYAJCE': + 'gjL//fyaFHADt9KBADGag8g7F8Up78B/K1zXeiEPLJo' + }, + 'signatures': { + '@test:fakeServer.notExisting': { + 'ed25519:GHTYAJCE': + 'NEQeTgv7ew1IZSLQphWd0y60EdHdcNfHgvoaMQco5XKeIYyiUZIWd7F4x/mkPDjUizv6yWMbTDCWdSg5XcgNBA', + 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': + 'Q4/55vZjEJD7M2EC40bgZqd9Zuy/4C75UPVopJdXeioQVaKtFf6EF0nUUuql0yD+r3hinsZcock0wO6Q2xcoAQ', + }, + }, + }, + 'OTHERDEVICE': { + 'user_id': '@test:fakeServer.notExisting', + 'device_id': 'OTHERDEVICE', + 'algorithms': [ + AlgorithmTypes.olmV1Curve25519AesSha2, + AlgorithmTypes.megolmV1AesSha2 + ], + 'keys': { + 'curve25519:OTHERDEVICE': + 'R96BA0qE1+QAWLp7E1jyWSTJ1VXMLpEdiM2SZHlKMXM', + 'ed25519:OTHERDEVICE': + 'EQo9eYbSygIbOR+tVJziqAY1NI6Gga+JQOVIqJe4mr4' + }, + 'signatures': { + '@test:fakeServer.notExisting': { + 'ed25519:OTHERDEVICE': + '/rT6pVRypJWxGos1QcI7jHL9HwcA83nkHLHqMcRPeLSxXHh4oHWvC0/tl0Xg06ogyiGw4NuB7TpOISvJBdt7BA', + 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': + 'qnjiLl36h/1jlLvcAgt46Igaod2T9lOSnoSVkV0KC+c7vYIjG4QBzXpH+hycfufOT/y+a/kl52dUTLQWctMKCA', + }, + }, + }, + }, + '@othertest:fakeServer.notExisting': { + 'FOXDEVICE': { + 'user_id': '@othertest:fakeServer.notExisting', + 'device_id': 'FOXDEVICE', + 'algorithms': [ + AlgorithmTypes.olmV1Curve25519AesSha2, + AlgorithmTypes.megolmV1AesSha2 + ], + 'keys': { + 'curve25519:FOXDEVICE': + 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg', + 'ed25519:FOXDEVICE': + 'R5/p04tticvdlNIxiiBIP0j9OQWv8ep6eEU6/lWKDxw', + }, + 'signatures': { + '@othertest:fakeServer.notExisting': { + 'ed25519:FOXDEVICE': + '2lJ3atmRIWgkyQNC9gvWEpxwuozsBQsg33M2IMDJqLhx/+g3Ds1vQ683dJsYIu04ORa4U0L9TqieHVpV/7qqDA', + }, + }, + }, + }, + }, + 'master_keys': { + '@test:fakeServer.notExisting': { + 'user_id': '@test:fakeServer.notExisting', + 'usage': ['master'], + 'keys': { + 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': + '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8', + }, + 'signatures': {}, + }, + '@othertest:fakeServer.notExisting': { + 'user_id': '@othertest:fakeServer.notExisting', + 'usage': ['master'], + 'keys': { + 'ed25519:master': 'master', + }, + 'signatures': {}, + }, + }, + 'self_signing_keys': { + '@test:fakeServer.notExisting': { + 'user_id': '@test:fakeServer.notExisting', + 'usage': ['self_signing'], + 'keys': { + 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': + 'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY', + }, + 'signatures': { + '@test:fakeServer.notExisting': { + 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': + 'afkrbGvPn5Zb5zc7Lk9cz2skI3QrzI/L0st1GS+/GATxNjMzc6vKmGu7r9cMb1GJxy4RdeUpfH3L7Fs/fNL1Dw', + }, + }, + }, + '@othertest:fakeServer.notExisting': { + 'user_id': '@othertest:fakeServer.notExisting', + 'usage': ['self_signing'], + 'keys': { + 'ed25519:self_signing': 'self_signing', + }, + 'signatures': {}, + }, + }, + 'user_signing_keys': { + '@test:fakeServer.notExisting': { + 'user_id': '@test:fakeServer.notExisting', + 'usage': ['user_signing'], + 'keys': { + 'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g': + '0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g', + }, + 'signatures': { + '@test:fakeServer.notExisting': { + 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': + 'pvgbZxEbllaElhpiRnb7/uOIUhrglvHCFnpoxr3/5ZrWa0EK/uaefhex9eEV4uBLrHjHg2ymwdNaM7ap9+sBBg', + }, + }, + }, + '@othertest:fakeServer.notExisting': { + 'user_id': '@othertest:fakeServer.notExisting', + 'usage': ['user_signing'], + 'keys': { + 'ed25519:user_signing': 'user_signing', + }, + 'signatures': {}, + }, + }, + }, + '/client/r0/register': (var req) => { + 'user_id': '@testuser:example.com', + 'access_token': '1234', + 'device_id': 'ABCD', + }, + '/client/r0/register?kind=user': (var req) => + {'user_id': '@testuser:example.com'}, + '/client/r0/register?kind=guest': (var req) => + {'user_id': '@testuser:example.com'}, + '/client/r0/rooms/1234/upgrade': (var req) => {}, + '/client/r0/user/1234/openid/request_token': (var req) => { + 'access_token': 'SomeT0kenHere', + 'token_type': 'Bearer', + 'matrix_server_name': 'example.com', + 'expires_in': 3600.0 + }, + '/client/r0/user/@test:fakeServer.notExisting/openid/request_token': + (var req) => { + 'access_token': 'SomeT0kenHere', + 'token_type': 'Bearer', + 'matrix_server_name': 'example.com', + 'expires_in': 3600 + }, + '/client/r0/login': (var req) => { + 'user_id': '@test:fakeServer.notExisting', + 'access_token': 'abc123', + 'device_id': 'GHTYAJCE', + 'well_known': { + 'm.homeserver': {'base_url': 'https://example.org'}, + 'm.identity_server': {'base_url': 'https://id.example.org'} + } + }, + '/media/r0/upload?filename=file.jpeg': (var req) => + {'content_uri': 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'}, + '/client/r0/logout': (var reqI) => {}, + '/client/r0/pushers/set': (var reqI) => {}, + '/client/r0/join/1234': (var reqI) => {'room_id': '1234'}, + '/client/r0/logout/all': (var reqI) => {}, + '/client/r0/createRoom': (var reqI) => { + 'room_id': '!1234:fakeServer.notExisting', + }, + '/client/r0/rooms/!localpart%3Aserver.abc/read_markers': (var reqI) => {}, + '/client/r0/rooms/!localpart:server.abc/kick': (var reqI) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/ban': (var reqI) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/unban': (var reqI) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/invite': (var reqI) => {}, + '/client/unstable/keys/device_signing/upload': (var reqI) { + return {}; + }, + '/client/r0/keys/signatures/upload': (var reqI) => {'failures': {}}, + '/client/unstable/room_keys/version': (var reqI) => {'version': '5'}, + }, + 'PUT': { + '/client/r0/user/%40test%3AfakeServer.notExisting/account_data/m.ignored_user_list': + (var req) => {}, + '/client/r0/presence/${Uri.encodeComponent('@alice:example.com')}/status': + (var req) => {}, + '/client/r0/pushrules/global/content/nocake/enabled': (var req) => {}, + '/client/r0/pushrules/global/content/nocake/actions': (var req) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.history_visibility': + (var req) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.join_rules': + (var req) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.guest_access': + (var req) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/send/m.call.invite/1234': + (var req) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/send/m.call.answer/1234': + (var req) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/send/m.call.candidates/1234': + (var req) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/send/m.call.hangup/1234': + (var req) => {}, + '/client/r0/rooms/!1234%3Aexample.com/redact/1143273582443PhrSn%3Aexample.org/1234': + (var req) => {'event_id': '1234'}, + '/client/r0/pushrules/global/room/!localpart%3Aserver.abc': (var req) => + {}, + '/client/r0/pushrules/global/override/.m.rule.master/enabled': + (var req) => {}, + '/client/r0/pushrules/global/content/nocake?before=1&after=2': + (var req) => {}, + '/client/r0/devices/QBUAZIFURK': (var req) => {}, + '/client/r0/directory/room/%23testalias%3Aexample.com': (var reqI) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/send/m.room.message/testtxid': + (var reqI) => { + 'event_id': '\$event${FakeMatrixApi.eventCounter++}', + }, + '/client/r0/rooms/!localpart%3Aserver.abc/send/m.reaction/testtxid': + (var reqI) => { + 'event_id': '\$event${FakeMatrixApi.eventCounter++}', + }, + '/client/r0/rooms/!localpart%3Aexample.com/typing/%40alice%3Aexample.com': + (var req) => {}, + '/client/r0/rooms/!1234%3Aexample.com/send/m.room.message/1234': + (var reqI) => { + 'event_id': '\$event${FakeMatrixApi.eventCounter++}', + }, + '/client/r0/rooms/!1234%3Aexample.com/send/m.room.message/newresend': + (var reqI) => { + 'event_id': '\$event${FakeMatrixApi.eventCounter++}', + }, + '/client/r0/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': + (var req) => {}, + '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': + (var req) => {}, + '/client/r0/user/%40alice%3Aexample.com/account_data/test.account.data': + (var req) => {}, + '/client/r0/user/%40test%3AfakeServer.notExisting/account_data/best%20animal': + (var req) => {}, + '/client/r0/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data': + (var req) => {}, + '/client/r0/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/account_data/com.famedly.marked_unread': + (var req) => {}, + '/client/r0/user/%40test%3AfakeServer.notExisting/account_data/m.direct': + (var req) => {}, + '/client/r0/user/%40othertest%3AfakeServer.notExisting/account_data/m.direct': + (var req) => {}, + '/client/r0/profile/%40alice%3Aexample.com/displayname': (var reqI) => {}, + '/client/r0/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => {}, + '/client/r0/profile/%40test%3AfakeServer.notExisting/avatar_url': + (var reqI) => {}, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.encryption': + (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.avatar': + (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, + '/client/r0/rooms/!localpart%3Aserver.abc/send/m.room.message/1234': + (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, + '/client/r0/rooms/!localpart%3Aserver.abc/redact/1234/1234': (var reqI) => + {'event_id': 'YUwRidLecu:example.com'}, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.name': + (var reqI) => { + 'event_id': '42', + }, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.topic': + (var reqI) => { + 'event_id': '42', + }, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.pinned_events': + (var reqI) => { + 'event_id': '42', + }, + '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.power_levels': + (var reqI) => { + 'event_id': '42', + }, + '/client/r0/directory/list/room/!localpart%3Aexample.com': (var req) => + {}, + '/client/unstable/room_keys/version/5': (var req) => {}, + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': + (var req) => { + 'etag': 'asdf', + 'count': 1, + }, + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': + (var req) => { + 'etag': 'asdf', + 'count': 1, + }, + '/client/unstable/room_keys/keys?version=5': (var req) => { + 'etag': 'asdf', + 'count': 1, + }, + }, + 'DELETE': { + '/unknown/token': (var req) => {'errcode': 'M_UNKNOWN_TOKEN'}, + '/client/r0/devices/QBUAZIFURK': (var req) => {}, + '/client/r0/directory/room/%23testalias%3Aexample.com': (var reqI) => {}, + '/client/r0/pushrules/global/content/nocake': (var req) => {}, + '/client/r0/pushrules/global/override/!localpart%3Aserver.abc': + (var req) => {}, + '/client/r0/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': + (var req) => {}, + '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': + (var req) => {}, + '/client/unstable/room_keys/version/5': (var req) => {}, + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': + (var req) => { + 'etag': 'asdf', + 'count': 1, + }, + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': + (var req) => { + 'etag': 'asdf', + 'count': 1, + }, + '/client/unstable/room_keys/keys?version=5': (var req) => { + 'etag': 'asdf', + 'count': 1, + }, + }, + }; +} diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart new file mode 100644 index 00000000..d545bf11 --- /dev/null +++ b/test/matrix_api_test.dart @@ -0,0 +1,1915 @@ +/* + * Ansible inventory script used at Famedly GmbH for managing many hosts + * Copyright (C) 2019, 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'dart:typed_data'; +import 'package:logger/logger.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; +import 'package:test/test.dart'; + +import 'fake_matrix_api.dart'; + +void main() { + /// All Tests related to device keys + group('Matrix API', () { + Logs().level = Level.error; + final matrixApi = MatrixApi( + httpClient: FakeMatrixApi(), + ); + test('MatrixException test', () async { + final exception = MatrixException.fromJson({ + 'flows': [ + { + 'stages': ['example.type.foo'] + } + ], + 'params': { + 'example.type.baz': {'example_key': 'foobar'} + }, + 'session': 'xxxxxxyz', + 'completed': ['example.type.foo'] + }); + expect( + exception.authenticationFlows.first.stages.first, 'example.type.foo'); + expect(exception.authenticationParams['example.type.baz'], + {'example_key': 'foobar'}); + expect(exception.session, 'xxxxxxyz'); + expect(exception.completedAuthenticationFlows, ['example.type.foo']); + expect(exception.requireAdditionalAuthentication, true); + expect(exception.retryAfterMs, null); + expect(exception.error, MatrixError.M_UNKNOWN); + expect(exception.errcode, 'M_FORBIDDEN'); + expect(exception.errorMessage, 'Require additional authentication'); + }); + test('triggerNotFoundError', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + bool error; + error = false; + try { + await matrixApi.request(RequestType.GET, '/fake/path'); + } catch (_) { + error = true; + } + expect(error, true); + error = false; + try { + await matrixApi.request(RequestType.POST, '/fake/path'); + } catch (_) { + error = true; + } + expect(error, true); + error = false; + try { + await matrixApi.request(RequestType.PUT, '/fake/path'); + } catch (_) { + error = true; + } + expect(error, true); + error = false; + try { + await matrixApi.request(RequestType.DELETE, '/fake/path'); + } catch (_) { + error = true; + } + expect(error, true); + error = false; + try { + await matrixApi.request(RequestType.GET, '/path/to/auth/error/'); + } catch (exception) { + expect(exception is MatrixException, true); + expect((exception as MatrixException).errcode, 'M_FORBIDDEN'); + expect((exception as MatrixException).error, MatrixError.M_FORBIDDEN); + expect((exception as MatrixException).errorMessage, 'Blabla'); + expect((exception as MatrixException).requireAdditionalAuthentication, + false); + expect( + (exception as MatrixException).toString(), 'M_FORBIDDEN: Blabla'); + error = true; + } + expect(error, true); + matrixApi.homeserver = null; + }); + test('getSupportedVersions', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + final supportedVersions = await matrixApi.requestSupportedVersions(); + expect(supportedVersions.versions.contains('r0.5.0'), true); + expect(supportedVersions.unstableFeatures['m.lazy_load_members'], true); + expect(FakeMatrixApi.api['GET']['/client/versions']({}), + supportedVersions.toJson()); + matrixApi.homeserver = null; + }); + test('getWellKnownInformations', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + final wellKnownInformations = + await matrixApi.requestWellKnownInformations(); + expect(wellKnownInformations.mHomeserver.baseUrl, + 'https://matrix.example.com'); + expect(wellKnownInformations.toJson(), { + 'm.homeserver': {'base_url': 'https://matrix.example.com'}, + 'm.identity_server': {'base_url': 'https://identity.example.com'}, + 'org.example.custom.property': { + 'app_url': 'https://custom.app.example.org' + } + }); + }); + test('getLoginTypes', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + final loginTypes = await matrixApi.requestLoginTypes(); + expect(loginTypes.flows.first.type, 'm.login.password'); + expect(FakeMatrixApi.api['GET']['/client/r0/login']({}), + loginTypes.toJson()); + matrixApi.homeserver = null; + }); + test('login', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + final loginResponse = + await matrixApi.login(userIdentifierType: 'username'); + expect(FakeMatrixApi.api['POST']['/client/r0/login']({}), + loginResponse.toJson()); + matrixApi.homeserver = null; + }); + test('logout', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.logout(); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('logoutAll', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.logoutAll(); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('register', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + final registerResponse = + await matrixApi.register(kind: 'guest', username: 'test'); + expect(FakeMatrixApi.api['POST']['/client/r0/register?kind=guest']({}), + registerResponse.toJson()); + matrixApi.homeserver = null; + }); + test('requestEmailToken', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.requestEmailToken( + 'alice@example.com', + '1234', + 1, + nextLink: 'https://example.com', + idServer: 'https://example.com', + idAccessToken: '1234', + ); + expect( + FakeMatrixApi.api['POST'] + ['/client/r0/register/email/requestToken']({}), + response.toJson()); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestMsisdnToken', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.requestMsisdnToken( + 'en', + '1234', + '1234', + 1, + nextLink: 'https://example.com', + idServer: 'https://example.com', + idAccessToken: '1234', + ); + expect( + FakeMatrixApi.api['POST'] + ['/client/r0/register/email/requestToken']({}), + response.toJson()); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('changePassword', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.changePassword( + '1234', + auth: AuthenticationData.fromJson({ + 'type': 'example.type.foo', + 'session': 'xxxxx', + 'example_credential': 'verypoorsharedsecret' + }), + ); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('resetPasswordUsingEmail', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.resetPasswordUsingEmail( + 'alice@example.com', + '1234', + 1, + nextLink: 'https://example.com', + idServer: 'https://example.com', + idAccessToken: '1234', + ); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('resetPasswordUsingMsisdn', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.resetPasswordUsingMsisdn( + 'en', + '1234', + '1234', + 1, + nextLink: 'https://example.com', + idServer: 'https://example.com', + idAccessToken: '1234', + ); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('deactivateAccount', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.deactivateAccount( + idServer: 'https://example.com', + auth: AuthenticationData.fromJson({ + 'type': 'example.type.foo', + 'session': 'xxxxx', + 'example_credential': 'verypoorsharedsecret' + }), + ); + expect(response, IdServerUnbindResult.success); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('usernameAvailable', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + final loginResponse = await matrixApi.usernameAvailable('testuser'); + expect(loginResponse, true); + matrixApi.homeserver = null; + }); + test('getThirdPartyIdentifiers', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.requestThirdPartyIdentifiers(); + expect(FakeMatrixApi.api['GET']['/client/r0/account/3pid']({}), + {'threepids': response.map((t) => t.toJson()).toList()}); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('addThirdPartyIdentifier', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.addThirdPartyIdentifier('1234', '1234', + auth: AuthenticationData.fromJson({'type': 'm.login.dummy'})); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('bindThirdPartyIdentifier', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.bindThirdPartyIdentifier( + '1234', + '1234', + 'https://example.com', + '1234', + ); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('deleteThirdPartyIdentifier', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.deleteThirdPartyIdentifier( + 'alice@example.com', + ThirdPartyIdentifierMedium.email, + idServer: 'https://example.com', + ); + expect(response, IdServerUnbindResult.success); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('unbindThirdPartyIdentifier', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.unbindThirdPartyIdentifier( + 'alice@example.com', + ThirdPartyIdentifierMedium.email, + 'https://example.com', + ); + expect(response, IdServerUnbindResult.success); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestEmailValidationToken', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.requestEmailValidationToken( + 'alice@example.com', + '1234', + 1, + nextLink: 'https://example.com', + idServer: 'https://example.com', + idAccessToken: '1234', + ); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestMsisdnValidationToken', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.requestMsisdnValidationToken( + 'en', + '1234', + '1234', + 1, + nextLink: 'https://example.com', + idServer: 'https://example.com', + idAccessToken: '1234', + ); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestMsisdnValidationToken', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.whoAmI(); + expect(response, 'alice@example.com'); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('getServerCapabilities', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.requestServerCapabilities(); + expect(FakeMatrixApi.api['GET']['/client/r0/capabilities']({}), + {'capabilities': response.toJson()}); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('uploadFilter', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = + await matrixApi.uploadFilter('alice@example.com', Filter()); + expect(response, '1234'); + final filter = Filter( + room: RoomFilter( + notRooms: ['!1234'], + rooms: ['!1234'], + ephemeral: StateFilter( + limit: 10, + senders: ['@alice:example.com'], + types: ['type1'], + notTypes: ['type2'], + notRooms: ['!1234'], + notSenders: ['@bob:example.com'], + lazyLoadMembers: true, + includeRedundantMembers: false, + containsUrl: true, + ), + includeLeave: true, + state: StateFilter(), + timeline: StateFilter(), + accountData: StateFilter(limit: 10, types: ['type1']), + ), + presence: EventFilter( + limit: 10, + senders: ['@alice:example.com'], + types: ['type1'], + notRooms: ['!1234'], + notSenders: ['@bob:example.com'], + ), + eventFormat: EventFormat.client, + eventFields: ['type', 'content', 'sender'], + accountData: EventFilter( + types: ['m.accountdatatest'], + notSenders: ['@alice:example.com'], + ), + ); + expect(filter.toJson(), { + 'room': { + 'not_rooms': ['!1234'], + 'rooms': ['!1234'], + 'ephemeral': { + 'limit': 10, + 'types': ['type1'], + 'not_rooms': ['!1234'], + 'not_senders': ['@bob:example.com'], + 'not_types': ['type2'], + 'lazy_load_members': ['type2'], + 'include_redundant_members': ['type2'], + 'contains_url': ['type2'] + }, + 'account_data': { + 'limit': 10, + 'types': ['type1'], + }, + 'include_leave': true, + 'state': {}, + 'timeline': {}, + }, + 'presence': { + 'limit': 10, + 'types': ['type1'], + 'not_rooms': ['!1234'], + 'not_senders': ['@bob:example.com'] + }, + 'event_format': 'client', + 'event_fields': ['type', 'content', 'sender'], + 'account_data': { + 'types': ['m.accountdatatest'], + 'not_senders': ['@alice:example.com'] + }, + }); + await matrixApi.uploadFilter( + 'alice@example.com', + filter, + ); + final filterMap = { + 'room': { + 'state': { + 'types': ['m.room.*'], + 'not_rooms': ['!726s6s6q:example.com'] + }, + 'timeline': { + 'limit': 10, + 'types': ['m.room.message'], + 'not_rooms': ['!726s6s6q:example.com'], + 'not_senders': ['@spam:example.com'] + }, + 'ephemeral': { + 'types': ['m.receipt', 'm.typing'], + 'not_rooms': ['!726s6s6q:example.com'], + 'not_senders': ['@spam:example.com'] + } + }, + 'presence': { + 'types': ['m.presence'], + 'not_senders': ['@alice:example.com'] + }, + 'account_data': { + 'types': ['m.accountdatatest'], + 'not_senders': ['@alice:example.com'] + }, + 'event_format': 'client', + 'event_fields': ['type', 'content', 'sender'] + }; + expect(filterMap, Filter.fromJson(filterMap).toJson()); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('downloadFilter', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + await matrixApi.downloadFilter('alice@example.com', '1234'); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('sync', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + final response = await matrixApi.sync( + filter: '{}', + since: '1234', + fullState: false, + setPresence: PresenceType.unavailable, + timeout: 15, + ); + expect( + FakeMatrixApi.api['GET'][ + '/client/r0/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15']( + {}) as Map, + response.toJson()); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestEvent', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final event = + await matrixApi.requestEvent('!localpart:server.abc', '1234'); + expect(event.eventId, '143273582443PhrSn:example.org'); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestStateContent', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.requestStateContent( + '!localpart:server.abc', + 'm.room.member', + '@getme:example.com', + ); + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestStates', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final states = await matrixApi.requestStates('!localpart:server.abc'); + expect(states.length, 4); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestMembers', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final states = await matrixApi.requestMembers( + '!localpart:server.abc', + at: '1234', + membership: Membership.join, + notMembership: Membership.leave, + ); + expect(states.length, 1); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestJoinedMembers', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final states = await matrixApi.requestJoinedMembers( + '!localpart:server.abc', + ); + expect(states.length, 1); + expect(states['@bar:example.com'].toJson(), { + 'display_name': 'Bar', + 'avatar_url': 'mxc://riot.ovh/printErCATzZijQsSDWorRaK' + }); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestMessages', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final timelineHistoryResponse = await matrixApi.requestMessages( + '!localpart:server.abc', + '1234', + Direction.b, + limit: 10, + filter: '{"lazy_load_members":true}', + to: '1234', + ); + + expect( + FakeMatrixApi.api['GET'][ + '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&dir=b&to=1234&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']( + {}) as Map, + timelineHistoryResponse.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('sendState', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final eventId = await matrixApi.sendState( + '!localpart:server.abc', 'm.room.avatar', {'url': 'mxc://1234'}); + + expect(eventId, 'YUwRidLecu:example.com'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('sendMessage', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final eventId = await matrixApi.sendMessage( + '!localpart:server.abc', + 'm.room.message', + '1234', + {'body': 'hello world', 'msgtype': 'm.text'}, + ); + + expect(eventId, 'YUwRidLecu:example.com'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('redact', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final eventId = await matrixApi.redact( + '!localpart:server.abc', + '1234', + '1234', + reason: 'hello world', + ); + + expect(eventId, 'YUwRidLecu:example.com'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('createRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = await matrixApi.createRoom( + visibility: Visibility.public, + roomAliasName: '#testroom:example.com', + name: 'testroom', + topic: 'just for testing', + invite: ['@bob:example.com'], + invite3pid: [], + roomVersion: '2', + creationContent: {}, + initialState: [], + preset: CreateRoomPreset.public_chat, + isDirect: false, + powerLevelContentOverride: {}, + ); + + expect(roomId, '!1234:fakeServer.notExisting'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('createRoomAlias', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.createRoomAlias( + '#testalias:example.com', + '!1234:example.com', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestRoomAliasInformations', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomAliasInformations = + await matrixApi.requestRoomAliasInformations( + '#testalias:example.com', + ); + + expect( + FakeMatrixApi.api['GET'] + ['/client/r0/directory/room/%23testalias%3Aexample.com']({}), + roomAliasInformations.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('removeRoomAlias', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.removeRoomAlias('#testalias:example.com'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestRoomAliases', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final list = await matrixApi.requestRoomAliases('!localpart:example.com'); + expect(list.length, 3); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestJoinedRooms', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final list = await matrixApi.requestJoinedRooms(); + expect(list.length, 1); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('inviteToRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.inviteToRoom( + '!localpart:example.com', '@bob:example.com'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('joinRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!localpart:example.com'; + final response = await matrixApi.joinRoom( + roomId, + thirdPidSignedSender: '@bob:example.com', + thirdPidSignedmxid: '@alice:example.com', + thirdPidSignedToken: '1234', + thirdPidSignedSiganture: { + 'example.org': {'ed25519:0': 'some9signature'} + }, + ); + expect(response, roomId); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('joinRoomOrAlias', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!localpart:example.com'; + final response = await matrixApi.joinRoomOrAlias( + roomId, + servers: ['example.com', 'example.abc'], + thirdPidSignedSender: '@bob:example.com', + thirdPidSignedmxid: '@alice:example.com', + thirdPidSignedToken: '1234', + thirdPidSignedSiganture: { + 'example.org': {'ed25519:0': 'some9signature'} + }, + ); + expect(response, roomId); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('leave', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.leaveRoom('!localpart:example.com'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('forget', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.forgetRoom('!localpart:example.com'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('kickFromRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.kickFromRoom( + '!localpart:example.com', + '@bob:example.com', + reason: 'test', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('banFromRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.banFromRoom( + '!localpart:example.com', + '@bob:example.com', + reason: 'test', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('unbanInRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.unbanInRoom( + '!localpart:example.com', + '@bob:example.com', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestRoomVisibility', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final visibility = + await matrixApi.requestRoomVisibility('!localpart:example.com'); + expect(visibility, Visibility.public); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setRoomVisibility', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setRoomVisibility( + '!localpart:example.com', Visibility.private); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestPublicRooms', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestPublicRooms( + limit: 10, + since: '1234', + server: 'example.com', + ); + + expect( + FakeMatrixApi.api['GET'][ + '/client/r0/publicRooms?limit=10&since=1234&server=example.com']({}), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('searchPublicRooms', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.searchPublicRooms( + limit: 10, + since: '1234', + server: 'example.com', + genericSearchTerm: 'test', + includeAllNetworks: false, + thirdPartyInstanceId: 'id', + ); + + expect( + FakeMatrixApi.api['POST'] + ['/client/r0/publicRooms?server=example.com']({}), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('searchUser', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.searchUser( + 'test', + limit: 10, + ); + + expect(FakeMatrixApi.api['POST']['/client/r0/user_directory/search']({}), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setDisplayname', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setDisplayname('@alice:example.com', 'Alice M'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestDisplayname', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.requestDisplayname('@alice:example.com'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setAvatarUrl', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setAvatarUrl( + '@alice:example.com', + Uri.parse('mxc://test'), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestAvatarUrl', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestAvatarUrl('@alice:example.com'); + expect(response, Uri.parse('mxc://test')); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestProfile', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestProfile('@alice:example.com'); + expect( + FakeMatrixApi.api['GET'] + ['/client/r0/profile/%40alice%3Aexample.com']({}), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestTurnServerCredentials', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestTurnServerCredentials(); + expect(FakeMatrixApi.api['GET']['/client/r0/voip/turnServer']({}), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('sendTypingNotification', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.sendTypingNotification( + '@alice:example.com', + '!localpart:example.com', + true, + timeout: 10, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('sendReceiptMarker', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.sendReceiptMarker( + '!localpart:example.com', + '\$1234:example.com', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('sendReadMarker', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.sendReadMarker( + '!localpart:example.com', + '\$1234:example.com', + readReceiptLocationEventId: '\$1234:example.com', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('sendPresence', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.sendPresence( + '@alice:example.com', + PresenceType.offline, + statusMsg: 'test', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestPresence', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestPresence( + '@alice:example.com', + ); + expect( + FakeMatrixApi.api['GET'][ + '/client/r0/presence/${Uri.encodeComponent('@alice:example.com')}/status']({}), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('upload', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + final response = await matrixApi.upload(Uint8List(0), 'file.jpeg'); + expect(response, 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'); + var throwsException = false; + try { + await matrixApi.upload(Uint8List(0), 'file.jpg'); + } on MatrixException catch (_) { + throwsException = true; + } + expect(throwsException, true); + matrixApi.homeserver = null; + }); + test('requestOpenGraphDataForUrl', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final openGraphData = await matrixApi.requestOpenGraphDataForUrl( + Uri.parse('https://matrix.org'), + ts: 10, + ); + expect( + FakeMatrixApi.api['GET'] + ['/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']({}), + openGraphData.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestMaxUploadSize', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestMaxUploadSize(); + expect(response, 50000000); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('sendToDevice', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.sendToDevice('m.test', '1234', { + '@alice:example.com': { + 'TLLBEANAAG': {'example_content_key': 'value'} + } + }); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestDevices', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final devices = await matrixApi.requestDevices(); + expect(FakeMatrixApi.api['GET']['/client/r0/devices']({})['devices'], + devices.map((i) => i.toJson()).toList()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestDevice', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.requestDevice('QBUAZIFURK'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setDeviceMetadata', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setDeviceMetadata('QBUAZIFURK', displayName: 'test'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('deleteDevice', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.deleteDevice('QBUAZIFURK', + auth: AuthenticationData.fromJson({})); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('deleteDevices', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi + .deleteDevices(['QBUAZIFURK'], auth: AuthenticationData.fromJson({})); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('uploadDeviceKeys', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.uploadDeviceKeys( + deviceKeys: MatrixDeviceKeys( + '@alice:example.com', + 'ABCD', + ['caesar-chiffre'], + {}, + {}, + unsigned: {}, + ), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestDeviceKeys', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestDeviceKeys( + { + '@alice:example.com': [], + }, + timeout: 10, + token: '1234', + ); + expect( + response + .deviceKeys['@alice:example.com']['JLAFKJWSCS'].deviceDisplayName, + 'Alices mobile phone'); + expect( + FakeMatrixApi.api['POST'] + ['/client/r0/keys/query']({'device_keys': {}}), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestOneTimeKeys', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestOneTimeKeys( + { + '@alice:example.com': {'JLAFKJWSCS': 'signed_curve25519'} + }, + timeout: 10, + ); + expect( + FakeMatrixApi.api['POST']['/client/r0/keys/claim']({ + 'one_time_keys': { + '@alice:example.com': {'JLAFKJWSCS': 'signed_curve25519'} + } + }), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestDeviceListsUpdate', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.requestDeviceListsUpdate('1234', '1234'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('uploadDeviceSigningKeys', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final masterKey = MatrixCrossSigningKey.fromJson({ + 'user_id': '@test:fakeServer.notExisting', + 'usage': ['master'], + 'keys': { + 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': + '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8', + }, + 'signatures': {}, + }); + final selfSigningKey = MatrixCrossSigningKey.fromJson({ + 'user_id': '@test:fakeServer.notExisting', + 'usage': ['self_signing'], + 'keys': { + 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': + 'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY', + }, + 'signatures': {}, + }); + final userSigningKey = MatrixCrossSigningKey.fromJson({ + 'user_id': '@test:fakeServer.notExisting', + 'usage': ['user_signing'], + 'keys': { + 'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g': + '0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g', + }, + 'signatures': {}, + }); + await matrixApi.uploadDeviceSigningKeys( + masterKey: masterKey, + selfSigningKey: selfSigningKey, + userSigningKey: userSigningKey); + }); + test('uploadKeySignatures', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final key1 = MatrixDeviceKeys.fromJson({ + 'user_id': '@alice:example.com', + 'device_id': 'JLAFKJWSCS', + 'algorithms': [ + AlgorithmTypes.olmV1Curve25519AesSha2, + AlgorithmTypes.megolmV1AesSha2 + ], + 'keys': { + 'curve25519:JLAFKJWSCS': + '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI', + 'ed25519:JLAFKJWSCS': 'lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI' + }, + 'signatures': { + '@alice:example.com': { + 'ed25519:JLAFKJWSCS': + 'dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA' + } + }, + 'unsigned': {'device_display_name': 'Alices mobile phone'}, + }); + final key2 = MatrixDeviceKeys.fromJson({ + 'user_id': '@alice:example.com', + 'device_id': 'JLAFKJWSCS', + 'algorithms': [ + AlgorithmTypes.olmV1Curve25519AesSha2, + AlgorithmTypes.megolmV1AesSha2 + ], + 'keys': { + 'curve25519:JLAFKJWSCS': + '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI', + 'ed25519:JLAFKJWSCS': 'lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI' + }, + 'signatures': { + '@alice:example.com': {'ed25519:OTHERDEVICE': 'OTHERSIG'} + }, + 'unsigned': {'device_display_name': 'Alices mobile phone'}, + }); + final ret = await matrixApi.uploadKeySignatures([key1, key2]); + expect( + FakeMatrixApi.api['POST']['/client/r0/keys/signatures/upload']({}), + ret.toJson(), + ); + }); + test('requestPushers', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestPushers(); + expect( + FakeMatrixApi.api['GET']['/client/r0/pushers']({}), + {'pushers': response.map((i) => i.toJson()).toList()}, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setPusher', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setPusher( + Pusher( + '1234', + 'app.id', + 'appDisplayName', + 'deviceDisplayName', + 'en', + PusherData( + format: 'event_id_only', url: Uri.parse('https://matrix.org')), + profileTag: 'tag', + kind: 'http', + ), + append: true, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestNotifications', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestNotifications( + from: '1234', + limit: 10, + only: '1234', + ); + expect( + FakeMatrixApi.api['GET'] + ['/client/r0/notifications?from=1234&limit=10&only=1234']({}), + response.toJson(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestPushRules', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestPushRules(); + expect( + FakeMatrixApi.api['GET']['/client/r0/pushrules']({}), + {'global': response.toJson()}, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestPushRule', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestPushRule( + 'global', PushRuleKind.content, 'nocake'); + expect( + FakeMatrixApi.api['GET'] + ['/client/r0/pushrules/global/content/nocake']({}), + response.toJson(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('deletePushRule', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.deletePushRule('global', PushRuleKind.content, 'nocake'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setPushRule', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setPushRule( + 'global', + PushRuleKind.content, + 'nocake', + [PushRuleAction.notify], + before: '1', + after: '2', + conditions: [ + PushConditions( + 'event_match', + key: 'key', + pattern: 'pattern', + isOperator: '+', + ) + ], + pattern: 'pattern', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestPushRuleEnabled', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final enabled = await matrixApi.requestPushRuleEnabled( + 'global', PushRuleKind.content, 'nocake'); + expect(enabled, true); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('enablePushRule', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.enablePushRule( + 'global', + PushRuleKind.content, + 'nocake', + true, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestPushRuleActions', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final actions = await matrixApi.requestPushRuleActions( + 'global', PushRuleKind.content, 'nocake'); + expect(actions.first, PushRuleAction.notify); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setPushRuleActions', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setPushRuleActions( + 'global', + PushRuleKind.content, + 'nocake', + [PushRuleAction.dont_notify], + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('globalSearch', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.globalSearch({}); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('globalSearch', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestEvents( + from: '1234', roomId: '!1234', timeout: 10); + expect( + FakeMatrixApi.api['GET'] + ['/client/r0/events?from=1234&timeout=10&roomId=%211234']({}), + response.toJson(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestRoomTags', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestRoomTags( + '@alice:example.com', '!localpart:example.com'); + expect( + FakeMatrixApi.api['GET'][ + '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']({}), + {'tags': response.map((k, v) => MapEntry(k, v.toJson()))}, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('addRoomTag', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.addRoomTag( + '@alice:example.com', + '!localpart:example.com', + 'testtag', + order: 0.5, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('addRoomTag', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.removeRoomTag( + '@alice:example.com', + '!localpart:example.com', + 'testtag', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setAccountData', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setAccountData( + '@alice:example.com', + 'test.account.data', + {'foo': 'bar'}, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestAccountData', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.requestAccountData( + '@alice:example.com', + 'test.account.data', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('setRoomAccountData', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.setRoomAccountData( + '@alice:example.com', + '1234', + 'test.account.data', + {'foo': 'bar'}, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestRoomAccountData', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.requestRoomAccountData( + '@alice:example.com', + '1234', + 'test.account.data', + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestWhoIsInfo', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestWhoIsInfo('@alice:example.com'); + expect( + FakeMatrixApi.api['GET'] + ['/client/r0/admin/whois/%40alice%3Aexample.com']({}), + response.toJson(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestEventContext', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestEventContext('1234', '1234', + limit: 10, filter: '{}'); + expect( + FakeMatrixApi.api['GET'] + ['/client/r0/rooms/1234/context/1234?filter=%7B%7D&limit=10']({}), + response.toJson(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('reportEvent', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.reportEvent( + '1234', + '1234', + 'test', + -100, + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestSupportedProtocols', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestSupportedProtocols(); + expect( + FakeMatrixApi.api['GET']['/client/r0/thirdparty/protocols']({}), + response.map((k, v) => MapEntry(k, v.toJson())), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestSupportedProtocol', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestSupportedProtocol('irc'); + expect( + FakeMatrixApi.api['GET']['/client/r0/thirdparty/protocol/irc']({}), + response.toJson(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestThirdPartyLocations', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestThirdPartyLocations('irc'); + expect( + FakeMatrixApi.api['GET']['/client/r0/thirdparty/location/irc']({}), + response.map((i) => i.toJson()).toList(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestThirdPartyUsers', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestThirdPartyUsers('irc'); + expect( + FakeMatrixApi.api['GET']['/client/r0/thirdparty/user/irc']({}), + response.map((i) => i.toJson()).toList(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestThirdPartyLocationsByAlias', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = + await matrixApi.requestThirdPartyLocationsByAlias('1234'); + expect( + FakeMatrixApi.api['GET'] + ['/client/r0/thirdparty/location?alias=1234']({}), + response.map((i) => i.toJson()).toList(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestThirdPartyUsersByUserId', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestThirdPartyUsersByUserId('1234'); + expect( + FakeMatrixApi.api['GET']['/client/r0/thirdparty/user?userid=1234']({}), + response.map((i) => i.toJson()).toList(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('requestOpenIdCredentials', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = await matrixApi.requestOpenIdCredentials('1234'); + expect( + FakeMatrixApi.api['POST'] + ['/client/r0/user/1234/openid/request_token']({}), + response.toJson(), + ); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('upgradeRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.upgradeRoom('1234', '2'); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); + test('createRoomKeysBackup', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final algorithm = RoomKeysAlgorithmType.v1Curve25519AesSha2; + final authData = { + 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', + 'signatures': {}, + }; + final ret = await matrixApi.createRoomKeysBackup(algorithm, authData); + expect( + FakeMatrixApi.api['POST'] + ['/client/unstable/room_keys/version']({})['version'], + ret); + }); + test('getRoomKeysBackup', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final ret = await matrixApi.getRoomKeysBackup(); + expect(FakeMatrixApi.api['GET']['/client/unstable/room_keys/version']({}), + ret.toJson()); + }); + test('updateRoomKeysBackup', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final algorithm = RoomKeysAlgorithmType.v1Curve25519AesSha2; + final authData = { + 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', + 'signatures': {}, + }; + await matrixApi.updateRoomKeysBackup('5', algorithm, authData); + }); + test('deleteRoomKeysBackup', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + await matrixApi.deleteRoomKeysBackup('5'); + }); + test('storeRoomKeysSingleKey', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final session = RoomKeysSingleKey.fromJson({ + 'first_message_index': 0, + 'forwarded_count': 0, + 'is_verified': true, + 'session_data': { + 'ephemeral': 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', + 'ciphertext': + '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', + 'mac': 'QzKV/fgAs4U', + }, + }); + final ret = await matrixApi.storeRoomKeysSingleKey( + roomId, sessionId, '5', session); + expect( + FakeMatrixApi.api['PUT'][ + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + ret.toJson()); + }); + test('getRoomKeysSingleKey', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final ret = await matrixApi.getRoomKeysSingleKey(roomId, sessionId, '5'); + expect( + FakeMatrixApi.api['GET'][ + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + ret.toJson()); + }); + test('deleteRoomKeysSingleKey', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final ret = + await matrixApi.deleteRoomKeysSingleKey(roomId, sessionId, '5'); + expect( + FakeMatrixApi.api['DELETE'][ + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + ret.toJson()); + }); + test('storeRoomKeysRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final session = RoomKeysRoom.fromJson({ + 'sessions': { + sessionId: { + 'first_message_index': 0, + 'forwarded_count': 0, + 'is_verified': true, + 'session_data': { + 'ephemeral': 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', + 'ciphertext': + '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', + 'mac': 'QzKV/fgAs4U', + }, + }, + }, + }); + final ret = await matrixApi.storeRoomKeysRoom(roomId, '5', session); + expect( + FakeMatrixApi.api['PUT'][ + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + ret.toJson()); + }); + test('getRoomKeysRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final ret = await matrixApi.getRoomKeysRoom(roomId, '5'); + expect( + FakeMatrixApi.api['GET'][ + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + ret.toJson()); + }); + test('deleteRoomKeysRoom', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final ret = await matrixApi.deleteRoomKeysRoom(roomId, '5'); + expect( + FakeMatrixApi.api['DELETE'][ + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + ret.toJson()); + }); + test('storeRoomKeys', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final session = RoomKeys.fromJson({ + 'rooms': { + roomId: { + 'sessions': { + sessionId: { + 'first_message_index': 0, + 'forwarded_count': 0, + 'is_verified': true, + 'session_data': { + 'ephemeral': 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', + 'ciphertext': + '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', + 'mac': 'QzKV/fgAs4U', + }, + }, + }, + }, + }, + }); + final ret = await matrixApi.storeRoomKeys('5', session); + expect( + FakeMatrixApi.api['PUT'] + ['/client/unstable/room_keys/keys?version=5']({}), + ret.toJson()); + }); + test('getRoomKeys', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final ret = await matrixApi.getRoomKeys('5'); + expect( + FakeMatrixApi.api['GET'] + ['/client/unstable/room_keys/keys?version=5']({}), + ret.toJson()); + }); + test('deleteRoomKeys', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final ret = await matrixApi.deleteRoomKeys('5'); + expect( + FakeMatrixApi.api['DELETE'] + ['/client/unstable/room_keys/keys?version=5']({}), + ret.toJson()); + }); + test('AuthenticationData', () { + final json = {'session': '1234', 'type': 'm.login.dummy'}; + expect(AuthenticationData.fromJson(json).toJson(), json); + expect( + AuthenticationData(session: '1234', type: 'm.login.dummy').toJson(), + json); + }); + test('AuthenticationRecaptcha', () { + final json = { + 'session': '1234', + 'type': 'm.login.recaptcha', + 'response': 'a', + }; + expect(AuthenticationRecaptcha.fromJson(json).toJson(), json); + expect(AuthenticationRecaptcha(session: '1234', response: 'a').toJson(), + json); + }); + test('AuthenticationToken', () { + final json = { + 'session': '1234', + 'type': 'm.login.token', + 'token': 'a', + 'txn_id': '1' + }; + expect(AuthenticationToken.fromJson(json).toJson(), json); + expect( + AuthenticationToken(session: '1234', token: 'a', txnId: '1').toJson(), + json); + }); + test('AuthenticationThreePidCreds', () { + final json = { + 'type': 'm.login.email.identity', + 'threepidCreds': [ + { + 'sid': '1', + 'client_secret': 'a', + 'id_server': 'matrix.org', + 'id_access_token': 'a', + }, + ], + 'threepid_creds': [ + { + 'sid': '1', + 'client_secret': 'a', + 'id_server': 'matrix.org', + 'id_access_token': 'a', + }, + ], + 'session': '1', + }; + expect(AuthenticationThreePidCreds.fromJson(json).toJson(), json); + expect( + AuthenticationThreePidCreds( + session: '1', + type: AuthenticationTypes.emailIdentity, + threepidCreds: [ + ThreepidCreds( + sid: '1', + clientSecret: 'a', + idServer: 'matrix.org', + idAccessToken: 'a', + ), + ]).toJson(), + json); + }); + test('AuthenticationIdentifier', () { + final json = {'type': 'm.id.user'}; + expect(AuthenticationIdentifier.fromJson(json).toJson(), json); + expect(AuthenticationIdentifier(type: 'm.id.user').toJson(), json); + }); + test('AuthenticationPassword', () { + final json = { + 'type': 'm.login.password', + 'identifier': {'type': 'm.id.user', 'user': 'a'}, + 'password': 'a', + 'session': '1', + 'user': 'a', + }; + expect(AuthenticationPassword.fromJson(json).toJson(), json); + expect( + AuthenticationPassword( + session: '1', + password: 'a', + user: 'a', + identifier: AuthenticationUserIdentifier(user: 'a'), + ).toJson(), + json); + json['identifier'] = { + 'type': 'm.id.thirdparty', + 'medium': 'a', + 'address': 'a', + }; + expect(AuthenticationPassword.fromJson(json).toJson(), json); + expect( + AuthenticationPassword( + session: '1', + password: 'a', + user: 'a', + identifier: + AuthenticationThirdPartyIdentifier(medium: 'a', address: 'a'), + ).toJson(), + json); + json['identifier'] = { + 'type': 'm.id.phone', + 'country': 'a', + 'phone': 'a', + }; + expect(AuthenticationPassword.fromJson(json).toJson(), json); + expect( + AuthenticationPassword( + session: '1', + password: 'a', + user: 'a', + identifier: AuthenticationPhoneIdentifier(country: 'a', phone: 'a'), + ).toJson(), + json); + }); + }); +} From af2024816f4016e80476d555e50c3af96f2545d6 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 30 Dec 2020 12:46:02 +0100 Subject: [PATCH 002/174] docs: Clean up --- README.md | 23 +++++++++++------------ example/matrix_api_lite_example.dart | 2 -- pubspec.yaml | 6 +++--- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1b0a69b6..c407e7d1 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,21 @@ -A library for Dart developers. +# Matrix API Lite -Created from templates made available by Stagehand under a BSD-style -[license](https://github.com/dart-lang/stagehand/blob/master/LICENSE). +This package is a dead simple data model over the client-server specification of https://matrix.org and is mostly used as a base for a more complete Matrix SDK. +It doesn't contain any logic and just provides methods for all API endpoints and json parser for all objects. It is intended to be as close to the specificaton +as possible so we get a 1:1 relationship with the API. More complex logic like a sync loop or a data model for rooms should be implemented in a more complete +Matrix SDK. ## Usage A simple usage example: ```dart -import 'package:matrix_api_lite/matrix_api_lite.dart'; +import 'package:matrix_api_lite/src/matrix_api.dart'; -main() { - var awesome = new Awesome(); +void main() async { + final api = MatrixApi(homeserver: Uri.parse('https://matrix.org')); + final capabilities = await api.requestServerCapabilities(); + print(capabilities.toJson()); } -``` -## Features and bugs - -Please file feature requests and bugs at the [issue tracker][tracker]. - -[tracker]: http://example.com/issues/replaceme +``` \ No newline at end of file diff --git a/example/matrix_api_lite_example.dart b/example/matrix_api_lite_example.dart index c588cf51..0699acc4 100644 --- a/example/matrix_api_lite_example.dart +++ b/example/matrix_api_lite_example.dart @@ -1,5 +1,3 @@ -//import 'package:matrix_api_lite/matrix_api_lite.dart'; - import 'package:matrix_api_lite/src/matrix_api.dart'; void main() async { diff --git a/pubspec.yaml b/pubspec.yaml index f796df2b..603bd7ca 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: matrix_api_lite -description: A starting point for Dart libraries or applications. -# version: 1.0.0 -# homepage: https://www.example.com +description: Dead simple data model for the matrix.org client-server API. +version: 0.1.0 +homepage: https://famedly.com environment: sdk: '>=2.10.0 <3.0.0' From 03901f4612b365a4faa1a9c662155641fbb2125b Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 31 Dec 2020 10:03:30 +0100 Subject: [PATCH 003/174] fix: Add marked unread to lib --- lib/matrix_api_lite.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index d90c0a1b..ce3ff7df 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -33,6 +33,7 @@ export 'src/model/filter.dart'; export 'src/model/keys_query_response.dart'; export 'src/model/login_response.dart'; export 'src/model/login_types.dart'; +export 'src/model/marked_unread.dart'; export 'src/model/matrix_connection_exception.dart'; export 'src/model/matrix_event.dart'; export 'src/model/matrix_exception.dart'; From e15c21bea85dca38fb676d120b4ec94426ac79a4 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 31 Dec 2020 10:15:24 +0100 Subject: [PATCH 004/174] fix: Remove empty readme --- lib/src/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib/src/README.md diff --git a/lib/src/README.md b/lib/src/README.md deleted file mode 100644 index e69de29b..00000000 From 62d36c2c39a51fb3c2b1afdb2b9e8a4ebc61e296 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 31 Dec 2020 10:19:50 +0100 Subject: [PATCH 005/174] docs: Update Contributing --- CONTRIBUTING.md | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a5c23f7a..1d9171e7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,10 @@ -# Contributing code to famedly talk +# Contributing code to Matrix API Lite -Everyone is welcome to contribute code to FamedlySDK, provided that they are willing to license their contributions under the same license as the project itself. -Please follow these rules when contributing code to famedly talk: +Everyone is welcome to contribute code to Matrix API Lite, provided that they are willing to license their contributions under the same license as the project itself. +Please follow these rules when contributing code to Matrix API Lite: ## Merge Requests: -- Never ever just push something directly to the master branch! +- Never ever just push something directly to the main branch! - Create a new branch or fork this project and send a Merge Request. - Only Merge Requests with a working CI can be merged. - Only Merge Requests with at least one code reviewer can be merged. @@ -14,27 +14,11 @@ Please follow these rules when contributing code to famedly talk: ## Branches ### Naming -Branches should get named by this pattern: `[Module Name]-[Type]-[Detail]`. - -That means for example: "users-fix-attach-roles-issue#765". - -Modules are various parts of the App. This can for example be the directory list or the chat room. - -Types can be one of these: -- **feature** -- **enhance** -- **cleanup** -- **refactor** -- **fix** -- **hotfix** (should rarely get used) - -The Detail part of the pattern should be a short description of what the branch delivers. +Branches should get named by this pattern: `[Author]/[Description]`. ## Commit Messages -Commit Messages should get written in this pattern: `[[Module Name]] [Commit Message]`. -That means for example: "[users] add fetch users endpoint". - +Please use [conventional commit messages](https://www.conventionalcommits.org/en/v1.0.0-beta.2/). ## File structure: - Every file must be named by the class and must be capitalized in the beginning. @@ -48,7 +32,6 @@ flutter format lib/**/*/*.dart ## Code quality: - Don't repeat yourself! Use local variables, functions, classes. -- Don't mix UI and business logic in the same environment. - Write tests for new classes, functions and widgets. - Keep it simple stupid: https://en.wikipedia.org/wiki/KISS_principle - Describe all of your classes, methods and attributes using **dartdoc** comments. Read this for more informations: https://dart.dev/guides/language/effective-dart/documentation \ No newline at end of file From 3340a1e5405fc315f1ce54981f269caa20104203 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 31 Dec 2020 10:25:54 +0100 Subject: [PATCH 006/174] refactor: Remove markedunread --- lib/matrix_api_lite.dart | 1 - lib/src/model/marked_unread.dart | 43 -------------------------------- 2 files changed, 44 deletions(-) delete mode 100644 lib/src/model/marked_unread.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index ce3ff7df..d90c0a1b 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -33,7 +33,6 @@ export 'src/model/filter.dart'; export 'src/model/keys_query_response.dart'; export 'src/model/login_response.dart'; export 'src/model/login_types.dart'; -export 'src/model/marked_unread.dart'; export 'src/model/matrix_connection_exception.dart'; export 'src/model/matrix_event.dart'; export 'src/model/matrix_exception.dart'; diff --git a/lib/src/model/marked_unread.dart b/lib/src/model/marked_unread.dart deleted file mode 100644 index c3223c78..00000000 --- a/lib/src/model/marked_unread.dart +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Famedly Matrix SDK - * Copyright (C) 2019, 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -mixin EventType { - static const String MarkedUnread = 'com.famedly.marked_unread'; -} - -class MarkedUnread { - bool unread; - - MarkedUnread(this.unread); - - MarkedUnread.fromJson(Map json) { - if (!(json['unread'] is bool)) { - unread = false; - } else { - unread = json['unread']; - } - } - - Map toJson() { - final data = {}; - if (unread != null) { - data['unread'] = unread; - } - return data; - } -} From 68e653083533f2965be53538936a7474675a0ed6 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 31 Dec 2020 10:33:59 +0100 Subject: [PATCH 007/174] fix: Current version --- lib/matrix_api_lite.dart | 1 + .../model/auth/authentication_password.dart | 1 + lib/src/model/basic_event.dart | 4 ++- lib/src/model/keys_query_response.dart | 5 ++- lib/src/model/matrix_event.dart | 9 ++--- lib/src/model/matrix_keys.dart | 7 ++-- .../model/one_time_keys_claim_response.dart | 8 +++-- lib/src/model/room_keys_info.dart | 2 +- lib/src/model/server_capabilities.dart | 4 ++- lib/src/model/third_party_identifier.dart | 2 +- lib/src/model/third_party_location.dart | 4 ++- lib/src/model/third_party_user.dart | 4 ++- lib/src/utils/map_copy_extension.dart | 33 +++++++++++++++++++ 13 files changed, 64 insertions(+), 20 deletions(-) create mode 100644 lib/src/utils/map_copy_extension.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index d90c0a1b..f2ac3ec3 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -20,6 +20,7 @@ library matrix_api_lite; export 'src/matrix_api.dart'; export 'src/utils/logs.dart'; +export 'src/utils/map_copy_extension.dart'; export 'src/utils/try_get_map_extension.dart'; export 'src/model/algorithm_types.dart'; export 'src/model/basic_event.dart'; diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index fe28d1c8..6ae4df3f 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -17,6 +17,7 @@ */ import 'authentication_user_identifier.dart'; + import 'authentication_data.dart'; import 'authentication_identifier.dart'; import 'authentication_phone_identifier.dart'; diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 095b2b21..7a91f559 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class BasicEvent { String type; Map content; @@ -27,7 +29,7 @@ class BasicEvent { BasicEvent.fromJson(Map json) { type = json['type']; - content = Map.from(json['content']); + content = (json['content'] as Map).copy(); } Map toJson() { final data = {}; diff --git a/lib/src/model/keys_query_response.dart b/lib/src/model/keys_query_response.dart index b368b4f1..ed02e87d 100644 --- a/lib/src/model/keys_query_response.dart +++ b/lib/src/model/keys_query_response.dart @@ -17,6 +17,7 @@ */ import 'matrix_keys.dart'; +import '../utils/map_copy_extension.dart'; class KeysQueryResponse { Map failures; @@ -26,9 +27,7 @@ class KeysQueryResponse { Map userSigningKeys; KeysQueryResponse.fromJson(Map json) { - failures = json['failures'] != null - ? Map.from(json['failures']) - : null; + failures = (json['failures'] as Map)?.copy(); deviceKeys = json['device_keys'] != null ? (json['device_keys'] as Map).map( (k, v) => MapEntry( diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index 2f5f35f0..83fe7596 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -17,6 +17,7 @@ */ import 'stripped_state_event.dart'; +import '../utils/map_copy_extension.dart'; class MatrixEvent extends StrippedStateEvent { String eventId; @@ -38,12 +39,8 @@ class MatrixEvent extends StrippedStateEvent { roomId = json['room_id']; originServerTs = DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']); - unsigned = json['unsigned'] != null - ? Map.from(json['unsigned']) - : null; - prevContent = json['prev_content'] != null - ? Map.from(json['prev_content']) - : null; + unsigned = (json['unsigned'] as Map)?.copy(); + prevContent = (json['prev_content'] as Map)?.copy(); redacts = json['redacts']; } diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index c0f00386..317ef390 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class MatrixSignableKey { String userId; String identifier; @@ -33,13 +35,12 @@ class MatrixSignableKey { _json = json; userId = json['user_id']; keys = Map.from(json['keys']); + // we need to manually copy to ensure that our map is Map> signatures = json['signatures'] is Map ? Map>.from((json['signatures'] as Map) .map((k, v) => MapEntry(k, Map.from(v)))) : null; - unsigned = json['unsigned'] is Map - ? Map.from(json['unsigned']) - : null; + unsigned = (json['unsigned'] as Map)?.copy(); } Map toJson() { diff --git a/lib/src/model/one_time_keys_claim_response.dart b/lib/src/model/one_time_keys_claim_response.dart index 7834211c..7607892b 100644 --- a/lib/src/model/one_time_keys_claim_response.dart +++ b/lib/src/model/one_time_keys_claim_response.dart @@ -16,13 +16,17 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class OneTimeKeysClaimResponse { Map failures; Map> oneTimeKeys; OneTimeKeysClaimResponse.fromJson(Map json) { - failures = Map.from(json['failures'] ?? {}); - oneTimeKeys = Map>.from(json['one_time_keys']); + failures = (json['failures'] as Map)?.copy() ?? {}; + // We still need a Map<...>.from(...) to ensure all second-level entries are also maps + oneTimeKeys = Map>.from( + (json['one_time_keys'] as Map).copy()); } Map toJson() { diff --git a/lib/src/model/room_keys_info.dart b/lib/src/model/room_keys_info.dart index 2ac7ac3c..037b20e1 100644 --- a/lib/src/model/room_keys_info.dart +++ b/lib/src/model/room_keys_info.dart @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import 'algorithm_types.dart'; +import '../../matrix_api_lite.dart'; enum RoomKeysAlgorithmType { v1Curve25519AesSha2 } diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart index 0e449e9d..0ae7c1ee 100644 --- a/lib/src/model/server_capabilities.dart +++ b/lib/src/model/server_capabilities.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + enum RoomVersionStability { stable, unstable } class ServerCapabilities { @@ -30,7 +32,7 @@ class ServerCapabilities { mRoomVersions = json['m.room_versions'] != null ? MRoomVersions.fromJson(json['m.room_versions']) : null; - customCapabilities = Map.from(json); + customCapabilities = json.copy(); customCapabilities.remove('m.change_password'); customCapabilities.remove('m.room_versions'); } diff --git a/lib/src/model/third_party_identifier.dart b/lib/src/model/third_party_identifier.dart index 14fe31d8..25d5b469 100644 --- a/lib/src/model/third_party_identifier.dart +++ b/lib/src/model/third_party_identifier.dart @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import '../../matrix_api_lite.dart'; +import '../matrix_api.dart'; class ThirdPartyIdentifier { ThirdPartyIdentifierMedium medium; diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index 68083805..39546099 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class ThirdPartyLocation { String alias; String protocol; @@ -24,7 +26,7 @@ class ThirdPartyLocation { ThirdPartyLocation.fromJson(Map json) { alias = json['alias']; protocol = json['protocol']; - fields = Map.from(json['fields']); + fields = (json['fields'] as Map).copy(); } Map toJson() { diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index fd84f907..e19818e8 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import '../utils/map_copy_extension.dart'; + class ThirdPartyUser { String userId; String protocol; @@ -24,7 +26,7 @@ class ThirdPartyUser { ThirdPartyUser.fromJson(Map json) { userId = json['userid']; protocol = json['protocol']; - fields = Map.from(json['fields']); + fields = (json['fields'] as Map).copy(); } Map toJson() { diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart new file mode 100644 index 00000000..84ddc272 --- /dev/null +++ b/lib/src/utils/map_copy_extension.dart @@ -0,0 +1,33 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +extension MapCopyExtension on Map { + /// Deep-copies a given json map + Map copy() { + final copy = Map.from(this); + for (final entry in copy.entries) { + if (entry.value is Map) { + copy[entry.key] = (entry.value as Map).copy(); + } + if (entry.value is List) { + copy[entry.key] = List.from(entry.value); + } + } + return copy; + } +} From 6b283d5c50f7b0df244a7b4efcaed20113aec45d Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 31 Dec 2020 10:33:59 +0100 Subject: [PATCH 008/174] fix: Current version --- {test => lib}/fake_matrix_api.dart | 1 + lib/src/matrix_api.dart | 2 +- lib/src/model/algorithm_types.dart | 2 +- lib/src/model/auth/authentication_data.dart | 2 +- lib/src/model/auth/authentication_identifier.dart | 2 +- lib/src/model/auth/authentication_password.dart | 2 +- lib/src/model/auth/authentication_phone_identifier.dart | 2 +- lib/src/model/auth/authentication_recaptcha.dart | 2 +- lib/src/model/auth/authentication_third_party_identifier.dart | 2 +- lib/src/model/auth/authentication_three_pid_creds.dart | 2 +- lib/src/model/auth/authentication_token.dart | 2 +- lib/src/model/auth/authentication_types.dart | 2 +- lib/src/model/auth/authentication_user_identifier.dart | 2 +- lib/src/model/basic_event.dart | 2 +- lib/src/model/basic_event_with_sender.dart | 2 +- lib/src/model/basic_room_event.dart | 2 +- lib/src/model/device.dart | 2 +- lib/src/model/event_context.dart | 2 +- lib/src/model/event_types.dart | 2 +- lib/src/model/events_sync_update.dart | 2 +- lib/src/model/filter.dart | 2 +- lib/src/model/keys_query_response.dart | 2 +- lib/src/model/login_response.dart | 2 +- lib/src/model/login_types.dart | 2 +- lib/src/model/matrix_connection_exception.dart | 2 +- lib/src/model/matrix_event.dart | 2 +- lib/src/model/matrix_exception.dart | 2 +- lib/src/model/matrix_keys.dart | 2 +- lib/src/model/message_types.dart | 2 +- lib/src/model/notifications_query_response.dart | 2 +- lib/src/model/one_time_keys_claim_response.dart | 2 +- lib/src/model/open_graph_data.dart | 2 +- lib/src/model/open_id_credentials.dart | 2 +- lib/src/model/presence.dart | 2 +- lib/src/model/presence_content.dart | 2 +- lib/src/model/profile.dart | 2 +- lib/src/model/public_rooms_response.dart | 2 +- lib/src/model/push_rule_set.dart | 2 +- lib/src/model/pusher.dart | 2 +- lib/src/model/request_token_response.dart | 2 +- lib/src/model/room_alias_informations.dart | 2 +- lib/src/model/room_keys_info.dart | 2 +- lib/src/model/room_keys_keys.dart | 2 +- lib/src/model/room_summary.dart | 2 +- lib/src/model/server_capabilities.dart | 2 +- lib/src/model/stripped_state_event.dart | 2 +- lib/src/model/supported_protocol.dart | 2 +- lib/src/model/supported_versions.dart | 2 +- lib/src/model/sync_update.dart | 2 +- lib/src/model/tag.dart | 2 +- lib/src/model/third_party_identifier.dart | 2 +- lib/src/model/third_party_location.dart | 2 +- lib/src/model/third_party_user.dart | 2 +- lib/src/model/timeline_history_response.dart | 2 +- lib/src/model/turn_server_credentials.dart | 2 +- lib/src/model/upload_key_signatures_response.dart | 2 +- lib/src/model/user_search_result.dart | 2 +- lib/src/model/well_known_informations.dart | 2 +- lib/src/model/who_is_info.dart | 2 +- lib/src/utils/logs.dart | 2 +- lib/src/utils/map_copy_extension.dart | 2 +- test/matrix_api_test.dart | 3 +-- 62 files changed, 62 insertions(+), 62 deletions(-) rename {test => lib}/fake_matrix_api.dart (99%) diff --git a/test/fake_matrix_api.dart b/lib/fake_matrix_api.dart similarity index 99% rename from test/fake_matrix_api.dart rename to lib/fake_matrix_api.dart index 8c980a4f..f43b1050 100644 --- a/test/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -34,6 +34,7 @@ Map decodeJson(dynamic data) { return data; } +/// A mock http client for testing purposes. class FakeMatrixApi extends MockClient { static final calledEndpoints = >{}; static int eventCounter = 0; diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index a1c055c4..d3c30def 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/algorithm_types.dart b/lib/src/model/algorithm_types.dart index cc657d7b..580e5f6a 100644 --- a/lib/src/model/algorithm_types.dart +++ b/lib/src/model/algorithm_types.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index ad340400..6d380639 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index be5a4bfa..42267c49 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index 6ae4df3f..ed9afd0e 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index 452f01c2..c25d602b 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index 3d0816ad..42e117fb 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index 5a4ab496..6dc1a3b1 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 1ddb45e7..87d4a00d 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index 23db3755..ce705039 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_types.dart b/lib/src/model/auth/authentication_types.dart index 34e357f3..46237bc0 100644 --- a/lib/src/model/auth/authentication_types.dart +++ b/lib/src/model/auth/authentication_types.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index 66e6091e..d8dffb59 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 7a91f559..372b2853 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index 0e50bd86..c48a4d6c 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index de8ee75c..a9990421 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/device.dart b/lib/src/model/device.dart index aa089a4b..367b6c42 100644 --- a/lib/src/model/device.dart +++ b/lib/src/model/device.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/event_context.dart b/lib/src/model/event_context.dart index 9d23961c..0332063f 100644 --- a/lib/src/model/event_context.dart +++ b/lib/src/model/event_context.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index 36b63a7d..fa506591 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart index 46b0fb3f..65a90b43 100644 --- a/lib/src/model/events_sync_update.dart +++ b/lib/src/model/events_sync_update.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/filter.dart b/lib/src/model/filter.dart index b1e18a7d..5886b83f 100644 --- a/lib/src/model/filter.dart +++ b/lib/src/model/filter.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/keys_query_response.dart b/lib/src/model/keys_query_response.dart index ed02e87d..4faaa46d 100644 --- a/lib/src/model/keys_query_response.dart +++ b/lib/src/model/keys_query_response.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/login_response.dart b/lib/src/model/login_response.dart index a29627ad..7d575246 100644 --- a/lib/src/model/login_response.dart +++ b/lib/src/model/login_response.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/login_types.dart b/lib/src/model/login_types.dart index 5cb67d22..647f7b97 100644 --- a/lib/src/model/login_types.dart +++ b/lib/src/model/login_types.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/matrix_connection_exception.dart b/lib/src/model/matrix_connection_exception.dart index b45192e0..4d89b454 100644 --- a/lib/src/model/matrix_connection_exception.dart +++ b/lib/src/model/matrix_connection_exception.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index 83fe7596..451dbb36 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index fa292c9c..05818130 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index 317ef390..d61f9bd9 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/message_types.dart b/lib/src/model/message_types.dart index 90fe2d08..c0bbf9a6 100644 --- a/lib/src/model/message_types.dart +++ b/lib/src/model/message_types.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/notifications_query_response.dart b/lib/src/model/notifications_query_response.dart index f9eff6b9..0f6f99d5 100644 --- a/lib/src/model/notifications_query_response.dart +++ b/lib/src/model/notifications_query_response.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/one_time_keys_claim_response.dart b/lib/src/model/one_time_keys_claim_response.dart index 7607892b..a0fc43c5 100644 --- a/lib/src/model/one_time_keys_claim_response.dart +++ b/lib/src/model/one_time_keys_claim_response.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/open_graph_data.dart b/lib/src/model/open_graph_data.dart index d2d8eb60..28ffbdf5 100644 --- a/lib/src/model/open_graph_data.dart +++ b/lib/src/model/open_graph_data.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/open_id_credentials.dart b/lib/src/model/open_id_credentials.dart index 1d2902bd..976aae64 100644 --- a/lib/src/model/open_id_credentials.dart +++ b/lib/src/model/open_id_credentials.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index c8044063..87ab5603 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index df9d2f08..4d50fbea 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/profile.dart b/lib/src/model/profile.dart index 37eace57..1a5a4180 100644 --- a/lib/src/model/profile.dart +++ b/lib/src/model/profile.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/public_rooms_response.dart b/lib/src/model/public_rooms_response.dart index f227dfb7..3bfe6f64 100644 --- a/lib/src/model/public_rooms_response.dart +++ b/lib/src/model/public_rooms_response.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/push_rule_set.dart b/lib/src/model/push_rule_set.dart index 2c9682b5..3df87126 100644 --- a/lib/src/model/push_rule_set.dart +++ b/lib/src/model/push_rule_set.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/pusher.dart b/lib/src/model/pusher.dart index 00bc2803..8c080949 100644 --- a/lib/src/model/pusher.dart +++ b/lib/src/model/pusher.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart index ee264be6..41df73cc 100644 --- a/lib/src/model/request_token_response.dart +++ b/lib/src/model/request_token_response.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/room_alias_informations.dart b/lib/src/model/room_alias_informations.dart index d6b81640..8fd7cfa2 100644 --- a/lib/src/model/room_alias_informations.dart +++ b/lib/src/model/room_alias_informations.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/room_keys_info.dart b/lib/src/model/room_keys_info.dart index 037b20e1..b482d192 100644 --- a/lib/src/model/room_keys_info.dart +++ b/lib/src/model/room_keys_info.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart index 69870665..4c47489d 100644 --- a/lib/src/model/room_keys_keys.dart +++ b/lib/src/model/room_keys_keys.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index 67b6a8f3..21064d1a 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart index 0ae7c1ee..de2d6fa0 100644 --- a/lib/src/model/server_capabilities.dart +++ b/lib/src/model/server_capabilities.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index 29c0740a..8749c89e 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart index 736b7d6d..c1b56f4f 100644 --- a/lib/src/model/supported_protocol.dart +++ b/lib/src/model/supported_protocol.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/supported_versions.dart b/lib/src/model/supported_versions.dart index 33ab8c49..0a834a99 100644 --- a/lib/src/model/supported_versions.dart +++ b/lib/src/model/supported_versions.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index c36c09e1..fb3b867d 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/tag.dart b/lib/src/model/tag.dart index f63d6e57..1c77be30 100644 --- a/lib/src/model/tag.dart +++ b/lib/src/model/tag.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/third_party_identifier.dart b/lib/src/model/third_party_identifier.dart index 25d5b469..a1c396c5 100644 --- a/lib/src/model/third_party_identifier.dart +++ b/lib/src/model/third_party_identifier.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index 39546099..0331f7b6 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index e19818e8..3a2d8db9 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/timeline_history_response.dart b/lib/src/model/timeline_history_response.dart index e5752762..ec04c60b 100644 --- a/lib/src/model/timeline_history_response.dart +++ b/lib/src/model/timeline_history_response.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/turn_server_credentials.dart b/lib/src/model/turn_server_credentials.dart index bf350f50..d6f28c6f 100644 --- a/lib/src/model/turn_server_credentials.dart +++ b/lib/src/model/turn_server_credentials.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/upload_key_signatures_response.dart b/lib/src/model/upload_key_signatures_response.dart index 325aa5e7..9c665e15 100644 --- a/lib/src/model/upload_key_signatures_response.dart +++ b/lib/src/model/upload_key_signatures_response.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/user_search_result.dart b/lib/src/model/user_search_result.dart index 1d498083..04beea6d 100644 --- a/lib/src/model/user_search_result.dart +++ b/lib/src/model/user_search_result.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/well_known_informations.dart b/lib/src/model/well_known_informations.dart index feba960c..a12cd171 100644 --- a/lib/src/model/well_known_informations.dart +++ b/lib/src/model/well_known_informations.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/model/who_is_info.dart b/lib/src/model/who_is_info.dart index 6a266852..fee8dbe2 100644 --- a/lib/src/model/who_is_info.dart +++ b/lib/src/model/who_is_info.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2019, 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index 7e15f379..35b1d2cc 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart index 84ddc272..ef821e9b 100644 --- a/lib/src/utils/map_copy_extension.dart +++ b/lib/src/utils/map_copy_extension.dart @@ -1,5 +1,5 @@ /* - * Famedly Matrix SDK + * Matrix API Lite * Copyright (C) 2020 Famedly GmbH * * This program is free software: you can redistribute it and/or modify diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index d545bf11..83c73acc 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -18,11 +18,10 @@ import 'dart:typed_data'; import 'package:logger/logger.dart'; +import 'package:matrix_api_lite/fake_matrix_api.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; -import 'fake_matrix_api.dart'; - void main() { /// All Tests related to device keys group('Matrix API', () { From ec019698bf63b9981434636b628eee242c65ac5e Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 31 Dec 2020 10:52:05 +0100 Subject: [PATCH 009/174] fix: Missing package --- CHANGELOG.md | 4 ++-- pubspec.yaml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 687440ba..5ed54dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,3 @@ -## 1.0.0 +## 0.1.0 -- Initial version, created by Stagehand +- Initial version \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 603bd7ca..2ef3820c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,6 +9,7 @@ environment: dependencies: http: ^0.12.2 logger: ^0.9.4 + mime: ^0.9.7 dev_dependencies: pedantic: ^1.9.0 From 48cdb18f18456556ad38418dd8c2ae0d70ad64ad Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 31 Dec 2020 11:00:15 +0100 Subject: [PATCH 010/174] chore: More tests --- test/map_copy_extension_test.dart | 39 ++++++++++++++++++++++++ test/try_get_map_extension_test.dart | 45 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 test/map_copy_extension_test.dart create mode 100644 test/try_get_map_extension_test.dart diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart new file mode 100644 index 00000000..958f01eb --- /dev/null +++ b/test/map_copy_extension_test.dart @@ -0,0 +1,39 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'package:matrix_api_lite/matrix_api_lite.dart'; +import 'package:test/test.dart'; + +void main() { + group('Map-copy-extension', () { + test('it should work', () { + final original = { + 'attr': 'fox', + 'child': { + 'attr': 'bunny', + 'list': [1, 2], + }, + }; + final copy = original.copy(); + original['child']['attr'] = 'raccoon'; + expect(copy['child']['attr'], 'bunny'); + original['child']['list'].add(3); + expect(copy['child']['list'], [1, 2]); + }); + }); +} diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart new file mode 100644 index 00000000..886700e3 --- /dev/null +++ b/test/try_get_map_extension_test.dart @@ -0,0 +1,45 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'package:matrix_api_lite/matrix_api_lite.dart'; +import 'package:test/test.dart'; + +void main() { + group('Try-get-map-extension', () { + test('it should work', () { + final data = { + 'str': 'foxies', + 'int': 42, + 'list': [2, 3, 4], + 'map': { + 'beep': 'boop', + }, + }; + expect(data.tryGet('str'), 'foxies'); + expect(data.tryGet('str'), null); + expect(data.tryGet('int'), 42); + expect(data.tryGet('list'), [2, 3, 4]); + expect(data.tryGet>('map')?.tryGet('beep'), + 'boop'); + expect(data.tryGet>('map')?.tryGet('meep'), + null); + expect(data.tryGet>('pam')?.tryGet('beep'), + null); + }); + }); +} From ede938c1055b915d6f182495c9c2c45a9107494d Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 4 Jan 2021 10:18:41 +0100 Subject: [PATCH 011/174] docs: Update license header --- lib/fake_matrix_api.dart | 2 +- lib/matrix_api_lite.dart | 2 +- lib/src/matrix_api.dart | 2 +- lib/src/model/algorithm_types.dart | 2 +- lib/src/model/auth/authentication_data.dart | 2 +- lib/src/model/auth/authentication_identifier.dart | 2 +- lib/src/model/auth/authentication_password.dart | 2 +- lib/src/model/auth/authentication_phone_identifier.dart | 2 +- lib/src/model/auth/authentication_recaptcha.dart | 2 +- lib/src/model/auth/authentication_third_party_identifier.dart | 2 +- lib/src/model/auth/authentication_three_pid_creds.dart | 2 +- lib/src/model/auth/authentication_token.dart | 2 +- lib/src/model/auth/authentication_types.dart | 2 +- lib/src/model/auth/authentication_user_identifier.dart | 2 +- lib/src/model/basic_event.dart | 2 +- lib/src/model/basic_event_with_sender.dart | 2 +- lib/src/model/basic_room_event.dart | 2 +- lib/src/model/device.dart | 2 +- lib/src/model/event_context.dart | 2 +- lib/src/model/event_types.dart | 2 +- lib/src/model/events_sync_update.dart | 2 +- lib/src/model/filter.dart | 2 +- lib/src/model/keys_query_response.dart | 2 +- lib/src/model/login_response.dart | 2 +- lib/src/model/login_types.dart | 2 +- lib/src/model/matrix_connection_exception.dart | 2 +- lib/src/model/matrix_event.dart | 2 +- lib/src/model/matrix_exception.dart | 2 +- lib/src/model/matrix_keys.dart | 2 +- lib/src/model/message_types.dart | 2 +- lib/src/model/notifications_query_response.dart | 2 +- lib/src/model/one_time_keys_claim_response.dart | 2 +- lib/src/model/open_graph_data.dart | 2 +- lib/src/model/open_id_credentials.dart | 2 +- lib/src/model/presence.dart | 2 +- lib/src/model/presence_content.dart | 2 +- lib/src/model/profile.dart | 2 +- lib/src/model/public_rooms_response.dart | 2 +- lib/src/model/push_rule_set.dart | 2 +- lib/src/model/pusher.dart | 2 +- lib/src/model/request_token_response.dart | 2 +- lib/src/model/room_alias_informations.dart | 2 +- lib/src/model/room_summary.dart | 2 +- lib/src/model/server_capabilities.dart | 2 +- lib/src/model/stripped_state_event.dart | 2 +- lib/src/model/supported_protocol.dart | 2 +- lib/src/model/supported_versions.dart | 2 +- lib/src/model/sync_update.dart | 2 +- lib/src/model/tag.dart | 2 +- lib/src/model/third_party_identifier.dart | 2 +- lib/src/model/third_party_location.dart | 2 +- lib/src/model/third_party_user.dart | 2 +- lib/src/model/timeline_history_response.dart | 2 +- lib/src/model/turn_server_credentials.dart | 2 +- lib/src/model/user_search_result.dart | 2 +- lib/src/model/well_known_informations.dart | 2 +- lib/src/model/who_is_info.dart | 2 +- test/matrix_api_test.dart | 2 +- 58 files changed, 58 insertions(+), 58 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index f43b1050..dad87872 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1,6 +1,6 @@ /* * Ansible inventory script used at Famedly GmbH for managing many hosts - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index f2ac3ec3..e7c0ed26 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index d3c30def..6c63a363 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/algorithm_types.dart b/lib/src/model/algorithm_types.dart index 580e5f6a..aa3fb0e2 100644 --- a/lib/src/model/algorithm_types.dart +++ b/lib/src/model/algorithm_types.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 6d380639..2a363dd6 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index 42267c49..cbb0981d 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index ed9afd0e..2fe57f63 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index c25d602b..8045f346 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index 42e117fb..1b714fd8 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index 6dc1a3b1..241c2058 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 87d4a00d..5d9eb800 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index ce705039..928f6b10 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_types.dart b/lib/src/model/auth/authentication_types.dart index 46237bc0..b5536204 100644 --- a/lib/src/model/auth/authentication_types.dart +++ b/lib/src/model/auth/authentication_types.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index d8dffb59..ab1e8bd4 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 372b2853..108dd0fd 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index c48a4d6c..b99fb343 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index a9990421..dd902730 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/device.dart b/lib/src/model/device.dart index 367b6c42..fbdbe6fc 100644 --- a/lib/src/model/device.dart +++ b/lib/src/model/device.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/event_context.dart b/lib/src/model/event_context.dart index 0332063f..75ed1e4f 100644 --- a/lib/src/model/event_context.dart +++ b/lib/src/model/event_context.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index fa506591..921e87a7 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart index 65a90b43..502dc9c2 100644 --- a/lib/src/model/events_sync_update.dart +++ b/lib/src/model/events_sync_update.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/filter.dart b/lib/src/model/filter.dart index 5886b83f..5e86c4a2 100644 --- a/lib/src/model/filter.dart +++ b/lib/src/model/filter.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/keys_query_response.dart b/lib/src/model/keys_query_response.dart index 4faaa46d..95a2eac8 100644 --- a/lib/src/model/keys_query_response.dart +++ b/lib/src/model/keys_query_response.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/login_response.dart b/lib/src/model/login_response.dart index 7d575246..76c5a006 100644 --- a/lib/src/model/login_response.dart +++ b/lib/src/model/login_response.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/login_types.dart b/lib/src/model/login_types.dart index 647f7b97..554be30a 100644 --- a/lib/src/model/login_types.dart +++ b/lib/src/model/login_types.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/matrix_connection_exception.dart b/lib/src/model/matrix_connection_exception.dart index 4d89b454..3ba584e4 100644 --- a/lib/src/model/matrix_connection_exception.dart +++ b/lib/src/model/matrix_connection_exception.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index 451dbb36..17dbee60 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 05818130..bcb112cb 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index d61f9bd9..b3c12ab8 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/message_types.dart b/lib/src/model/message_types.dart index c0bbf9a6..e3bd6f38 100644 --- a/lib/src/model/message_types.dart +++ b/lib/src/model/message_types.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/notifications_query_response.dart b/lib/src/model/notifications_query_response.dart index 0f6f99d5..b22ace0b 100644 --- a/lib/src/model/notifications_query_response.dart +++ b/lib/src/model/notifications_query_response.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/one_time_keys_claim_response.dart b/lib/src/model/one_time_keys_claim_response.dart index a0fc43c5..785ef945 100644 --- a/lib/src/model/one_time_keys_claim_response.dart +++ b/lib/src/model/one_time_keys_claim_response.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/open_graph_data.dart b/lib/src/model/open_graph_data.dart index 28ffbdf5..2dc72813 100644 --- a/lib/src/model/open_graph_data.dart +++ b/lib/src/model/open_graph_data.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/open_id_credentials.dart b/lib/src/model/open_id_credentials.dart index 976aae64..8851a473 100644 --- a/lib/src/model/open_id_credentials.dart +++ b/lib/src/model/open_id_credentials.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index 87ab5603..fb05599b 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index 4d50fbea..e89ec4a9 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/profile.dart b/lib/src/model/profile.dart index 1a5a4180..ec36928b 100644 --- a/lib/src/model/profile.dart +++ b/lib/src/model/profile.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/public_rooms_response.dart b/lib/src/model/public_rooms_response.dart index 3bfe6f64..e713b24c 100644 --- a/lib/src/model/public_rooms_response.dart +++ b/lib/src/model/public_rooms_response.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/push_rule_set.dart b/lib/src/model/push_rule_set.dart index 3df87126..858080bd 100644 --- a/lib/src/model/push_rule_set.dart +++ b/lib/src/model/push_rule_set.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/pusher.dart b/lib/src/model/pusher.dart index 8c080949..fd49859f 100644 --- a/lib/src/model/pusher.dart +++ b/lib/src/model/pusher.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart index 41df73cc..2ce7051b 100644 --- a/lib/src/model/request_token_response.dart +++ b/lib/src/model/request_token_response.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/room_alias_informations.dart b/lib/src/model/room_alias_informations.dart index 8fd7cfa2..70c88645 100644 --- a/lib/src/model/room_alias_informations.dart +++ b/lib/src/model/room_alias_informations.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index 21064d1a..bae41f99 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart index de2d6fa0..c1c00205 100644 --- a/lib/src/model/server_capabilities.dart +++ b/lib/src/model/server_capabilities.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index 8749c89e..43f6cac8 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart index c1b56f4f..97e25521 100644 --- a/lib/src/model/supported_protocol.dart +++ b/lib/src/model/supported_protocol.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/supported_versions.dart b/lib/src/model/supported_versions.dart index 0a834a99..2b362570 100644 --- a/lib/src/model/supported_versions.dart +++ b/lib/src/model/supported_versions.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index fb3b867d..32a3caa9 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/tag.dart b/lib/src/model/tag.dart index 1c77be30..8b6fe8af 100644 --- a/lib/src/model/tag.dart +++ b/lib/src/model/tag.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/third_party_identifier.dart b/lib/src/model/third_party_identifier.dart index a1c396c5..bdfd8714 100644 --- a/lib/src/model/third_party_identifier.dart +++ b/lib/src/model/third_party_identifier.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index 0331f7b6..41e21f23 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index 3a2d8db9..8c51e876 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/timeline_history_response.dart b/lib/src/model/timeline_history_response.dart index ec04c60b..863929ef 100644 --- a/lib/src/model/timeline_history_response.dart +++ b/lib/src/model/timeline_history_response.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/turn_server_credentials.dart b/lib/src/model/turn_server_credentials.dart index d6f28c6f..2b7d2394 100644 --- a/lib/src/model/turn_server_credentials.dart +++ b/lib/src/model/turn_server_credentials.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/user_search_result.dart b/lib/src/model/user_search_result.dart index 04beea6d..bfdeafe6 100644 --- a/lib/src/model/user_search_result.dart +++ b/lib/src/model/user_search_result.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/well_known_informations.dart b/lib/src/model/well_known_informations.dart index a12cd171..f7eeed59 100644 --- a/lib/src/model/well_known_informations.dart +++ b/lib/src/model/well_known_informations.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/lib/src/model/who_is_info.dart b/lib/src/model/who_is_info.dart index fee8dbe2..86289804 100644 --- a/lib/src/model/who_is_info.dart +++ b/lib/src/model/who_is_info.dart @@ -1,6 +1,6 @@ /* * Matrix API Lite - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 83c73acc..a673911b 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1,6 +1,6 @@ /* * Ansible inventory script used at Famedly GmbH for managing many hosts - * Copyright (C) 2019, 2020 Famedly GmbH + * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as From 9d727fa1f0a63d84160845b17d5e39d357ea0e36 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Mon, 4 Jan 2021 09:27:24 +0000 Subject: [PATCH 012/174] Delete LICENSE --- LICENSE | 661 -------------------------------------------------------- 1 file changed, 661 deletions(-) delete mode 100644 LICENSE diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 096ad991..00000000 --- a/LICENSE +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - famedlySDK - Copyright (C) 2019 famedly - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. From 52c771b793673556fd87c6633b79d15b1fb6a777 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Mon, 4 Jan 2021 09:27:45 +0000 Subject: [PATCH 013/174] Add LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d4b01570 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Matrix API Lite + +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. From 128df8d8ebefd3da917e9bbf06e83c60fa865d7f Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 7 Jan 2021 13:55:57 +0100 Subject: [PATCH 014/174] feat: Add encryption content --- lib/matrix_api_lite.dart | 2 + .../model/events/room_encrypted_content.dart | 71 ++++++++++++++++ .../model/events/room_encryption_content.dart | 30 +++++++ test/event_content_test.dart | 82 +++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 lib/src/model/events/room_encrypted_content.dart create mode 100644 lib/src/model/events/room_encryption_content.dart create mode 100644 test/event_content_test.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index e7c0ed26..0583e2ef 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -79,6 +79,8 @@ export 'src/model/auth/authentication_three_pid_creds.dart'; export 'src/model/auth/authentication_token.dart'; export 'src/model/auth/authentication_types.dart'; export 'src/model/auth/authentication_user_identifier.dart'; +export 'src/model/events/room_encrypted_content.dart'; +export 'src/model/events/room_encryption_content.dart'; export 'src/model/events/secret_storage_default_key_content.dart'; export 'src/model/events/secret_storage_key_content.dart'; export 'src/model/events/tombstone_content.dart'; diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart new file mode 100644 index 00000000..f5f98e4d --- /dev/null +++ b/lib/src/model/events/room_encrypted_content.dart @@ -0,0 +1,71 @@ +import 'package:matrix_api_lite/src/utils/logs.dart'; + +import '../basic_event.dart'; +import '../../utils/try_get_map_extension.dart'; + +extension RoomEncryptedContentBasicEventExtension on BasicEvent { + RoomEncryptedContent get parsedRoomEncryptedContent => + RoomEncryptedContent.fromJson(content); +} + +class RoomEncryptedContent { + String algorithm; + String senderKey; + String deviceId; + String sessionId; + String ciphertextMegolm; + Map ciphertextOlm; + + RoomEncryptedContent.fromJson(Map json) + : algorithm = json.tryGet('algorithm', ''), + senderKey = json.tryGet('sender_key', ''), + deviceId = json.tryGet('device_id'), + sessionId = json.tryGet('session_id'), + ciphertextMegolm = json.tryGet('ciphertext'), + ciphertextOlm = json + .tryGet>('ciphertext') + ?.map((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))); + + Map toJson() { + final data = {}; + data['algorithm'] = algorithm; + data['sender_key'] = senderKey; + if (deviceId != null) { + data['device_id'] = deviceId; + } + if (sessionId != null) { + data['session_id'] = sessionId; + } + if (ciphertextMegolm != null) { + data['ciphertext'] = ciphertextMegolm; + } + if (ciphertextOlm != null) { + data['ciphertext'] = ciphertextOlm.map((k, v) => MapEntry(k, v.toJson())); + if (ciphertextMegolm != null) { + Logs().wtf( + 'ciphertextOlm and ciphertextMegolm are both set, which should never happen!'); + } + } + return data; + } +} + +class CiphertextInfo { + String body; + int type; + + CiphertextInfo.fromJson(Map json) + : body = json.tryGet('body'), + type = json.tryGet('type'); + + Map toJson() { + final data = {}; + if (body != null) { + data['body'] = body; + } + if (type != null) { + data['type'] = type; + } + return data; + } +} diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/src/model/events/room_encryption_content.dart new file mode 100644 index 00000000..7431f99b --- /dev/null +++ b/lib/src/model/events/room_encryption_content.dart @@ -0,0 +1,30 @@ +import '../basic_event.dart'; +import '../../utils/try_get_map_extension.dart'; + +extension RoomEncryptionContentBasicEventExtension on BasicEvent { + RoomEncryptionContent get parsedRoomEncryptionContent => + RoomEncryptionContent.fromJson(content); +} + +class RoomEncryptionContent { + String algorithm; + int rotationPeriodMs; + int rotationPeriodMsgs; + + RoomEncryptionContent.fromJson(Map json) + : algorithm = json.tryGet('algorithm', ''), + rotationPeriodMs = json.tryGet('rotation_period_ms'), + rotationPeriodMsgs = json.tryGet('rotation_period_msgs'); + + Map toJson() { + final data = {}; + data['algorithm'] = algorithm; + if (rotationPeriodMs != null) { + data['rotation_period_ms'] = rotationPeriodMs; + } + if (rotationPeriodMsgs != null) { + data['rotation_period_msgs'] = rotationPeriodMsgs; + } + return data; + } +} diff --git a/test/event_content_test.dart b/test/event_content_test.dart new file mode 100644 index 00000000..e1fee0d0 --- /dev/null +++ b/test/event_content_test.dart @@ -0,0 +1,82 @@ +/* + * Famedly Matrix SDK + * Copyright (C) 2020 Famedly GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'package:matrix_api_lite/matrix_api_lite.dart'; +import 'package:test/test.dart'; + +void main() { + group('Event Content tests', () { + test('Room Encryption Content', () { + var json = { + 'content': { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'rotation_period_ms': 604800000, + 'rotation_period_msgs': 100 + }, + 'event_id': '\$143273582443PhrSn:example.org', + 'origin_server_ts': 1432735824653, + 'room_id': '!jEsUZKDJdhlrceRyVU:example.org', + 'sender': '@example:example.org', + 'state_key': '', + 'type': 'm.room.encryption', + 'unsigned': {'age': 1234} + }; + expect(MatrixEvent.fromJson(json).parsedRoomEncryptionContent.toJson(), + json['content']); + }); + test('Room Encrypted Content', () { + var json = { + 'content': { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'ciphertext': 'AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...', + 'device_id': 'RJYKSTBOIE', + 'sender_key': 'IlRMeOPX2e0MurIyfWEucYBRVOEEUMrOHqn/8mLqMjA', + 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ' + }, + 'event_id': '\$143273582443PhrSn:example.org', + 'origin_server_ts': 1432735824653, + 'room_id': '!jEsUZKDJdhlrceRyVU:example.org', + 'sender': '@example:example.org', + 'type': 'm.room.encrypted', + 'unsigned': {'age': 1234} + }; + expect(MatrixEvent.fromJson(json).parsedRoomEncryptedContent.toJson(), + json['content']); + json = { + 'content': { + 'algorithm': 'm.olm.v1.curve25519-aes-sha2', + 'ciphertext': { + '7qZcfnBmbEGzxxaWfBjElJuvn7BZx+lSz/SvFrDF/z8': { + 'body': 'AwogGJJzMhf/S3GQFXAOrCZ3iKyGU5ZScVtjI0KypTYrW...', + 'type': 0 + } + }, + 'sender_key': 'Szl29ksW/L8yZGWAX+8dY1XyFi+i5wm+DRhTGkbMiwU' + }, + 'event_id': '\$143273582443PhrSn:example.org', + 'origin_server_ts': 1432735824653, + 'room_id': '!jEsUZKDJdhlrceRyVU:example.org', + 'sender': '@example:example.org', + 'type': 'm.room.encrypted', + 'unsigned': {'age': 1234} + }; + expect(MatrixEvent.fromJson(json).parsedRoomEncryptedContent.toJson(), + json['content']); + }); + }); +} From 0c77539291f5b7ef8cbb6e347b9d84e560efa403 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 08:43:28 +0100 Subject: [PATCH 015/174] feat: Add RoomEncryptedContent and RoomEncryptionContent --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ed54dd6..38a87874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1 + +- Add RoomEncryptedContent and RoomEncryptionContent + ## 0.1.0 - Initial version \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 2ef3820c..64ccc0a0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.0 +version: 0.1.1 homepage: https://famedly.com environment: From 81c86a6c05bec6165f2234a4f4d37bac65277985 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 09:33:03 +0100 Subject: [PATCH 016/174] feat: Add room_key content --- lib/matrix_api_lite.dart | 1 + .../model/events/room_encrypted_content.dart | 12 +++++--- lib/src/model/events/room_key_content.dart | 28 +++++++++++++++++++ test/event_content_test.dart | 13 +++++++++ test/try_get_map_extension_test.dart | 2 ++ 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 lib/src/model/events/room_key_content.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 0583e2ef..407c8b2f 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -81,6 +81,7 @@ export 'src/model/auth/authentication_types.dart'; export 'src/model/auth/authentication_user_identifier.dart'; export 'src/model/events/room_encrypted_content.dart'; export 'src/model/events/room_encryption_content.dart'; +export 'src/model/events/room_key_content.dart'; export 'src/model/events/secret_storage_default_key_content.dart'; export 'src/model/events/secret_storage_key_content.dart'; export 'src/model/events/tombstone_content.dart'; diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index f5f98e4d..86eb7298 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -21,10 +21,14 @@ class RoomEncryptedContent { senderKey = json.tryGet('sender_key', ''), deviceId = json.tryGet('device_id'), sessionId = json.tryGet('session_id'), - ciphertextMegolm = json.tryGet('ciphertext'), - ciphertextOlm = json - .tryGet>('ciphertext') - ?.map((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))); + ciphertextMegolm = json['ciphertext'] is String + ? json.tryGet('ciphertext') + : null, + ciphertextOlm = json['ciphertext'] is Map + ? json + .tryGet>('ciphertext') + ?.map((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))) + : null; Map toJson() { final data = {}; diff --git a/lib/src/model/events/room_key_content.dart b/lib/src/model/events/room_key_content.dart new file mode 100644 index 00000000..8b76dd68 --- /dev/null +++ b/lib/src/model/events/room_key_content.dart @@ -0,0 +1,28 @@ +import '../basic_event.dart'; +import '../../utils/try_get_map_extension.dart'; + +extension RoomKeyContentBasicEventExtension on BasicEvent { + RoomKeyContent get parsedRoomKeyContent => RoomKeyContent.fromJson(content); +} + +class RoomKeyContent { + String algorithm; + String roomId; + String sessionId; + String sessionKey; + + RoomKeyContent.fromJson(Map json) + : algorithm = json.tryGet('algorithm', ''), + roomId = json.tryGet('room_id', ''), + sessionId = json.tryGet('session_id', ''), + sessionKey = json.tryGet('session_key', ''); + + Map toJson() { + final data = {}; + data['algorithm'] = algorithm; + data['room_id'] = roomId; + data['session_id'] = sessionId; + data['session_key'] = sessionKey; + return data; + } +} diff --git a/test/event_content_test.dart b/test/event_content_test.dart index e1fee0d0..c4ab99e2 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -78,5 +78,18 @@ void main() { expect(MatrixEvent.fromJson(json).parsedRoomEncryptedContent.toJson(), json['content']); }); + test('Room Key Content', () { + var json = { + 'content': { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': '!Cuyf34gef24t:localhost', + 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ', + 'session_key': 'AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8LlfJL7qNBEY...' + }, + 'type': 'm.room_key' + }; + expect(BasicEvent.fromJson(json).parsedRoomKeyContent.toJson(), + json['content']); + }); }); } diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index 886700e3..40ee0098 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -16,11 +16,13 @@ * along with this program. If not, see . */ +import 'package:logger/logger.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; void main() { group('Try-get-map-extension', () { + Logs().level = Level.error; test('it should work', () { final data = { 'str': 'foxies', From fce77052430f4ec65ae14bb1b02bdfebe86b3271 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 09:54:11 +0100 Subject: [PATCH 017/174] feat: Implement room key request parsing --- lib/matrix_api_lite.dart | 1 + .../events/room_key_request_content.dart | 58 +++++++++++++++++++ test/event_content_test.dart | 28 +++++++++ 3 files changed, 87 insertions(+) create mode 100644 lib/src/model/events/room_key_request_content.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 407c8b2f..440ba497 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -82,6 +82,7 @@ export 'src/model/auth/authentication_user_identifier.dart'; export 'src/model/events/room_encrypted_content.dart'; export 'src/model/events/room_encryption_content.dart'; export 'src/model/events/room_key_content.dart'; +export 'src/model/events/room_key_request_content.dart'; export 'src/model/events/secret_storage_default_key_content.dart'; export 'src/model/events/secret_storage_key_content.dart'; export 'src/model/events/tombstone_content.dart'; diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart new file mode 100644 index 00000000..2c5bac13 --- /dev/null +++ b/lib/src/model/events/room_key_request_content.dart @@ -0,0 +1,58 @@ +import '../basic_event.dart'; +import '../../utils/try_get_map_extension.dart'; + +extension RoomKeyRequestContentBasicEventExtension on BasicEvent { + RoomKeyRequestContent get parsedRoomKeyRequestContent => + RoomKeyRequestContent.fromJson(content); +} + +class RoomKeyRequestContent { + RequestedKeyInfo body; + String action; + String requestingDeviceId; + String requestId; + + RoomKeyRequestContent.fromJson(Map json) + : body = RequestedKeyInfo.fromJson( + json.tryGet>('body')), + action = json.tryGet('action', ''), + requestingDeviceId = json.tryGet('requesting_device_id', ''), + requestId = json.tryGet('request_id', ''); + + Map toJson() { + final data = {}; + if (body != null) data['body'] = body.toJson(); + data['action'] = action; + data['requesting_device_id'] = requestingDeviceId; + data['request_id'] = requestId; + return data; + } +} + +class RequestedKeyInfo { + String algorithm; + String roomId; + String sessionId; + String senderKey; + + RequestedKeyInfo(); + + factory RequestedKeyInfo.fromJson(Map json) { + if (json == null) return null; + final requestKeyInfo = RequestedKeyInfo(); + requestKeyInfo.algorithm = json.tryGet('algorithm', ''); + requestKeyInfo.roomId = json.tryGet('room_id', ''); + requestKeyInfo.sessionId = json.tryGet('session_id', ''); + requestKeyInfo.senderKey = json.tryGet('sender_key', ''); + return requestKeyInfo; + } + + Map toJson() { + final data = {}; + data['algorithm'] = algorithm; + data['room_id'] = roomId; + data['session_id'] = sessionId; + data['sender_key'] = senderKey; + return data; + } +} diff --git a/test/event_content_test.dart b/test/event_content_test.dart index c4ab99e2..80eb2232 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -91,5 +91,33 @@ void main() { expect(BasicEvent.fromJson(json).parsedRoomKeyContent.toJson(), json['content']); }); + test('Room Key Request Content', () { + var json = { + 'content': { + 'action': 'request_cancellation', + 'request_id': '1495474790150.19', + 'requesting_device_id': 'RJYKSTBOIE' + }, + 'type': 'm.room_key_request' + }; + expect(BasicEvent.fromJson(json).parsedRoomKeyRequestContent.toJson(), + json['content']); + json = { + 'content': { + 'action': 'request', + 'body': { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': '!Cuyf34gef24t:localhost', + 'sender_key': 'RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU', + 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ' + }, + 'request_id': '1495474790150.19', + 'requesting_device_id': 'RJYKSTBOIE' + }, + 'type': 'm.room_key_request' + }; + expect(BasicEvent.fromJson(json).parsedRoomKeyRequestContent.toJson(), + json['content']); + }); }); } From 618d42a44816c74a1bf8b5850290a44edf8d577a Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 10:30:57 +0100 Subject: [PATCH 018/174] feat: Room forwarded key content --- lib/matrix_api_lite.dart | 1 + .../events/forwarded_room_key_content.dart | 31 +++++++++++++++++++ lib/src/model/events/room_key_content.dart | 2 ++ lib/src/utils/try_get_map_extension.dart | 21 +++++++++++++ test/event_content_test.dart | 27 ++++++++++++++++ 5 files changed, 82 insertions(+) create mode 100644 lib/src/model/events/forwarded_room_key_content.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 440ba497..d9d91fa0 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -79,6 +79,7 @@ export 'src/model/auth/authentication_three_pid_creds.dart'; export 'src/model/auth/authentication_token.dart'; export 'src/model/auth/authentication_types.dart'; export 'src/model/auth/authentication_user_identifier.dart'; +export 'src/model/events/forwarded_room_key_content.dart'; export 'src/model/events/room_encrypted_content.dart'; export 'src/model/events/room_encryption_content.dart'; export 'src/model/events/room_key_content.dart'; diff --git a/lib/src/model/events/forwarded_room_key_content.dart b/lib/src/model/events/forwarded_room_key_content.dart new file mode 100644 index 00000000..29cb3221 --- /dev/null +++ b/lib/src/model/events/forwarded_room_key_content.dart @@ -0,0 +1,31 @@ +import '../basic_event.dart'; +import '../../utils/try_get_map_extension.dart'; +import 'room_key_content.dart'; + +extension ForwardedRoomKeyContentBasicEventExtension on BasicEvent { + ForwardedRoomKeyContent get parsedForwardedRoomKeyContent => + ForwardedRoomKeyContent.fromJson(content); +} + +class ForwardedRoomKeyContent extends RoomKeyContent { + String senderKey; + String senderClaimedEd25519Key; + List forwardingCurve25519KeyChain; + ForwardedRoomKeyContent.fromJson(Map json) + : senderKey = json.tryGet('sender_key', ''), + senderClaimedEd25519Key = + json.tryGet('sender_claimed_ed25519_key', ''), + forwardingCurve25519KeyChain = + json.tryGetList('forwarding_curve25519_key_chain', []), + super.fromJson(json); + + @override + Map toJson() { + final data = super.toJson(); + data['sender_key'] = senderKey; + data['sender_claimed_ed25519_key'] = senderClaimedEd25519Key; + data['forwarding_curve25519_key_chain'] = forwardingCurve25519KeyChain; + + return data; + } +} diff --git a/lib/src/model/events/room_key_content.dart b/lib/src/model/events/room_key_content.dart index 8b76dd68..a84a2299 100644 --- a/lib/src/model/events/room_key_content.dart +++ b/lib/src/model/events/room_key_content.dart @@ -11,6 +11,8 @@ class RoomKeyContent { String sessionId; String sessionKey; + RoomKeyContent(); + RoomKeyContent.fromJson(Map json) : algorithm = json.tryGet('algorithm', ''), roomId = json.tryGet('room_id', ''), diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index fe8f306c..bc7a926b 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -15,4 +15,25 @@ extension TryGetMapExtension on Map { } return value; } + + List tryGetList(String key, [List fallbackValue]) { + final value = this[key]; + if (value != null && !(value is List)) { + Logs().w( + 'Expected "${T.runtimeType}" in event content for the key "$key" but got "${value.runtimeType}".'); + return fallbackValue; + } + if (value == null && fallbackValue != null) { + Logs().w( + 'Required field in event content for the key "$key" is null. Set to "$fallbackValue".'); + return fallbackValue; + } + try { + return List.from(value as List); + } catch (_) { + Logs().w( + 'Unable to create List<${T.runtimeType}> in event content for the key "$key'); + return fallbackValue; + } + } } diff --git a/test/event_content_test.dart b/test/event_content_test.dart index 80eb2232..a9ef3e47 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -18,6 +18,7 @@ import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; +import 'dart:convert'; void main() { group('Event Content tests', () { @@ -36,6 +37,7 @@ void main() { 'type': 'm.room.encryption', 'unsigned': {'age': 1234} }; + json = jsonDecode(jsonEncode(json)); expect(MatrixEvent.fromJson(json).parsedRoomEncryptionContent.toJson(), json['content']); }); @@ -55,6 +57,7 @@ void main() { 'type': 'm.room.encrypted', 'unsigned': {'age': 1234} }; + json = jsonDecode(jsonEncode(json)); expect(MatrixEvent.fromJson(json).parsedRoomEncryptedContent.toJson(), json['content']); json = { @@ -75,6 +78,7 @@ void main() { 'type': 'm.room.encrypted', 'unsigned': {'age': 1234} }; + json = jsonDecode(jsonEncode(json)); expect(MatrixEvent.fromJson(json).parsedRoomEncryptedContent.toJson(), json['content']); }); @@ -88,6 +92,7 @@ void main() { }, 'type': 'm.room_key' }; + json = jsonDecode(jsonEncode(json)); expect(BasicEvent.fromJson(json).parsedRoomKeyContent.toJson(), json['content']); }); @@ -100,6 +105,7 @@ void main() { }, 'type': 'm.room_key_request' }; + json = jsonDecode(jsonEncode(json)); expect(BasicEvent.fromJson(json).parsedRoomKeyRequestContent.toJson(), json['content']); json = { @@ -116,8 +122,29 @@ void main() { }, 'type': 'm.room_key_request' }; + json = jsonDecode(jsonEncode(json)); expect(BasicEvent.fromJson(json).parsedRoomKeyRequestContent.toJson(), json['content']); }); + test('Forwarded Room Key Content', () { + var json = { + 'content': { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'forwarding_curve25519_key_chain': [ + 'hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw' + ], + 'room_id': '!Cuyf34gef24t:localhost', + 'sender_claimed_ed25519_key': + 'aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y', + 'sender_key': 'RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU', + 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ', + 'session_key': 'AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf...' + }, + 'type': 'm.forwarded_room_key' + }; + json = jsonDecode(jsonEncode(json)); + expect(BasicEvent.fromJson(json).parsedForwardedRoomKeyContent.toJson(), + json['content']); + }); }); } From ae34041f29d3ec253c11e13d46f9ef02b424c092 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 10:54:04 +0100 Subject: [PATCH 019/174] feat: Implement plaintext parsing --- lib/matrix_api_lite.dart | 1 + .../model/events/olm_plaintext_payload.dart | 40 +++++++++++++++++++ lib/src/utils/try_get_map_extension.dart | 27 +++++++++++-- test/event_content_test.dart | 15 +++++++ 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 lib/src/model/events/olm_plaintext_payload.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index d9d91fa0..1a57a8b7 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -80,6 +80,7 @@ export 'src/model/auth/authentication_token.dart'; export 'src/model/auth/authentication_types.dart'; export 'src/model/auth/authentication_user_identifier.dart'; export 'src/model/events/forwarded_room_key_content.dart'; +export 'src/model/events/olm_plaintext_payload.dart'; export 'src/model/events/room_encrypted_content.dart'; export 'src/model/events/room_encryption_content.dart'; export 'src/model/events/room_key_content.dart'; diff --git a/lib/src/model/events/olm_plaintext_payload.dart b/lib/src/model/events/olm_plaintext_payload.dart new file mode 100644 index 00000000..fbd46c5c --- /dev/null +++ b/lib/src/model/events/olm_plaintext_payload.dart @@ -0,0 +1,40 @@ +import '../../utils/try_get_map_extension.dart'; + +class OlmPlaintextPayload { + String type; + Map content; + String sender; + String recipient; + Map recipientKeys; + Map keys; + + OlmPlaintextPayload({ + this.type, + this.content, + this.sender, + this.recipient, + this.recipientKeys, + this.keys, + }) : super(); + + factory OlmPlaintextPayload.fromJson(Map json) => + OlmPlaintextPayload( + sender: json.tryGet('sender'), + type: json.tryGet('type'), + content: json.tryGetMap('content'), + recipient: json.tryGet('recipient'), + recipientKeys: json.tryGetMap('recipient_keys'), + keys: json.tryGetMap('keys'), + ); + + Map toJson() { + final data = {}; + if (type != null) data['type'] = type; + if (sender != null) data['sender'] = sender; + if (content != null) data['content'] = content; + if (recipient != null) data['recipient'] = recipient; + if (recipientKeys != null) data['recipient_keys'] = recipientKeys; + if (keys != null) data['keys'] = keys; + return data; + } +} diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index bc7a926b..46db4943 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -20,7 +20,7 @@ extension TryGetMapExtension on Map { final value = this[key]; if (value != null && !(value is List)) { Logs().w( - 'Expected "${T.runtimeType}" in event content for the key "$key" but got "${value.runtimeType}".'); + 'Expected "List<${T.runtimeType}>" in event content for the key "$key" but got "${value.runtimeType}".'); return fallbackValue; } if (value == null && fallbackValue != null) { @@ -29,10 +29,31 @@ extension TryGetMapExtension on Map { return fallbackValue; } try { - return List.from(value as List); + return List.from(value); } catch (_) { Logs().w( - 'Unable to create List<${T.runtimeType}> in event content for the key "$key'); + 'Unable to create "List<${T.runtimeType}>" in event content for the key "$key"'); + return fallbackValue; + } + } + + Map tryGetMap(String key, [Map fallbackValue]) { + final value = this[key]; + if (value != null && !(value is Map)) { + Logs().w( + 'Expected "Map<${A.runtimeType},${B.runtimeType}>" in event content for the key "$key" but got "${value.runtimeType}".'); + return fallbackValue; + } + if (value == null && fallbackValue != null) { + Logs().w( + 'Required field in event content for the key "$key" is null. Set to "$fallbackValue".'); + return fallbackValue; + } + try { + return Map.from(value); + } catch (_) { + Logs().w( + 'Unable to create "Map<${A.runtimeType},${B.runtimeType}>" in event content for the key "$key"'); return fallbackValue; } } diff --git a/test/event_content_test.dart b/test/event_content_test.dart index a9ef3e47..95fb274e 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -146,5 +146,20 @@ void main() { expect(BasicEvent.fromJson(json).parsedForwardedRoomKeyContent.toJson(), json['content']); }); + test('OLM Plaintext Payload', () { + var json = { + 'type': '', + 'content': { + 'msgtype': 'm.text', + 'body': 'Hello world', + }, + 'sender': '', + 'recipient': '', + 'recipient_keys': {'ed25519': ''}, + 'keys': {'ed25519': ''} + }; + json = jsonDecode(jsonEncode(json)); + expect(OlmPlaintextPayload.fromJson(json).toJson(), json); + }); }); } From e9933659a09c13c65a2f29ddb1ea515399fa138f Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 10:54:38 +0100 Subject: [PATCH 020/174] chore: Bump version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38a87874..7853dd49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.2 + +- Add more encryption and decryption content parsing + ## 0.1.1 - Add RoomEncryptedContent and RoomEncryptionContent diff --git a/pubspec.yaml b/pubspec.yaml index 64ccc0a0..e9f09605 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.1 +version: 0.1.2 homepage: https://famedly.com environment: From 5ea63b1f1f77657517acffd39171a22b0c8773e7 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 11:16:14 +0100 Subject: [PATCH 021/174] fix: Set Content-Length on upload --- CHANGELOG.md | 4 ++++ lib/src/matrix_api.dart | 4 +++- pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7853dd49..af3d941e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.3 + +- Set Content-Length on upload + ## 0.1.2 - Add more encryption and decryption content parsing diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 6c63a363..f3424cf6 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -1295,16 +1295,18 @@ class MatrixApi { Future upload(Uint8List file, String fileName, {String contentType}) async { fileName = fileName.split('/').last; + final length = file.length; var headers = {}; headers['Authorization'] = 'Bearer $accessToken'; headers['Content-Type'] = contentType ?? lookupMimeType(fileName, headerBytes: file); + headers['Content-Length'] = length.toString(); fileName = Uri.encodeQueryComponent(fileName); final url = '${homeserver.toString()}/_matrix/media/r0/upload?filename=$fileName'; final streamedRequest = http.StreamedRequest('POST', Uri.parse(url)) ..headers.addAll(headers); - streamedRequest.contentLength = await file.length; + streamedRequest.contentLength = length; streamedRequest.sink.add(file); streamedRequest.sink.close(); var streamedResponse = _testMode ? null : await streamedRequest.send(); diff --git a/pubspec.yaml b/pubspec.yaml index e9f09605..fcc6c15d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.2 +version: 0.1.3 homepage: https://famedly.com environment: From 0ccf3007776b1cc27c7fe9a3149f98310accb03b Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 12:55:16 +0100 Subject: [PATCH 022/174] fix: Cast instead of shallow copy --- lib/src/utils/try_get_map_extension.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index 46db4943..a9bde740 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -29,7 +29,7 @@ extension TryGetMapExtension on Map { return fallbackValue; } try { - return List.from(value); + return (value as List).cast(); } catch (_) { Logs().w( 'Unable to create "List<${T.runtimeType}>" in event content for the key "$key"'); @@ -50,7 +50,7 @@ extension TryGetMapExtension on Map { return fallbackValue; } try { - return Map.from(value); + return (value as Map).cast(); } catch (_) { Logs().w( 'Unable to create "Map<${A.runtimeType},${B.runtimeType}>" in event content for the key "$key"'); From 5f46a75d104551073200b5e9507b2bb99de198fa Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 13:03:06 +0100 Subject: [PATCH 023/174] chore: Bump version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af3d941e..05b79c51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4 + +- Fix creating shallow copies all the time + ## 0.1.3 - Set Content-Length on upload diff --git a/pubspec.yaml b/pubspec.yaml index fcc6c15d..a9bfb810 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.3 +version: 0.1.4 homepage: https://famedly.com environment: From 8f1d35e0bccb3fafef1262317cc0b6262eeadb8a Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 8 Jan 2021 13:14:03 +0100 Subject: [PATCH 024/174] docs: Update license to MIT --- LICENSE | 2 +- lib/fake_matrix_api.dart | 39 +++++++++++-------- lib/matrix_api_lite.dart | 39 +++++++++++-------- lib/src/matrix_api.dart | 39 +++++++++++-------- lib/src/model/algorithm_types.dart | 39 +++++++++++-------- lib/src/model/auth/authentication_data.dart | 39 +++++++++++-------- .../model/auth/authentication_identifier.dart | 39 +++++++++++-------- .../model/auth/authentication_password.dart | 39 +++++++++++-------- .../auth/authentication_phone_identifier.dart | 39 +++++++++++-------- .../model/auth/authentication_recaptcha.dart | 39 +++++++++++-------- ...authentication_third_party_identifier.dart | 39 +++++++++++-------- .../auth/authentication_three_pid_creds.dart | 39 +++++++++++-------- lib/src/model/auth/authentication_token.dart | 39 +++++++++++-------- lib/src/model/auth/authentication_types.dart | 39 +++++++++++-------- .../auth/authentication_user_identifier.dart | 39 +++++++++++-------- lib/src/model/basic_event.dart | 39 +++++++++++-------- lib/src/model/basic_event_with_sender.dart | 39 +++++++++++-------- lib/src/model/basic_room_event.dart | 39 +++++++++++-------- lib/src/model/device.dart | 39 +++++++++++-------- lib/src/model/event_context.dart | 39 +++++++++++-------- lib/src/model/event_types.dart | 39 +++++++++++-------- .../events/forwarded_room_key_content.dart | 23 +++++++++++ .../model/events/olm_plaintext_payload.dart | 23 +++++++++++ .../model/events/room_encrypted_content.dart | 23 +++++++++++ .../model/events/room_encryption_content.dart | 23 +++++++++++ lib/src/model/events/room_key_content.dart | 23 +++++++++++ .../events/room_key_request_content.dart | 23 +++++++++++ .../secret_storage_default_key_content.dart | 23 +++++++++++ .../events/secret_storage_key_content.dart | 23 +++++++++++ lib/src/model/events/tombstone_content.dart | 23 +++++++++++ lib/src/model/events_sync_update.dart | 39 +++++++++++-------- lib/src/model/filter.dart | 39 +++++++++++-------- lib/src/model/keys_query_response.dart | 39 +++++++++++-------- lib/src/model/login_response.dart | 39 +++++++++++-------- lib/src/model/login_types.dart | 39 +++++++++++-------- .../model/matrix_connection_exception.dart | 39 +++++++++++-------- lib/src/model/matrix_event.dart | 39 +++++++++++-------- lib/src/model/matrix_exception.dart | 39 +++++++++++-------- lib/src/model/matrix_keys.dart | 39 +++++++++++-------- lib/src/model/message_types.dart | 39 +++++++++++-------- .../model/notifications_query_response.dart | 39 +++++++++++-------- .../model/one_time_keys_claim_response.dart | 39 +++++++++++-------- lib/src/model/open_graph_data.dart | 39 +++++++++++-------- lib/src/model/open_id_credentials.dart | 39 +++++++++++-------- lib/src/model/presence.dart | 39 +++++++++++-------- lib/src/model/presence_content.dart | 39 +++++++++++-------- lib/src/model/profile.dart | 39 +++++++++++-------- lib/src/model/public_rooms_response.dart | 39 +++++++++++-------- lib/src/model/push_rule_set.dart | 39 +++++++++++-------- lib/src/model/pusher.dart | 39 +++++++++++-------- lib/src/model/request_token_response.dart | 39 +++++++++++-------- lib/src/model/room_alias_informations.dart | 39 +++++++++++-------- lib/src/model/room_keys_info.dart | 39 +++++++++++-------- lib/src/model/room_keys_keys.dart | 39 +++++++++++-------- lib/src/model/room_summary.dart | 39 +++++++++++-------- lib/src/model/server_capabilities.dart | 39 +++++++++++-------- lib/src/model/stripped_state_event.dart | 39 +++++++++++-------- lib/src/model/supported_protocol.dart | 39 +++++++++++-------- lib/src/model/supported_versions.dart | 39 +++++++++++-------- lib/src/model/sync_update.dart | 39 +++++++++++-------- lib/src/model/tag.dart | 39 +++++++++++-------- lib/src/model/third_party_identifier.dart | 39 +++++++++++-------- lib/src/model/third_party_location.dart | 39 +++++++++++-------- lib/src/model/third_party_user.dart | 39 +++++++++++-------- lib/src/model/timeline_history_response.dart | 39 +++++++++++-------- lib/src/model/turn_server_credentials.dart | 39 +++++++++++-------- .../model/upload_key_signatures_response.dart | 39 +++++++++++-------- lib/src/model/user_search_result.dart | 39 +++++++++++-------- lib/src/model/well_known_informations.dart | 39 +++++++++++-------- lib/src/model/who_is_info.dart | 39 +++++++++++-------- lib/src/utils/logs.dart | 39 +++++++++++-------- lib/src/utils/map_copy_extension.dart | 39 +++++++++++-------- lib/src/utils/try_get_map_extension.dart | 23 +++++++++++ test/event_content_test.dart | 39 +++++++++++-------- test/map_copy_extension_test.dart | 39 +++++++++++-------- test/matrix_api_test.dart | 39 +++++++++++-------- test/try_get_map_extension_test.dart | 39 +++++++++++-------- 77 files changed, 1683 insertions(+), 1123 deletions(-) diff --git a/LICENSE b/LICENSE index d4b01570..2c086bbb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Matrix API Lite +Copyright (C) 2021 Famedly GmbH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index dad87872..69060955 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1,20 +1,25 @@ -/* - * Ansible inventory script used at Famedly GmbH for managing many hosts - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'dart:convert'; import 'dart:core'; diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 1a57a8b7..9264103e 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ library matrix_api_lite; diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index f3424cf6..bfe13ca7 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'dart:async'; import 'dart:convert'; diff --git a/lib/src/model/algorithm_types.dart b/lib/src/model/algorithm_types.dart index aa3fb0e2..e4f8548b 100644 --- a/lib/src/model/algorithm_types.dart +++ b/lib/src/model/algorithm_types.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ abstract class AlgorithmTypes { static const String olmV1Curve25519AesSha2 = 'm.olm.v1.curve25519-aes-sha2'; diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 2a363dd6..565c2dbd 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class AuthenticationData { String type; diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index cbb0981d..5c6bec93 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class AuthenticationIdentifier { String type; diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index 2fe57f63..6600a4f1 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'authentication_user_identifier.dart'; diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index 8045f346..8ae4d06a 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'authentication_identifier.dart'; import 'authentication_types.dart'; diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index 1b714fd8..f37526f9 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'authentication_data.dart'; import 'authentication_types.dart'; diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index 241c2058..742248ff 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'authentication_identifier.dart'; import 'authentication_types.dart'; diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 5d9eb800..37e7ba97 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'authentication_data.dart'; diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index 928f6b10..f182c2dc 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'authentication_data.dart'; import 'authentication_types.dart'; diff --git a/lib/src/model/auth/authentication_types.dart b/lib/src/model/auth/authentication_types.dart index b5536204..ea181e40 100644 --- a/lib/src/model/auth/authentication_types.dart +++ b/lib/src/model/auth/authentication_types.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ abstract class AuthenticationTypes { static const String password = 'm.login.password'; diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index ab1e8bd4..28491a6b 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'authentication_identifier.dart'; import 'authentication_types.dart'; diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 108dd0fd..48ea0c1a 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import '../utils/map_copy_extension.dart'; diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index b99fb343..6c93fd07 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'basic_event.dart'; diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index dd902730..8a97ee72 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'basic_event.dart'; diff --git a/lib/src/model/device.dart b/lib/src/model/device.dart index fbdbe6fc..01b027b2 100644 --- a/lib/src/model/device.dart +++ b/lib/src/model/device.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class Device { String deviceId; diff --git a/lib/src/model/event_context.dart b/lib/src/model/event_context.dart index 75ed1e4f..2bdc026d 100644 --- a/lib/src/model/event_context.dart +++ b/lib/src/model/event_context.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'matrix_event.dart'; diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index 921e87a7..655e24ba 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ abstract class EventTypes { // Room timeline and state event types diff --git a/lib/src/model/events/forwarded_room_key_content.dart b/lib/src/model/events/forwarded_room_key_content.dart index 29cb3221..73eac32e 100644 --- a/lib/src/model/events/forwarded_room_key_content.dart +++ b/lib/src/model/events/forwarded_room_key_content.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; import 'room_key_content.dart'; diff --git a/lib/src/model/events/olm_plaintext_payload.dart b/lib/src/model/events/olm_plaintext_payload.dart index fbd46c5c..c4a918d5 100644 --- a/lib/src/model/events/olm_plaintext_payload.dart +++ b/lib/src/model/events/olm_plaintext_payload.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import '../../utils/try_get_map_extension.dart'; class OlmPlaintextPayload { diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 86eb7298..def336dc 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import 'package:matrix_api_lite/src/utils/logs.dart'; import '../basic_event.dart'; diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/src/model/events/room_encryption_content.dart index 7431f99b..15ea46f0 100644 --- a/lib/src/model/events/room_encryption_content.dart +++ b/lib/src/model/events/room_encryption_content.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; diff --git a/lib/src/model/events/room_key_content.dart b/lib/src/model/events/room_key_content.dart index a84a2299..4a78e36f 100644 --- a/lib/src/model/events/room_key_content.dart +++ b/lib/src/model/events/room_key_content.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index 2c5bac13..c48a1fba 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/src/model/events/secret_storage_default_key_content.dart index 2e40ddf5..f5067a34 100644 --- a/lib/src/model/events/secret_storage_default_key_content.dart +++ b/lib/src/model/events/secret_storage_default_key_content.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index 29050834..899fead4 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; diff --git a/lib/src/model/events/tombstone_content.dart b/lib/src/model/events/tombstone_content.dart index efddba3c..dfc8beef 100644 --- a/lib/src/model/events/tombstone_content.dart +++ b/lib/src/model/events/tombstone_content.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart index 502dc9c2..6ea08df5 100644 --- a/lib/src/model/events_sync_update.dart +++ b/lib/src/model/events_sync_update.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'matrix_event.dart'; diff --git a/lib/src/model/filter.dart b/lib/src/model/filter.dart index 5e86c4a2..5b009fcd 100644 --- a/lib/src/model/filter.dart +++ b/lib/src/model/filter.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ enum EventFormat { client, federation } diff --git a/lib/src/model/keys_query_response.dart b/lib/src/model/keys_query_response.dart index 95a2eac8..c705ab1b 100644 --- a/lib/src/model/keys_query_response.dart +++ b/lib/src/model/keys_query_response.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'matrix_keys.dart'; import '../utils/map_copy_extension.dart'; diff --git a/lib/src/model/login_response.dart b/lib/src/model/login_response.dart index 76c5a006..20960edb 100644 --- a/lib/src/model/login_response.dart +++ b/lib/src/model/login_response.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'well_known_informations.dart'; diff --git a/lib/src/model/login_types.dart b/lib/src/model/login_types.dart index 554be30a..f95098ad 100644 --- a/lib/src/model/login_types.dart +++ b/lib/src/model/login_types.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class LoginTypes { List flows; diff --git a/lib/src/model/matrix_connection_exception.dart b/lib/src/model/matrix_connection_exception.dart index 3ba584e4..a7046525 100644 --- a/lib/src/model/matrix_connection_exception.dart +++ b/lib/src/model/matrix_connection_exception.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class MatrixConnectionException implements Exception { final dynamic original; diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index 17dbee60..74dd4296 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'stripped_state_event.dart'; import '../utils/map_copy_extension.dart'; diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index bcb112cb..00af277e 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'dart:convert'; diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index b3c12ab8..81819f78 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import '../utils/map_copy_extension.dart'; diff --git a/lib/src/model/message_types.dart b/lib/src/model/message_types.dart index e3bd6f38..d6745350 100644 --- a/lib/src/model/message_types.dart +++ b/lib/src/model/message_types.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ abstract class MessageTypes { static const String Text = 'm.text'; diff --git a/lib/src/model/notifications_query_response.dart b/lib/src/model/notifications_query_response.dart index b22ace0b..01b2777c 100644 --- a/lib/src/model/notifications_query_response.dart +++ b/lib/src/model/notifications_query_response.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'matrix_event.dart'; diff --git a/lib/src/model/one_time_keys_claim_response.dart b/lib/src/model/one_time_keys_claim_response.dart index 785ef945..b3bab36d 100644 --- a/lib/src/model/one_time_keys_claim_response.dart +++ b/lib/src/model/one_time_keys_claim_response.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import '../utils/map_copy_extension.dart'; diff --git a/lib/src/model/open_graph_data.dart b/lib/src/model/open_graph_data.dart index 2dc72813..7ba8f5aa 100644 --- a/lib/src/model/open_graph_data.dart +++ b/lib/src/model/open_graph_data.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class OpenGraphData { String ogTitle; diff --git a/lib/src/model/open_id_credentials.dart b/lib/src/model/open_id_credentials.dart index 8851a473..4ead2f91 100644 --- a/lib/src/model/open_id_credentials.dart +++ b/lib/src/model/open_id_credentials.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class OpenIdCredentials { String accessToken; diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index fb05599b..93d17c9b 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'basic_event_with_sender.dart'; import 'presence_content.dart'; diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index e89ec4a9..99d926cf 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ enum PresenceType { online, offline, unavailable } diff --git a/lib/src/model/profile.dart b/lib/src/model/profile.dart index ec36928b..79c6a38e 100644 --- a/lib/src/model/profile.dart +++ b/lib/src/model/profile.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class Profile { /// The user's avatar URL if they have set one, otherwise null. diff --git a/lib/src/model/public_rooms_response.dart b/lib/src/model/public_rooms_response.dart index e713b24c..56671440 100644 --- a/lib/src/model/public_rooms_response.dart +++ b/lib/src/model/public_rooms_response.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class PublicRoomsResponse { List chunk; diff --git a/lib/src/model/push_rule_set.dart b/lib/src/model/push_rule_set.dart index 858080bd..0055e5ad 100644 --- a/lib/src/model/push_rule_set.dart +++ b/lib/src/model/push_rule_set.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ enum PushRuleKind { content, override, room, sender, underride } enum PushRuleAction { notify, dont_notify, coalesce, set_tweak } diff --git a/lib/src/model/pusher.dart b/lib/src/model/pusher.dart index fd49859f..4068e2c9 100644 --- a/lib/src/model/pusher.dart +++ b/lib/src/model/pusher.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class Pusher { String pushkey; diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart index 2ce7051b..e7b41c7c 100644 --- a/lib/src/model/request_token_response.dart +++ b/lib/src/model/request_token_response.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class RequestTokenResponse { String sid; diff --git a/lib/src/model/room_alias_informations.dart b/lib/src/model/room_alias_informations.dart index 70c88645..82c40f4e 100644 --- a/lib/src/model/room_alias_informations.dart +++ b/lib/src/model/room_alias_informations.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class RoomAliasInformations { String roomId; diff --git a/lib/src/model/room_keys_info.dart b/lib/src/model/room_keys_info.dart index b482d192..9deaea3d 100644 --- a/lib/src/model/room_keys_info.dart +++ b/lib/src/model/room_keys_info.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import '../../matrix_api_lite.dart'; diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart index 4c47489d..fb8c20fc 100644 --- a/lib/src/model/room_keys_keys.dart +++ b/lib/src/model/room_keys_keys.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class RoomKeysSingleKey { int firstMessageIndex; diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index bae41f99..78d505ee 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class RoomSummary { List mHeroes; diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart index c1c00205..3b2c2025 100644 --- a/lib/src/model/server_capabilities.dart +++ b/lib/src/model/server_capabilities.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import '../utils/map_copy_extension.dart'; diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index 43f6cac8..da9298ff 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'basic_event_with_sender.dart'; diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart index 97e25521..0f0c1b30 100644 --- a/lib/src/model/supported_protocol.dart +++ b/lib/src/model/supported_protocol.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class SupportedProtocol { List userFields; diff --git a/lib/src/model/supported_versions.dart b/lib/src/model/supported_versions.dart index 2b362570..92b5160f 100644 --- a/lib/src/model/supported_versions.dart +++ b/lib/src/model/supported_versions.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class SupportedVersions { List versions; diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index 32a3caa9..0be0150d 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'basic_event.dart'; import 'basic_event_with_sender.dart'; diff --git a/lib/src/model/tag.dart b/lib/src/model/tag.dart index 8b6fe8af..5b3968a1 100644 --- a/lib/src/model/tag.dart +++ b/lib/src/model/tag.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class Tag { double order; diff --git a/lib/src/model/third_party_identifier.dart b/lib/src/model/third_party_identifier.dart index bdfd8714..7ca0c2ad 100644 --- a/lib/src/model/third_party_identifier.dart +++ b/lib/src/model/third_party_identifier.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import '../matrix_api.dart'; diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index 41e21f23..0206a283 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import '../utils/map_copy_extension.dart'; diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index 8c51e876..40a67893 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import '../utils/map_copy_extension.dart'; diff --git a/lib/src/model/timeline_history_response.dart b/lib/src/model/timeline_history_response.dart index 863929ef..84a68fb2 100644 --- a/lib/src/model/timeline_history_response.dart +++ b/lib/src/model/timeline_history_response.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'matrix_event.dart'; diff --git a/lib/src/model/turn_server_credentials.dart b/lib/src/model/turn_server_credentials.dart index 2b7d2394..67fca47a 100644 --- a/lib/src/model/turn_server_credentials.dart +++ b/lib/src/model/turn_server_credentials.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class TurnServerCredentials { String username; diff --git a/lib/src/model/upload_key_signatures_response.dart b/lib/src/model/upload_key_signatures_response.dart index 9c665e15..cf845766 100644 --- a/lib/src/model/upload_key_signatures_response.dart +++ b/lib/src/model/upload_key_signatures_response.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'matrix_exception.dart'; diff --git a/lib/src/model/user_search_result.dart b/lib/src/model/user_search_result.dart index bfdeafe6..837a08ec 100644 --- a/lib/src/model/user_search_result.dart +++ b/lib/src/model/user_search_result.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'profile.dart'; diff --git a/lib/src/model/well_known_informations.dart b/lib/src/model/well_known_informations.dart index f7eeed59..9978c237 100644 --- a/lib/src/model/well_known_informations.dart +++ b/lib/src/model/well_known_informations.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class WellKnownInformations { MHomeserver mHomeserver; diff --git a/lib/src/model/who_is_info.dart b/lib/src/model/who_is_info.dart index 86289804..be144736 100644 --- a/lib/src/model/who_is_info.dart +++ b/lib/src/model/who_is_info.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ class WhoIsInfo { String userId; diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index 35b1d2cc..e902859f 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'package:logger/logger.dart'; diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart index ef821e9b..7d2bbaec 100644 --- a/lib/src/utils/map_copy_extension.dart +++ b/lib/src/utils/map_copy_extension.dart @@ -1,20 +1,25 @@ -/* - * Matrix API Lite - * Copyright (C) 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ extension MapCopyExtension on Map { /// Deep-copies a given json map diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index a9bde740..850a3a45 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -1,3 +1,26 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + import 'logs.dart'; extension TryGetMapExtension on Map { diff --git a/test/event_content_test.dart b/test/event_content_test.dart index 95fb274e..a9969989 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -1,20 +1,25 @@ -/* - * Famedly Matrix SDK - * Copyright (C) 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart index 958f01eb..38d9290a 100644 --- a/test/map_copy_extension_test.dart +++ b/test/map_copy_extension_test.dart @@ -1,20 +1,25 @@ -/* - * Famedly Matrix SDK - * Copyright (C) 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index a673911b..df6e1645 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1,20 +1,25 @@ -/* - * Ansible inventory script used at Famedly GmbH for managing many hosts - * Copyright (C) 2019, 2020, 2021 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'dart:typed_data'; import 'package:logger/logger.dart'; diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index 40ee0098..45a4503b 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -1,20 +1,25 @@ -/* - * Famedly Matrix SDK - * Copyright (C) 2020 Famedly GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ import 'package:logger/logger.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; From 195d46b901d117397c32f2e915729c289a34c1da Mon Sep 17 00:00:00 2001 From: Sorunome Date: Sun, 17 Jan 2021 15:38:09 +0100 Subject: [PATCH 025/174] fix: Deep-copy arrays correctly --- lib/src/utils/map_copy_extension.dart | 29 ++++++++++++++++++--------- test/map_copy_extension_test.dart | 21 +++++++++++++++---- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart index 7d2bbaec..9e3018b7 100644 --- a/lib/src/utils/map_copy_extension.dart +++ b/lib/src/utils/map_copy_extension.dart @@ -1,17 +1,17 @@ /* MIT License -* +* * Copyright (C) 2019, 2020, 2021 Famedly GmbH -* +* * 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 @@ -22,16 +22,25 @@ */ extension MapCopyExtension on Map { + dynamic _copyValue(dynamic value) { + if (value is Map) { + return value.copy(); + } + if (value is List) { + final ret = []; + for (final val in value) { + ret.add(_copyValue(val)); + } + return ret; + } + return value; + } + /// Deep-copies a given json map Map copy() { final copy = Map.from(this); for (final entry in copy.entries) { - if (entry.value is Map) { - copy[entry.key] = (entry.value as Map).copy(); - } - if (entry.value is List) { - copy[entry.key] = List.from(entry.value); - } + copy[entry.key] = _copyValue(entry.value); } return copy; } diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart index 38d9290a..329771d9 100644 --- a/test/map_copy_extension_test.dart +++ b/test/map_copy_extension_test.dart @@ -1,17 +1,17 @@ /* MIT License -* +* * Copyright (C) 2019, 2020, 2021 Famedly GmbH -* +* * 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 @@ -40,5 +40,18 @@ void main() { original['child']['list'].add(3); expect(copy['child']['list'], [1, 2]); }); + test('should do arrays', () { + final original = { + 'arr': [ + [1, 2], + {'beep': 'boop'}, + ], + }; + final copy = original.copy(); + original['arr'][0].add(3); + expect(copy['arr'][0], [1, 2]); + original['arr'][1]['beep'] = 'blargh'; + expect(copy['arr'][1]['beep'], 'boop'); + }); }); } From 484037a13f9b1c9c4fe85de03bde3869365a259d Mon Sep 17 00:00:00 2001 From: Sorunome Date: Mon, 18 Jan 2021 16:33:12 +0100 Subject: [PATCH 026/174] feat: Add m.dummy event --- lib/src/model/event_types.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index 655e24ba..f832d63c 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -1,17 +1,17 @@ /* MIT License -* +* * Copyright (C) 2019, 2020, 2021 Famedly GmbH -* +* * 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 @@ -59,6 +59,9 @@ abstract class EventTypes { static const String KeyVerificationAccept = 'm.key.verification.accept'; static const String SecretRequest = 'm.secret.request'; static const String SecretSend = 'm.secret.send'; + static const String Dummy = 'm.dummy'; + + // Account data event types static const String CrossSigningSelfSigning = 'm.cross_signing.self_signing'; static const String CrossSigningUserSigning = 'm.cross_signing.user_signing'; static const String CrossSigningMasterKey = 'm.cross_signing.master'; From d8c12dd43da6b851ef28c11ac2b017773515f60e Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 20 Jan 2021 12:45:16 +0100 Subject: [PATCH 027/174] chore: Bump version --- CHANGELOG.md | 5 +++++ pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05b79c51..991e3a23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.5 + +- Add m.dummy event +- fix: Deep-copy arrays correctly + ## 0.1.4 - Fix creating shallow copies all the time diff --git a/pubspec.yaml b/pubspec.yaml index a9bfb810..1176c389 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.4 +version: 0.1.5 homepage: https://famedly.com environment: From 2b04551838ff05cd9e0d41b150fd50c863ad1971 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 20 Jan 2021 14:07:40 +0100 Subject: [PATCH 028/174] fix: well-known in fake_matrix_api --- CHANGELOG.md | 3 +++ lib/fake_matrix_api.dart | 10 +++++++--- pubspec.yaml | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 991e3a23..79f6e866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.1.6 + +- fix: well-known in fake_matrix_api ## 0.1.5 - Add m.dummy event diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 69060955..a38b7a9b 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -763,10 +763,14 @@ class FakeMatrixApi extends MockClient { }, '/media/r0/config': (var req) => {'m.upload.size': 50000000}, '/.well-known/matrix/client': (var req) => { - 'm.homeserver': {'base_url': 'https://matrix.example.com'}, - 'm.identity_server': {'base_url': 'https://identity.example.com'}, + 'm.homeserver': { + 'base_url': 'https://fakeserver.notexisting', + }, + 'm.identity_server': { + 'base_url': 'https://identity.fakeserver.notexisting' + }, 'org.example.custom.property': { - 'app_url': 'https://custom.app.example.org' + 'app_url': 'https://custom.app.fakeserver.notexisting' } }, '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags': diff --git a/pubspec.yaml b/pubspec.yaml index 1176c389..920ebc89 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.5 +version: 0.1.6 homepage: https://famedly.com environment: From 9617e76763e7b672fb25c7cf2c0ab6aeeb2ad03b Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 26 Jan 2021 15:32:04 +0100 Subject: [PATCH 029/174] change: Less noisy oneline logs --- CHANGELOG.md | 5 +++++ lib/src/utils/logs.dart | 16 +++++++++++++++- pubspec.yaml | 2 +- test/matrix_api_test.dart | 13 +++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79f6e866..b469972e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ +## 0.1.7 + +- change: Less noisy one-line logs + ## 0.1.6 - fix: well-known in fake_matrix_api + ## 0.1.5 - Add m.dummy event diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index e902859f..a6a64be5 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -36,7 +36,7 @@ class Logs extends Logger { Logs._internal() : super( - printer: PrettyPrinter(methodCount: 0, lineLength: 100), + printer: _MatrixSdkPrinter(), filter: _MatrixSdkFilter(), output: _CacheOutput(), ); @@ -54,3 +54,17 @@ class _CacheOutput extends ConsoleOutput { super.output(event); } } + +class _MatrixSdkPrinter extends PrettyPrinter { + _MatrixSdkPrinter() : super(methodCount: 0, lineLength: 100); + + @override + List log(LogEvent event) { + if (event.error == null && event.stackTrace == null) { + return [ + '${PrettyPrinter.levelColors[event.level]}${PrettyPrinter.levelEmojis[event.level]} ${event.message.toString()}' + ]; + } + return super.log(event); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 920ebc89..9d2cee96 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.6 +version: 0.1.7 homepage: https://famedly.com environment: diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index df6e1645..ecdff689 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -30,6 +30,19 @@ import 'package:test/test.dart'; void main() { /// All Tests related to device keys group('Matrix API', () { + test('Logger', () async { + Logs().level = Level.verbose; + Logs().v('Test log'); + Logs().d('Test log'); + Logs().w('Test log'); + Logs().e('Test log'); + Logs().wtf('Test log'); + Logs().v('Test log', Exception('Test')); + Logs().d('Test log', Exception('Test')); + Logs().w('Test log', Exception('Test')); + Logs().e('Test log', Exception('Test')); + Logs().wtf('Test log', Exception('Test')); + }); Logs().level = Level.error; final matrixApi = MatrixApi( httpClient: FakeMatrixApi(), From 0b7a0dffb9009ab559781b8f66b5935fa7d86428 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 9 Feb 2021 10:26:58 +0100 Subject: [PATCH 030/174] fix: Wrong parameters use --- CHANGELOG.md | 4 ++++ lib/src/matrix_api.dart | 27 ++++++++++++++++++--------- lib/src/model/filter.dart | 6 +++--- pubspec.yaml | 2 +- test/matrix_api_test.dart | 16 +++++++++------- 5 files changed, 35 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b469972e..c781a083 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8 + +- fix: Wrong parameters use + ## 0.1.7 - change: Less noisy one-line logs diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index bfe13ca7..91e11475 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -2038,7 +2038,8 @@ class MatrixApi { String sessionId, String version, RoomKeysSingleKey session) async { final ret = await request( RequestType.PUT, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + query: {'version': version}, data: session.toJson(), ); return RoomKeysUpdateResponse.fromJson(ret); @@ -2050,7 +2051,8 @@ class MatrixApi { String roomId, String sessionId, String version) async { final ret = await request( RequestType.GET, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + query: {'version': version}, ); return RoomKeysSingleKey.fromJson(ret); } @@ -2061,7 +2063,8 @@ class MatrixApi { String roomId, String sessionId, String version) async { final ret = await request( RequestType.DELETE, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + query: {'version': version}, ); return RoomKeysUpdateResponse.fromJson(ret); } @@ -2072,7 +2075,8 @@ class MatrixApi { String roomId, String version, RoomKeysRoom keys) async { final ret = await request( RequestType.PUT, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + query: {'version': version}, data: keys.toJson(), ); return RoomKeysUpdateResponse.fromJson(ret); @@ -2083,7 +2087,8 @@ class MatrixApi { Future getRoomKeysRoom(String roomId, String version) async { final ret = await request( RequestType.GET, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + query: {'version': version}, ); return RoomKeysRoom.fromJson(ret); } @@ -2094,7 +2099,8 @@ class MatrixApi { String roomId, String version) async { final ret = await request( RequestType.DELETE, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + query: {'version': version}, ); return RoomKeysUpdateResponse.fromJson(ret); } @@ -2105,7 +2111,8 @@ class MatrixApi { String version, RoomKeys keys) async { final ret = await request( RequestType.PUT, - '/client/unstable/room_keys/keys?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys', + query: {'version': version}, data: keys.toJson(), ); return RoomKeysUpdateResponse.fromJson(ret); @@ -2116,7 +2123,8 @@ class MatrixApi { Future getRoomKeys(String version) async { final ret = await request( RequestType.GET, - '/client/unstable/room_keys/keys?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys', + query: {'version': version}, ); return RoomKeys.fromJson(ret); } @@ -2126,7 +2134,8 @@ class MatrixApi { Future deleteRoomKeys(String version) async { final ret = await request( RequestType.DELETE, - '/client/unstable/room_keys/keys?version=${Uri.encodeComponent(version)}', + '/client/unstable/room_keys/keys', + query: {'version': version}, ); return RoomKeysUpdateResponse.fromJson(ret); } diff --git a/lib/src/model/filter.dart b/lib/src/model/filter.dart index 5b009fcd..7103ec1e 100644 --- a/lib/src/model/filter.dart +++ b/lib/src/model/filter.dart @@ -214,13 +214,13 @@ class StateFilter extends EventFilter { data['not_types'] = notTypes; } if (lazyLoadMembers != null) { - data['lazy_load_members'] = notTypes; + data['lazy_load_members'] = lazyLoadMembers; } if (includeRedundantMembers != null) { - data['include_redundant_members'] = notTypes; + data['include_redundant_members'] = includeRedundantMembers; } if (containsUrl != null) { - data['contains_url'] = notTypes; + data['contains_url'] = containsUrl; } return data; } diff --git a/pubspec.yaml b/pubspec.yaml index 9d2cee96..94f1ee46 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.7 +version: 0.1.8 homepage: https://famedly.com environment: diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index ecdff689..be00af9f 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -134,12 +134,14 @@ void main() { final wellKnownInformations = await matrixApi.requestWellKnownInformations(); expect(wellKnownInformations.mHomeserver.baseUrl, - 'https://matrix.example.com'); + 'https://fakeserver.notexisting'); expect(wellKnownInformations.toJson(), { - 'm.homeserver': {'base_url': 'https://matrix.example.com'}, - 'm.identity_server': {'base_url': 'https://identity.example.com'}, + 'm.homeserver': {'base_url': 'https://fakeserver.notexisting'}, + 'm.identity_server': { + 'base_url': 'https://identity.fakeserver.notexisting' + }, 'org.example.custom.property': { - 'app_url': 'https://custom.app.example.org' + 'app_url': 'https://custom.app.fakeserver.notexisting' } }); }); @@ -414,9 +416,9 @@ void main() { 'not_rooms': ['!1234'], 'not_senders': ['@bob:example.com'], 'not_types': ['type2'], - 'lazy_load_members': ['type2'], - 'include_redundant_members': ['type2'], - 'contains_url': ['type2'] + 'lazy_load_members': true, + 'include_redundant_members': false, + 'contains_url': true, }, 'account_data': { 'limit': 10, From 8573e1915f5cf2a53f48bcd2bdcb30f25355747d Mon Sep 17 00:00:00 2001 From: Sorunome Date: Mon, 15 Feb 2021 16:23:33 +0100 Subject: [PATCH 031/174] feat: Add fallback keys support --- lib/src/matrix_api.dart | 16 +++++++++++----- lib/src/model/sync_update.dart | 20 ++++++++++++++++---- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 91e11475..5042d01e 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -1,17 +1,17 @@ /* MIT License -* +* * Copyright (C) 2019, 2020, 2021 Famedly GmbH -* +* * 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 @@ -1427,13 +1427,19 @@ class MatrixApi { /// Publishes end-to-end encryption keys for the device. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query Future> uploadDeviceKeys( - {MatrixDeviceKeys deviceKeys, Map oneTimeKeys}) async { + {MatrixDeviceKeys deviceKeys, + Map oneTimeKeys, + Map fallbackKeys}) async { final response = await request( RequestType.POST, '/client/r0/keys/upload', data: { if (deviceKeys != null) 'device_keys': deviceKeys.toJson(), if (oneTimeKeys != null) 'one_time_keys': oneTimeKeys, + if (fallbackKeys != null) ...{ + 'fallback_keys': fallbackKeys, + 'org.matrix.msc2732.fallback_keys': fallbackKeys, + }, }, ); return Map.from(response['one_time_key_counts']); diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index 0be0150d..741b3405 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -1,17 +1,17 @@ /* MIT License -* +* * Copyright (C) 2019, 2020, 2021 Famedly GmbH -* +* * 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 @@ -37,6 +37,7 @@ class SyncUpdate { List toDevice; DeviceListsUpdate deviceLists; Map deviceOneTimeKeysCount; + List deviceUnusedFallbackKeyTypes; SyncUpdate(); @@ -66,6 +67,12 @@ class SyncUpdate { deviceOneTimeKeysCount = json['device_one_time_keys_count'] != null ? Map.from(json['device_one_time_keys_count']) : null; + deviceUnusedFallbackKeyTypes = (json['device_unused_fallback_key_types'] ?? + json['org.matrix.msc2732.device_unused_fallback_key_types']) != + null + ? List.from(json['device_unused_fallback_key_types'] ?? + json['org.matrix.msc2732.device_unused_fallback_key_types']) + : null; } Map toJson() { @@ -95,6 +102,11 @@ class SyncUpdate { if (deviceOneTimeKeysCount != null) { data['device_one_time_keys_count'] = deviceOneTimeKeysCount; } + if (deviceUnusedFallbackKeyTypes != null) { + data['device_unused_fallback_key_types'] = deviceUnusedFallbackKeyTypes; + data['org.matrix.msc2732.device_unused_fallback_key_types'] = + deviceUnusedFallbackKeyTypes; + } return data; } } From 31e72662efb0f369cd2e3d41a34948759421ba00 Mon Sep 17 00:00:00 2001 From: Sorunome Date: Fri, 19 Feb 2021 13:08:32 +0100 Subject: [PATCH 032/174] chore: version bump --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 94f1ee46..48825ac5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.8 +version: 0.1.9 homepage: https://famedly.com environment: From 512abfc47643609543750d23f23a86bb92703db1 Mon Sep 17 00:00:00 2001 From: Sorunome Date: Fri, 19 Feb 2021 13:09:17 +0100 Subject: [PATCH 033/174] chore: Add changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c781a083..c71fdc5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.1.9 +- feat: Add support for fallback keys + ## 0.1.8 - fix: Wrong parameters use @@ -33,4 +36,4 @@ ## 0.1.0 -- Initial version \ No newline at end of file +- Initial version From 7d91cdac5e02ce55e0ebec9efa0559bfb2bc211b Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 1 Mar 2021 11:35:00 +0100 Subject: [PATCH 034/174] fix: Typo and wellknown parsing --- .gitlab-ci.yml | 2 +- CONTRIBUTING.md | 2 +- lib/matrix_api_lite.dart | 4 +-- lib/src/matrix_api.dart | 15 ++++----- lib/src/model/login_response.dart | 11 +++---- ...tions.dart => room_alias_information.dart} | 4 +-- ...tions.dart => well_known_information.dart} | 33 ++++++++++++------- test/matrix_api_test.dart | 17 +++++----- 8 files changed, 47 insertions(+), 41 deletions(-) rename lib/src/model/{room_alias_informations.dart => room_alias_information.dart} (93%) rename lib/src/model/{well_known_informations.dart => well_known_information.dart} (65%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b324a26a..d5294662 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,7 +19,7 @@ code_analyze: image: cirrusci/flutter dependencies: [] script: - - flutter format lib/ test/ test_driver/ --set-exit-if-changed + - flutter format lib/ test/ --set-exit-if-changed - flutter analyze build_api_doc: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d9171e7..bdbe67d9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,4 +34,4 @@ flutter format lib/**/*/*.dart - Don't repeat yourself! Use local variables, functions, classes. - Write tests for new classes, functions and widgets. - Keep it simple stupid: https://en.wikipedia.org/wiki/KISS_principle -- Describe all of your classes, methods and attributes using **dartdoc** comments. Read this for more informations: https://dart.dev/guides/language/effective-dart/documentation \ No newline at end of file +- Describe all of your classes, methods and attributes using **dartdoc** comments. Read this for more information: https://dart.dev/guides/language/effective-dart/documentation \ No newline at end of file diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 9264103e..f44af1ea 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -55,7 +55,7 @@ export 'src/model/public_rooms_response.dart'; export 'src/model/push_rule_set.dart'; export 'src/model/pusher.dart'; export 'src/model/request_token_response.dart'; -export 'src/model/room_alias_informations.dart'; +export 'src/model/room_alias_information.dart'; export 'src/model/room_keys_info.dart'; export 'src/model/room_keys_keys.dart'; export 'src/model/room_summary.dart'; @@ -72,7 +72,7 @@ export 'src/model/timeline_history_response.dart'; export 'src/model/turn_server_credentials.dart'; export 'src/model/upload_key_signatures_response.dart'; export 'src/model/user_search_result.dart'; -export 'src/model/well_known_informations.dart'; +export 'src/model/well_known_information.dart'; export 'src/model/who_is_info.dart'; export 'src/model/auth/authentication_data.dart'; export 'src/model/auth/authentication_identifier.dart'; diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 5042d01e..037847dc 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -51,7 +51,7 @@ import 'model/public_rooms_response.dart'; import 'model/push_rule_set.dart'; import 'model/pusher.dart'; import 'model/request_token_response.dart'; -import 'model/room_alias_informations.dart'; +import 'model/room_alias_information.dart'; import 'model/room_keys_info.dart'; import 'model/room_keys_keys.dart'; import 'model/server_capabilities.dart'; @@ -66,7 +66,7 @@ import 'model/timeline_history_response.dart'; import 'model/turn_server_credentials.dart'; import 'model/upload_key_signatures_response.dart'; import 'model/user_search_result.dart'; -import 'model/well_known_informations.dart'; +import 'model/well_known_information.dart'; import 'model/who_is_info.dart'; enum RequestType { GET, POST, PUT, DELETE } @@ -233,14 +233,14 @@ class MatrixApi { /// Gets discovery information about the domain. The file may include additional keys. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-well-known-matrix-client - Future requestWellKnownInformations() async { + Future requestWellKnownInformation() async { var baseUrl = homeserver.toString(); if (baseUrl.endsWith('/')) { baseUrl = baseUrl.substring(0, baseUrl.length - 1); } final response = await httpClient.get('$baseUrl/.well-known/matrix/client'); final rawJson = json.decode(response.body); - return WellKnownInformations.fromJson(rawJson); + return WellKnownInformation.fromJson(rawJson); } Future requestLoginTypes() async { @@ -883,13 +883,12 @@ class MatrixApi { /// Requests that the server resolve a room alias to a room ID. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-room-roomalias - Future requestRoomAliasInformations( - String alias) async { + Future requestRoomAliasInformation(String alias) async { final response = await request( RequestType.GET, '/client/r0/directory/room/${Uri.encodeComponent(alias)}', ); - return RoomAliasInformations.fromJson(response); + return RoomAliasInformation.fromJson(response); } /// Remove a mapping of room alias to room ID. @@ -1726,7 +1725,7 @@ class MatrixApi { /// Performs a full text search across different categories. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-search /// Please note: The specification is not 100% clear what it is expecting and sending here. - /// So we stick with pure json until we have more informations. + /// So we stick with pure json until we have more information. Future> globalSearch(Map query) async { return await request( RequestType.POST, diff --git a/lib/src/model/login_response.dart b/lib/src/model/login_response.dart index 20960edb..d64b1cd2 100644 --- a/lib/src/model/login_response.dart +++ b/lib/src/model/login_response.dart @@ -21,21 +21,20 @@ * SOFTWARE. */ -import 'well_known_informations.dart'; +import 'well_known_information.dart'; class LoginResponse { String userId; String accessToken; String deviceId; - WellKnownInformations wellKnownInformations; + WellKnownInformation wellKnownInformation; LoginResponse.fromJson(Map json) { userId = json['user_id']; accessToken = json['access_token']; deviceId = json['device_id']; if (json['well_known'] is Map) { - wellKnownInformations = - WellKnownInformations.fromJson(json['well_known']); + wellKnownInformation = WellKnownInformation.fromJson(json['well_known']); } } @@ -44,8 +43,8 @@ class LoginResponse { if (userId != null) data['user_id'] = userId; if (accessToken != null) data['access_token'] = accessToken; if (deviceId != null) data['device_id'] = deviceId; - if (wellKnownInformations != null) { - data['well_known'] = wellKnownInformations.toJson(); + if (wellKnownInformation != null) { + data['well_known'] = wellKnownInformation.toJson(); } return data; } diff --git a/lib/src/model/room_alias_informations.dart b/lib/src/model/room_alias_information.dart similarity index 93% rename from lib/src/model/room_alias_informations.dart rename to lib/src/model/room_alias_information.dart index 82c40f4e..ae675991 100644 --- a/lib/src/model/room_alias_informations.dart +++ b/lib/src/model/room_alias_information.dart @@ -21,11 +21,11 @@ * SOFTWARE. */ -class RoomAliasInformations { +class RoomAliasInformation { String roomId; List servers; - RoomAliasInformations.fromJson(Map json) { + RoomAliasInformation.fromJson(Map json) { roomId = json['room_id']; servers = json['servers'].cast(); } diff --git a/lib/src/model/well_known_informations.dart b/lib/src/model/well_known_information.dart similarity index 65% rename from lib/src/model/well_known_informations.dart rename to lib/src/model/well_known_information.dart index 9978c237..631ef698 100644 --- a/lib/src/model/well_known_informations.dart +++ b/lib/src/model/well_known_information.dart @@ -21,25 +21,34 @@ * SOFTWARE. */ -class WellKnownInformations { +import '../utils/try_get_map_extension.dart'; + +class WellKnownInformation { MHomeserver mHomeserver; MHomeserver mIdentityServer; Map content; - WellKnownInformations.fromJson(Map json) { + WellKnownInformation.fromJson(Map json) { content = json; - mHomeserver = json['m.homeserver'] != null - ? MHomeserver.fromJson(json['m.homeserver']) - : null; - mIdentityServer = json['m.identity_server'] != null - ? MHomeserver.fromJson(json['m.identity_server']) - : null; + final mHomeserverMap = json.tryGetMap('m.homeserver'); + if (mHomeserverMap != null) { + mHomeserver = MHomeserver.fromJson(mHomeserverMap); + } + final mIdentityServerMap = + json.tryGetMap('m.identity_server'); + if (mIdentityServerMap != null) { + mIdentityServer = MHomeserver.fromJson(mIdentityServerMap); + } } Map toJson() { final data = content; - data['m.homeserver'] = mHomeserver.toJson(); - data['m.identity_server'] = mIdentityServer.toJson(); + if (mHomeserver != null) { + data['m.homeserver'] = mHomeserver.toJson(); + } + if (mIdentityServer != null) { + data['m.identity_server'] = mIdentityServer.toJson(); + } return data; } } @@ -48,12 +57,12 @@ class MHomeserver { String baseUrl; MHomeserver.fromJson(Map json) { - baseUrl = json['base_url']; + baseUrl = json.tryGet('base_url'); } Map toJson() { final data = {}; - data['base_url'] = baseUrl; + if (baseUrl != null) data['base_url'] = baseUrl; return data; } } diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index be00af9f..c52b0778 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -129,13 +129,13 @@ void main() { supportedVersions.toJson()); matrixApi.homeserver = null; }); - test('getWellKnownInformations', () async { + test('getWellKnownInformation', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final wellKnownInformations = - await matrixApi.requestWellKnownInformations(); - expect(wellKnownInformations.mHomeserver.baseUrl, + final wellKnownInformation = + await matrixApi.requestWellKnownInformation(); + expect(wellKnownInformation.mHomeserver.baseUrl, 'https://fakeserver.notexisting'); - expect(wellKnownInformations.toJson(), { + expect(wellKnownInformation.toJson(), { 'm.homeserver': {'base_url': 'https://fakeserver.notexisting'}, 'm.identity_server': { 'base_url': 'https://identity.fakeserver.notexisting' @@ -654,19 +654,18 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestRoomAliasInformations', () async { + test('requestRoomAliasInformation', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final roomAliasInformations = - await matrixApi.requestRoomAliasInformations( + final roomAliasInformation = await matrixApi.requestRoomAliasInformation( '#testalias:example.com', ); expect( FakeMatrixApi.api['GET'] ['/client/r0/directory/room/%23testalias%3Aexample.com']({}), - roomAliasInformations.toJson()); + roomAliasInformation.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); From e28b0fa1b3df01b596154da26a523439961c8d5d Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 9 Mar 2021 07:40:16 +0100 Subject: [PATCH 035/174] refactor: login method AuthenticationIdentifier This is a breaking change for the login method to use the correct format. It makes it possible to login with email or phone. Also this does some housekeeping stuff while upgrading to pedantic 1.11.0 which doesnt allow curly braces in Strings where not needed anymore. --- CHANGELOG.md | 10 ++++++++++ lib/src/matrix_api.dart | 23 ++++++++++++----------- pubspec.yaml | 6 +++--- test/matrix_api_test.dart | 5 +++-- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c71fdc5f..808c2a9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.2.0 +- refactor: login method AuthenticationIdentifier + +This is a breaking change for the login method to use the correct format. +It makes it possible to login with email or phone. +Also this does some housekeeping stuff while +upgrading to pedantic 1.11.0 which doesnt +allow curly braces in Strings where not needed +anymore. + ## 0.1.9 - feat: Add support for fallback keys diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 037847dc..b227f375 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -28,6 +28,7 @@ import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'package:mime/mime.dart'; +import '../matrix_api_lite.dart'; import 'model/auth/authentication_data.dart'; import 'model/auth/authentication_types.dart'; import 'model/device.dart'; @@ -152,7 +153,7 @@ class MatrixApi { ?.where((x) => x.value != null) ?.map((x) => [x.key, x.value].map(Uri.encodeQueryComponent).join('=')) ?.join('&'); - final url = ['${homeserver.toString()}/_matrix${action}', queryPart] + final url = ['${homeserver.toString()}/_matrix$action', queryPart] .where((x) => x != null && x != '') .join('?'); @@ -161,7 +162,7 @@ class MatrixApi { headers['Content-Type'] = contentType; } if (accessToken != null) { - headers['Authorization'] = 'Bearer ${accessToken}'; + headers['Authorization'] = 'Bearer $accessToken'; } http.Response resp; @@ -253,25 +254,25 @@ class MatrixApi { /// Authenticates the user, and issues an access token they can use to authorize themself in subsequent requests. /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-login + /// To just login with the username 'alice' you set [identifier] to: + /// `AuthenticationUserIdentifier(user: 'alice')` + /// Maybe you want to set [user] to the same String to stay compatible with + /// older server versions. Future login({ String type = AuthenticationTypes.password, - String userIdentifierType, - String user, - String medium, - String address, + AuthenticationIdentifier identifier, String password, String token, String deviceId, String initialDeviceDisplayName, AuthenticationData auth, + @Deprecated('Deprecated in favour of identifier.') String user, + @Deprecated('Deprecated in favour of identifier.') String medium, + @Deprecated('Deprecated in favour of identifier.') String address, }) async { final response = await request(RequestType.POST, '/client/r0/login', data: { 'type': type, - if (userIdentifierType != null) - 'identifier': { - 'type': userIdentifierType, - if (user != null) 'user': user, - }, + if (identifier != null) 'identifier': identifier.toJson(), if (user != null) 'user': user, if (medium != null) 'medium': medium, if (address != null) 'address': address, diff --git a/pubspec.yaml b/pubspec.yaml index 48825ac5..ec883d32 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.1.9 +version: 0.2.0 homepage: https://famedly.com environment: - sdk: '>=2.10.0 <3.0.0' + sdk: ">=2.10.0 <3.0.0" dependencies: http: ^0.12.2 @@ -12,5 +12,5 @@ dependencies: mime: ^0.9.7 dev_dependencies: - pedantic: ^1.9.0 + pedantic: ^1.11.0 test: ^1.14.4 diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index c52b0778..c25f8430 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -155,8 +155,9 @@ void main() { }); test('login', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final loginResponse = - await matrixApi.login(userIdentifierType: 'username'); + final loginResponse = await matrixApi.login( + identifier: AuthenticationUserIdentifier(user: 'username'), + ); expect(FakeMatrixApi.api['POST']['/client/r0/login']({}), loginResponse.toJson()); matrixApi.homeserver = null; From 7a078251a6413be003d72f9b5bac4e8aedaac72f Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Sat, 27 Feb 2021 09:01:22 +0000 Subject: [PATCH 036/174] fix: IdServerUnbindResult typo --- lib/src/matrix_api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index b227f375..7e43e342 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -71,7 +71,7 @@ import 'model/well_known_information.dart'; import 'model/who_is_info.dart'; enum RequestType { GET, POST, PUT, DELETE } -enum IdServerUnbindResult { success, no_success } +enum IdServerUnbindResult { success, no_support } enum ThirdPartyIdentifierMedium { email, msisdn } enum Membership { join, invite, leave, ban } enum Direction { b, f } From 11904f4da1e30ddf71a5a607ead994c815e8ad52 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 30 Mar 2021 12:29:46 +0200 Subject: [PATCH 037/174] fix: Remove unused dependency mime --- CHANGELOG.md | 3 +++ pubspec.yaml | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 808c2a9c..28e8533d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.2.1 +- fix: Remove unused dependency mime + ## 0.2.0 - refactor: login method AuthenticationIdentifier diff --git a/pubspec.yaml b/pubspec.yaml index ec883d32..6aadbf69 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.2.0 +version: 0.2.1 homepage: https://famedly.com environment: @@ -9,7 +9,6 @@ environment: dependencies: http: ^0.12.2 logger: ^0.9.4 - mime: ^0.9.7 dev_dependencies: pedantic: ^1.11.0 From af693700fb9b5d807599b7dcf8092252cbcadc1f Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 30 Mar 2021 12:37:08 +0200 Subject: [PATCH 038/174] fix: Mime --- CHANGELOG.md | 2 +- pubspec.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28e8533d..de3dd453 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ ## 0.2.1 -- fix: Remove unused dependency mime +- fix: Update dependency mime ## 0.2.0 - refactor: login method AuthenticationIdentifier diff --git a/pubspec.yaml b/pubspec.yaml index 6aadbf69..76d7feb8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,6 +9,7 @@ environment: dependencies: http: ^0.12.2 logger: ^0.9.4 + mime: ^1.0.0 dev_dependencies: pedantic: ^1.11.0 From 04674e2dfd8158a05c2e5a779f09209a1adc3949 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Tue, 30 Mar 2021 14:29:24 +0200 Subject: [PATCH 039/174] refactor: upgrade to http 0.13 --- lib/src/matrix_api.dart | 84 +++++++++++++++++++---------------------- pubspec.yaml | 2 +- 2 files changed, 40 insertions(+), 46 deletions(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 7e43e342..d55082f5 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -139,7 +139,7 @@ class MatrixApi { dynamic data = '', int timeout, String contentType = 'application/json', - Map query, + Map query, }) async { if (homeserver == null) { throw ('No homeserver specified.'); @@ -149,13 +149,8 @@ class MatrixApi { (!(data is String)) ? json = jsonEncode(data) : json = data; if (data is List || action.startsWith('/media/r0/upload')) json = data; - final queryPart = query?.entries - ?.where((x) => x.value != null) - ?.map((x) => [x.key, x.value].map(Uri.encodeQueryComponent).join('=')) - ?.join('&'); - final url = ['${homeserver.toString()}/_matrix$action', queryPart] - .where((x) => x != null && x != '') - .join('?'); + final url = homeserver + .resolveUri(Uri(path: '_matrix$action', queryParameters: query)); var headers = {}; if (type == RequestType.PUT || type == RequestType.POST) { @@ -235,11 +230,8 @@ class MatrixApi { /// Gets discovery information about the domain. The file may include additional keys. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-well-known-matrix-client Future requestWellKnownInformation() async { - var baseUrl = homeserver.toString(); - if (baseUrl.endsWith('/')) { - baseUrl = baseUrl.substring(0, baseUrl.length - 1); - } - final response = await httpClient.get('$baseUrl/.well-known/matrix/client'); + final response = + await httpClient.get(homeserver.resolve('.well-known/matrix/client')); final rawJson = json.decode(response.body); return WellKnownInformation.fromJson(rawJson); } @@ -332,9 +324,10 @@ class MatrixApi { AuthenticationData auth, String kind, }) async { - var action = '/client/r0/register'; - if (kind != null) action += '?kind=${Uri.encodeQueryComponent(kind)}'; - final response = await request(RequestType.POST, action, data: { + final response = + await request(RequestType.POST, '/client/r0/register', query: { + if (kind != null) 'kind': kind, + }, data: { if (username != null) 'username': username, if (password != null) 'password': password, if (deviceId != null) 'device_id': deviceId, @@ -483,7 +476,10 @@ class MatrixApi { Future usernameAvailable(String username) async { final response = await request( RequestType.GET, - '/client/r0/register/available?username=$username', + '/client/r0/register/available', + query: { + 'username': username, + }, ); return response['available']; } @@ -970,16 +966,10 @@ class MatrixApi { String thirdPidSignedToken, Map thirdPidSignedSiganture, }) async { - var action = '/client/r0/join/${Uri.encodeComponent(roomIdOrAlias)}'; - final queryPart = servers - ?.map((x) => 'server_name=${Uri.encodeQueryComponent(x)}') - ?.join('&'); - if (queryPart != null && queryPart != '') { - action += '?' + queryPart; - } final response = await request( RequestType.POST, - action, + '/client/r0/join/${Uri.encodeComponent(roomIdOrAlias)}', + query: {'server_name': servers}, data: { if (thirdPidSignedSiganture != null) 'third_party_signed': { @@ -1307,9 +1297,11 @@ class MatrixApi { contentType ?? lookupMimeType(fileName, headerBytes: file); headers['Content-Length'] = length.toString(); fileName = Uri.encodeQueryComponent(fileName); - final url = - '${homeserver.toString()}/_matrix/media/r0/upload?filename=$fileName'; - final streamedRequest = http.StreamedRequest('POST', Uri.parse(url)) + final url = homeserver.resolveUri(Uri( + path: '_matrix/media/r0/upload', + queryParameters: {'filename': fileName}, + )); + final streamedRequest = http.StreamedRequest('POST', url) ..headers.addAll(headers); streamedRequest.contentLength = length; streamedRequest.sink.add(file); @@ -1333,11 +1325,11 @@ class MatrixApi { /// URL in a message and wants to render a preview for the user. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-preview-url Future requestOpenGraphDataForUrl(Uri url, {int ts}) async { - var action = - '${homeserver.toString()}/_matrix/media/r0/preview_url?url=${Uri.encodeQueryComponent(url.toString())}'; - if (ts != null) { - action += '&ts=${Uri.encodeQueryComponent(ts.toString())}'; - } + var action = homeserver + .resolveUri(Uri(path: '_matrix/media/r0/preview_url', queryParameters: { + 'url': url.toString(), + if (ts != null) 'ts': ts.toString(), + })); final response = await httpClient.get(action); final rawJson = json.decode(response.body.isEmpty ? '{}' : response.body); return OpenGraphData.fromJson(rawJson); @@ -1346,7 +1338,7 @@ class MatrixApi { /// This endpoint allows clients to retrieve the configuration of the content repository, such as upload limitations. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-config Future requestMaxUploadSize() async { - var action = '${homeserver.toString()}/_matrix/media/r0/config'; + var action = homeserver.resolve('_matrix/media/r0/config'); final response = await httpClient.get(action); final rawJson = json.decode(response.body.isEmpty ? '{}' : response.body); return rawJson['m.upload.size']; @@ -1485,10 +1477,11 @@ class MatrixApi { /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-upload Future requestDeviceListsUpdate( String from, String to) async { - final response = await request( - RequestType.GET, - '/client/r0/keys/changes?from=${Uri.encodeQueryComponent(from)}&to=${Uri.encodeQueryComponent(to)}', - ); + final response = + await request(RequestType.GET, '/client/r0/keys/changes', query: { + 'from': from, + 'to': to, + }); return DeviceListsUpdate.fromJson(response); } @@ -1946,9 +1939,10 @@ class MatrixApi { Future> requestThirdPartyLocationsByAlias( String alias) async { final response = await request( - RequestType.GET, - '/client/r0/thirdparty/location?alias=${Uri.encodeComponent(alias)}', - ); + RequestType.GET, '/client/r0/thirdparty/location', + query: { + 'alias': alias, + }); return (response['chunk'] as List) .map((i) => ThirdPartyLocation.fromJson(i)) .toList(); @@ -1958,10 +1952,10 @@ class MatrixApi { /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-user Future> requestThirdPartyUsersByUserId( String userId) async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/user?userid=${Uri.encodeComponent(userId)}', - ); + final response = + await request(RequestType.GET, '/client/r0/thirdparty/user', query: { + 'userid': userId, + }); return (response['chunk'] as List) .map((i) => ThirdPartyUser.fromJson(i)) .toList(); diff --git a/pubspec.yaml b/pubspec.yaml index 76d7feb8..f8ecc97c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: ">=2.10.0 <3.0.0" dependencies: - http: ^0.12.2 + http: ^0.13.0 logger: ^0.9.4 mime: ^1.0.0 From 8f0e20c044dbcd5fd4feaf0cdbe723b1806ef170 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Tue, 30 Mar 2021 14:52:17 +0200 Subject: [PATCH 040/174] chore: upgrade logger to 1.0.0 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index f8ecc97c..b948acea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,7 @@ environment: dependencies: http: ^0.13.0 - logger: ^0.9.4 + logger: ^1.0.0 mime: ^1.0.0 dev_dependencies: From af70aee53775260e1f765b5bfe2a8eca7186625f Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 31 Mar 2021 13:42:09 +0200 Subject: [PATCH 041/174] chore: Update version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de3dd453..d5a278db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.2 +- chore: upgrade logger to 1.0.0 +- refactor: upgrade to http 0.13 + ## 0.2.1 - fix: Update dependency mime diff --git a/pubspec.yaml b/pubspec.yaml index b948acea..adaba938 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.2.1 +version: 0.2.2 homepage: https://famedly.com environment: From 924af98f303c295db7a92135cf2f2a7c566ebe67 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Wed, 31 Mar 2021 18:33:59 +0200 Subject: [PATCH 042/174] fix: no empty server_name parameter --- lib/src/matrix_api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index d55082f5..47173c70 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -969,7 +969,7 @@ class MatrixApi { final response = await request( RequestType.POST, '/client/r0/join/${Uri.encodeComponent(roomIdOrAlias)}', - query: {'server_name': servers}, + query: {'server_name': servers ?? []}, data: { if (thirdPidSignedSiganture != null) 'third_party_signed': { From cd76448f8b7e50257a93c63dc7aca142364aa30e Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 12 Apr 2021 09:00:11 +0200 Subject: [PATCH 043/174] feat: Add room and event types for spaces --- CHANGELOG.md | 3 +++ lib/src/model/event_types.dart | 4 ++++ lib/src/model/room_types.dart | 29 +++++++++++++++++++++++++++++ pubspec.yaml | 2 +- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 lib/src/model/room_types.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index d5a278db..03041072 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.2.2 +- feat: Add room and event types for spaces + ## 0.2.2 - chore: upgrade logger to 1.0.0 - refactor: upgrade to http 0.13 diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index f832d63c..69251296 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -68,4 +68,8 @@ abstract class EventTypes { static const String MegolmBackup = 'm.megolm_backup.v1'; static const String SecretStorageDefaultKey = 'm.secret_storage.default_key'; static String secretStorageKey(String keyId) => 'm.secret_storage.key.$keyId'; + + // Spaces + static const String spaceParent = 'm.space.parent'; + static const String spaceChild = 'm.space.child'; } diff --git a/lib/src/model/room_types.dart b/lib/src/model/room_types.dart new file mode 100644 index 00000000..ba551ae9 --- /dev/null +++ b/lib/src/model/room_types.dart @@ -0,0 +1,29 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + +/// Type of a room which is presented in a `m.room.creation` state content in +/// the `type` key. +abstract class RoomCreationTypes { + static const String mSpace = 'm.space'; + static const String mDirectMessage = 'm.dm'; +} diff --git a/pubspec.yaml b/pubspec.yaml index adaba938..e033342d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.2.2 +version: 0.2.3 homepage: https://famedly.com environment: From a84e196b0334f9594fd9aff67ff0a54013f991a4 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 12 Apr 2021 09:00:30 +0200 Subject: [PATCH 044/174] fix: Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03041072..a28cb192 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.2.2 +## 0.2.3 - feat: Add room and event types for spaces ## 0.2.2 From 88d0eae2b73fbc2b16742841d4ccb7ce1534fd47 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Sat, 1 May 2021 09:00:31 +0200 Subject: [PATCH 045/174] fix: Request aliases --- CHANGELOG.md | 3 +++ lib/fake_matrix_api.dart | 2 +- lib/src/matrix_api.dart | 2 +- pubspec.yaml | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a28cb192..e5375fde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.2.4 +- fix: Request aliases + ## 0.2.3 - feat: Add room and event types for spaces diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index a38b7a9b..7786b4ea 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1150,7 +1150,7 @@ class FakeMatrixApi extends MockClient { 'prev_batch': 'p1902', 'total_room_count_estimate': 115 }, - '/client/r0/room/!localpart%3Aexample.com/aliases': (var req) => { + '/client/r0/rooms/!localpart%3Aexample.com/aliases': (var req) => { 'aliases': [ '#somewhere:example.com', '#another:example.com', diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 47173c70..d32e3524 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -903,7 +903,7 @@ class MatrixApi { Future> requestRoomAliases(String roomId) async { final response = await request( RequestType.GET, - '/client/r0/room/${Uri.encodeComponent(roomId)}/aliases', + '/client/r0/rooms/${Uri.encodeComponent(roomId)}/aliases', ); return List.from(response['aliases']); } diff --git a/pubspec.yaml b/pubspec.yaml index e033342d..2eefdbd5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.2.3 +version: 0.2.4 homepage: https://famedly.com environment: From ddce012498286754763df7f3fc8072a6a581bc17 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Sat, 1 May 2021 09:01:20 +0200 Subject: [PATCH 046/174] chore: Bump version --- CHANGELOG.md | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5375fde..2abd35f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.2.4 +## 0.2.5 - fix: Request aliases ## 0.2.3 diff --git a/pubspec.yaml b/pubspec.yaml index 2eefdbd5..4a6177c7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.2.4 +version: 0.2.5 homepage: https://famedly.com environment: From a5af392fb89c288adedc1d53bb58e16726cb6d17 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Sat, 1 May 2021 09:26:18 +0200 Subject: [PATCH 047/174] fix: Missing RoomCreationTypes --- CHANGELOG.md | 3 +++ lib/matrix_api_lite.dart | 1 + lib/src/model/room_creation_types.dart | 3 +++ pubspec.yaml | 2 +- 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 lib/src/model/room_creation_types.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 2abd35f9..d30a93d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.2.6 +- fix: Missing RoomCreationTypes + ## 0.2.5 - fix: Request aliases diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index f44af1ea..afd709b0 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -56,6 +56,7 @@ export 'src/model/push_rule_set.dart'; export 'src/model/pusher.dart'; export 'src/model/request_token_response.dart'; export 'src/model/room_alias_information.dart'; +export 'src/model/room_creation_types.dart'; export 'src/model/room_keys_info.dart'; export 'src/model/room_keys_keys.dart'; export 'src/model/room_summary.dart'; diff --git a/lib/src/model/room_creation_types.dart b/lib/src/model/room_creation_types.dart new file mode 100644 index 00000000..703f0ce1 --- /dev/null +++ b/lib/src/model/room_creation_types.dart @@ -0,0 +1,3 @@ +abstract class RoomCreationTypes { + static const String mSpace = 'm.space'; +} diff --git a/pubspec.yaml b/pubspec.yaml index 4a6177c7..9c1b9de8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.2.5 +version: 0.2.6 homepage: https://famedly.com environment: From 19500307be0a3da7868b005d40e686605db08d79 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Wed, 5 May 2021 12:05:26 +0200 Subject: [PATCH 048/174] refactor: call fromJson constructor of base class --- lib/src/model/basic_event_with_sender.dart | 6 ++---- lib/src/model/basic_room_event.dart | 5 +---- lib/src/model/filter.dart | 9 +-------- lib/src/model/matrix_event.dart | 7 +------ lib/src/model/presence.dart | 6 +----- lib/src/model/stripped_state_event.dart | 7 ++----- 6 files changed, 8 insertions(+), 32 deletions(-) diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index 6c93fd07..6c90e8c9 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -28,10 +28,8 @@ class BasicEventWithSender extends BasicEvent { BasicEventWithSender(); - BasicEventWithSender.fromJson(Map json) { - final basicEvent = BasicEvent.fromJson(json); - type = basicEvent.type; - content = basicEvent.content; + BasicEventWithSender.fromJson(Map json) + : super.fromJson(json) { senderId = json['sender']; } diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index 8a97ee72..27f28e8f 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -35,10 +35,7 @@ class BasicRoomEvent extends BasicEvent { type: type, ); - BasicRoomEvent.fromJson(Map json) { - final basicEvent = BasicEvent.fromJson(json); - content = basicEvent.content; - type = basicEvent.type; + BasicRoomEvent.fromJson(Map json) : super.fromJson(json) { roomId = json['room_id']; } diff --git a/lib/src/model/filter.dart b/lib/src/model/filter.dart index 7103ec1e..391537cf 100644 --- a/lib/src/model/filter.dart +++ b/lib/src/model/filter.dart @@ -190,14 +190,7 @@ class StateFilter extends EventFilter { notSenders: notSenders, ); - StateFilter.fromJson(Map json) { - final eventFilter = EventFilter.fromJson(json); - limit = eventFilter.limit; - senders = eventFilter.senders; - types = eventFilter.types; - notRooms = eventFilter.notRooms; - notSenders = eventFilter.notSenders; - + StateFilter.fromJson(Map json) : super.fromJson(json) { notTypes = json['not_types']?.cast(); lazyLoadMembers = json['lazy_load_members']; includeRedundantMembers = json['include_redundant_members']; diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index 74dd4296..705f2f04 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -34,12 +34,7 @@ class MatrixEvent extends StrippedStateEvent { MatrixEvent(); - MatrixEvent.fromJson(Map json) { - final strippedStateEvent = StrippedStateEvent.fromJson(json); - content = strippedStateEvent.content; - type = strippedStateEvent.type; - senderId = strippedStateEvent.senderId; - stateKey = strippedStateEvent.stateKey; + MatrixEvent.fromJson(Map json) : super.fromJson(json) { eventId = json['event_id']; roomId = json['room_id']; originServerTs = diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index 93d17c9b..7d9fb753 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -27,11 +27,7 @@ import 'presence_content.dart'; class Presence extends BasicEventWithSender { PresenceContent presence; - Presence.fromJson(Map json) { - final basicEvent = BasicEventWithSender.fromJson(json); - type = basicEvent.type; - content = basicEvent.content; - senderId = basicEvent.senderId; + Presence.fromJson(Map json) : super.fromJson(json) { presence = PresenceContent.fromJson(content); } } diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index da9298ff..e6d1edd5 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -27,11 +27,8 @@ class StrippedStateEvent extends BasicEventWithSender { String stateKey; StrippedStateEvent(); - StrippedStateEvent.fromJson(Map json) { - final basicEvent = BasicEventWithSender.fromJson(json); - content = basicEvent.content; - type = basicEvent.type; - senderId = basicEvent.senderId; + StrippedStateEvent.fromJson(Map json) + : super.fromJson(json) { stateKey = json['state_key']; } From 83ef6484eb6d1ce487e85414746d5e962cca0686 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Wed, 5 May 2021 12:05:26 +0200 Subject: [PATCH 049/174] refactor: use map --- lib/src/model/event_context.dart | 20 ++++++++----------- lib/src/model/login_types.dart | 5 +---- lib/src/model/matrix_exception.dart | 12 +++++------ .../model/notifications_query_response.dart | 7 +++---- lib/src/model/public_rooms_response.dart | 5 +---- lib/src/model/supported_protocol.dart | 7 +++---- lib/src/model/user_search_result.dart | 7 ++----- lib/src/model/who_is_info.dart | 13 +++++------- lib/src/utils/map_copy_extension.dart | 6 +----- 9 files changed, 29 insertions(+), 53 deletions(-) diff --git a/lib/src/model/event_context.dart b/lib/src/model/event_context.dart index 2bdc026d..aeee869e 100644 --- a/lib/src/model/event_context.dart +++ b/lib/src/model/event_context.dart @@ -34,24 +34,20 @@ class EventContext { EventContext.fromJson(Map json) { end = json['end']; if (json['events_after'] != null) { - eventsAfter = []; - json['events_after'].forEach((v) { - eventsAfter.add(MatrixEvent.fromJson(v)); - }); + eventsAfter = (json['events_after'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(); } event = json['event'] != null ? MatrixEvent.fromJson(json['event']) : null; if (json['events_before'] != null) { - eventsBefore = []; - json['events_before'].forEach((v) { - eventsBefore.add(MatrixEvent.fromJson(v)); - }); + eventsBefore = (json['events_before'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(); } start = json['start']; if (json['state'] != null) { - state = []; - json['state'].forEach((v) { - state.add(MatrixEvent.fromJson(v)); - }); + state = + (json['state'] as List).map((v) => MatrixEvent.fromJson(v)).toList(); } } diff --git a/lib/src/model/login_types.dart b/lib/src/model/login_types.dart index f95098ad..de8dca7f 100644 --- a/lib/src/model/login_types.dart +++ b/lib/src/model/login_types.dart @@ -26,10 +26,7 @@ class LoginTypes { LoginTypes.fromJson(Map json) { if (json['flows'] != null) { - flows = []; - json['flows'].forEach((v) { - flows.add(Flows.fromJson(v)); - }); + flows = (json['flows'] as List).map((v) => Flows.fromJson(v)).toList(); } } diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 00af277e..1e1b3bf4 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -88,13 +88,11 @@ class MatrixException implements Exception { /// doesn't need additional authentication, then this is null. List get authenticationFlows { if (!raw.containsKey('flows') || !(raw['flows'] is List)) return null; - var flows = []; - for (Map flow in raw['flows']) { - if (flow['stages'] is List) { - flows.add(AuthenticationFlow(List.from(flow['stages']))); - } - } - return flows; + return (raw['flows'] as List) + .map((flow) => flow['stages']) + .whereType() + .map((stages) => AuthenticationFlow(List.from(stages))) + .toList(); } /// This section contains any information that the client will need to know in order to use a given type diff --git a/lib/src/model/notifications_query_response.dart b/lib/src/model/notifications_query_response.dart index 01b2777c..aaeadbda 100644 --- a/lib/src/model/notifications_query_response.dart +++ b/lib/src/model/notifications_query_response.dart @@ -29,10 +29,9 @@ class NotificationsQueryResponse { NotificationsQueryResponse.fromJson(Map json) { nextToken = json['next_token']; - notifications = []; - json['notifications'].forEach((v) { - notifications.add(Notification.fromJson(v)); - }); + notifications = (json['notifications'] as List) + .map((v) => Notification.fromJson(v)) + .toList(); } Map toJson() { diff --git a/lib/src/model/public_rooms_response.dart b/lib/src/model/public_rooms_response.dart index 56671440..34ae0bf7 100644 --- a/lib/src/model/public_rooms_response.dart +++ b/lib/src/model/public_rooms_response.dart @@ -28,10 +28,7 @@ class PublicRoomsResponse { int totalRoomCountEstimate; PublicRoomsResponse.fromJson(Map json) { - chunk = []; - json['chunk'].forEach((v) { - chunk.add(PublicRoom.fromJson(v)); - }); + chunk = (json['chunk'] as List).map((v) => PublicRoom.fromJson(v)).toList(); nextBatch = json['next_batch']; prevBatch = json['prev_batch']; totalRoomCountEstimate = json['total_room_count_estimate']; diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart index 0f0c1b30..a81c6bd8 100644 --- a/lib/src/model/supported_protocol.dart +++ b/lib/src/model/supported_protocol.dart @@ -34,10 +34,9 @@ class SupportedProtocol { icon = json['icon']; fieldTypes = (json['field_types'] as Map) .map((k, v) => MapEntry(k, ProtocolFieldType.fromJson(v))); - instances = []; - json['instances'].forEach((v) { - instances.add(ProtocolInstance.fromJson(v)); - }); + instances = (json['instances'] as List) + .map((v) => ProtocolInstance.fromJson(v)) + .toList(); } Map toJson() { diff --git a/lib/src/model/user_search_result.dart b/lib/src/model/user_search_result.dart index 837a08ec..27c84d7c 100644 --- a/lib/src/model/user_search_result.dart +++ b/lib/src/model/user_search_result.dart @@ -28,11 +28,8 @@ class UserSearchResult { bool limited; UserSearchResult.fromJson(Map json) { - results = []; - json['results'].forEach((v) { - results.add(Profile.fromJson(v)); - }); - + results = + (json['results'] as List).map((v) => Profile.fromJson(v)).toList(); limited = json['limited']; } diff --git a/lib/src/model/who_is_info.dart b/lib/src/model/who_is_info.dart index be144736..5504a24d 100644 --- a/lib/src/model/who_is_info.dart +++ b/lib/src/model/who_is_info.dart @@ -48,10 +48,8 @@ class DeviceInfo { DeviceInfo.fromJson(Map json) { if (json['sessions'] != null) { - sessions = []; - json['sessions'].forEach((v) { - sessions.add(Sessions.fromJson(v)); - }); + sessions = + (json['sessions'] as List).map((v) => Sessions.fromJson(v)).toList(); } } @@ -69,10 +67,9 @@ class Sessions { Sessions.fromJson(Map json) { if (json['connections'] != null) { - connections = []; - json['connections'].forEach((v) { - connections.add(Connections.fromJson(v)); - }); + connections = (json['connections'] as List) + .map((v) => Connections.fromJson(v)) + .toList(); } } diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart index 9e3018b7..2cf95989 100644 --- a/lib/src/utils/map_copy_extension.dart +++ b/lib/src/utils/map_copy_extension.dart @@ -27,11 +27,7 @@ extension MapCopyExtension on Map { return value.copy(); } if (value is List) { - final ret = []; - for (final val in value) { - ret.add(_copyValue(val)); - } - return ret; + return value.map(_copyValue).toList(); } return value; } From 23db25d4af075f1ae5841914a0083827a9df32ec Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Wed, 5 May 2021 12:05:26 +0200 Subject: [PATCH 050/174] refactor: use .. --- lib/src/model/server_capabilities.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart index 3b2c2025..0e11e1f9 100644 --- a/lib/src/model/server_capabilities.dart +++ b/lib/src/model/server_capabilities.dart @@ -37,9 +37,9 @@ class ServerCapabilities { mRoomVersions = json['m.room_versions'] != null ? MRoomVersions.fromJson(json['m.room_versions']) : null; - customCapabilities = json.copy(); - customCapabilities.remove('m.change_password'); - customCapabilities.remove('m.room_versions'); + customCapabilities = json.copy() + ..remove('m.change_password') + ..remove('m.room_versions'); } Map toJson() { From 9de57fad9ba17631e0f741de2ebe1d152b96d840 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Wed, 5 May 2021 12:05:26 +0200 Subject: [PATCH 051/174] refactor: initializer lists in fromJson constructors --- lib/src/model/auth/authentication_data.dart | 7 +- .../model/auth/authentication_identifier.dart | 5 +- .../model/auth/authentication_password.dart | 8 +- .../auth/authentication_phone_identifier.dart | 7 +- .../model/auth/authentication_recaptcha.dart | 5 +- ...authentication_third_party_identifier.dart | 7 +- .../auth/authentication_three_pid_creds.dart | 11 ++- lib/src/model/auth/authentication_token.dart | 7 +- .../auth/authentication_user_identifier.dart | 5 +- lib/src/model/basic_event.dart | 8 +- lib/src/model/basic_event_with_sender.dart | 5 +- lib/src/model/basic_room_event.dart | 6 +- lib/src/model/device.dart | 12 +-- lib/src/model/event_context.dart | 39 +++++----- lib/src/model/events_sync_update.dart | 15 ++-- lib/src/model/filter.dart | 31 ++++---- lib/src/model/keys_query_response.dart | 75 +++++++++---------- lib/src/model/login_response.dart | 15 ++-- lib/src/model/matrix_event.dart | 18 ++--- lib/src/model/matrix_keys.dart | 21 +++--- .../model/notifications_query_response.dart | 11 ++- .../model/one_time_keys_claim_response.dart | 11 ++- lib/src/model/open_graph_data.dart | 17 ++--- lib/src/model/open_id_credentials.dart | 11 ++- lib/src/model/presence.dart | 6 +- lib/src/model/presence_content.dart | 13 ++-- lib/src/model/public_rooms_response.dart | 33 ++++---- lib/src/model/pusher.dart | 28 +++---- lib/src/model/request_token_response.dart | 7 +- lib/src/model/room_alias_information.dart | 7 +- lib/src/model/room_keys_info.dart | 17 ++--- lib/src/model/room_keys_keys.dart | 32 ++++---- lib/src/model/room_summary.dart | 13 ++-- lib/src/model/server_capabilities.dart | 21 +++--- lib/src/model/stripped_state_event.dart | 5 +- lib/src/model/supported_protocol.dart | 19 +++-- lib/src/model/supported_versions.dart | 8 +- lib/src/model/sync_update.dart | 61 ++++++++------- lib/src/model/tag.dart | 5 +- lib/src/model/third_party_identifier.dart | 13 ++-- lib/src/model/third_party_location.dart | 9 +-- lib/src/model/third_party_user.dart | 9 +-- lib/src/model/timeline_history_response.dart | 23 +++--- lib/src/model/turn_server_credentials.dart | 11 ++- .../model/upload_key_signatures_response.dart | 25 +++---- lib/src/model/user_search_result.dart | 9 +-- lib/src/model/well_known_information.dart | 29 ++++--- lib/src/model/who_is_info.dart | 13 ++-- 48 files changed, 372 insertions(+), 401 deletions(-) diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 565c2dbd..2d8e0632 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -27,10 +27,9 @@ class AuthenticationData { AuthenticationData({this.type, this.session}); - AuthenticationData.fromJson(Map json) { - type = json['type']; - session = json['session']; - } + AuthenticationData.fromJson(Map json) + : type = json['type'], + session = json['session']; Map toJson() { final data = {}; diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index 5c6bec93..e46613b8 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -26,9 +26,8 @@ class AuthenticationIdentifier { AuthenticationIdentifier({this.type}); - AuthenticationIdentifier.fromJson(Map json) { - type = json['type']; - } + AuthenticationIdentifier.fromJson(Map json) + : type = json['type']; Map toJson() { final data = {}; diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index 6600a4f1..bfc85546 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -45,10 +45,10 @@ class AuthenticationPassword extends AuthenticationData { ); AuthenticationPassword.fromJson(Map json) - : super.fromJson(json) { - user = json['user']; - password = json['password']; - identifier = AuthenticationIdentifier.fromJson(json['identifier']); + : user = json['user'], + password = json['password'], + identifier = AuthenticationIdentifier.fromJson(json['identifier']), + super.fromJson(json) { switch (identifier.type) { case AuthenticationIdentifierTypes.userId: identifier = AuthenticationUserIdentifier.fromJson(json['identifier']); diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index 8ae4d06a..d45a3eab 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -32,10 +32,9 @@ class AuthenticationPhoneIdentifier extends AuthenticationIdentifier { : super(type: AuthenticationIdentifierTypes.phone); AuthenticationPhoneIdentifier.fromJson(Map json) - : super.fromJson(json) { - country = json['country']; - phone = json['phone']; - } + : country = json['country'], + phone = json['phone'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index f37526f9..a98ec159 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -34,9 +34,8 @@ class AuthenticationRecaptcha extends AuthenticationData { ); AuthenticationRecaptcha.fromJson(Map json) - : super.fromJson(json) { - response = json['response']; - } + : response = json['response'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index 742248ff..e8dabf3b 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -32,10 +32,9 @@ class AuthenticationThirdPartyIdentifier extends AuthenticationIdentifier { : super(type: AuthenticationIdentifierTypes.thirdParty); AuthenticationThirdPartyIdentifier.fromJson(Map json) - : super.fromJson(json) { - medium = json['medium']; - address = json['address']; - } + : medium = json['medium'], + address = json['address'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 37e7ba97..41c04d6c 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -72,12 +72,11 @@ class ThreepidCreds { ThreepidCreds( {this.sid, this.clientSecret, this.idServer, this.idAccessToken}); - ThreepidCreds.fromJson(Map json) { - sid = json['sid']; - clientSecret = json['client_secret']; - idServer = json['id_server']; - idAccessToken = json['id_access_token']; - } + ThreepidCreds.fromJson(Map json) + : sid = json['sid'], + clientSecret = json['client_secret'], + idServer = json['id_server'], + idAccessToken = json['id_access_token']; Map toJson() { final data = {}; diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index f182c2dc..d8e96301 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -35,10 +35,9 @@ class AuthenticationToken extends AuthenticationData { ); AuthenticationToken.fromJson(Map json) - : super.fromJson(json) { - token = json['token']; - txnId = json['txn_id']; - } + : token = json['token'], + txnId = json['txn_id'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index 28491a6b..7531bdd8 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -31,9 +31,8 @@ class AuthenticationUserIdentifier extends AuthenticationIdentifier { : super(type: AuthenticationIdentifierTypes.userId); AuthenticationUserIdentifier.fromJson(Map json) - : super.fromJson(json) { - user = json['user']; - } + : user = json['user'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 48ea0c1a..cd708d48 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -32,10 +32,10 @@ class BasicEvent { this.content, }); - BasicEvent.fromJson(Map json) { - type = json['type']; - content = (json['content'] as Map).copy(); - } + BasicEvent.fromJson(Map json) + : type = json['type'], + content = (json['content'] as Map).copy(); + Map toJson() { final data = {}; data['type'] = type; diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index 6c90e8c9..8a99781c 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -29,9 +29,8 @@ class BasicEventWithSender extends BasicEvent { BasicEventWithSender(); BasicEventWithSender.fromJson(Map json) - : super.fromJson(json) { - senderId = json['sender']; - } + : senderId = json['sender'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index 27f28e8f..3a3dbb86 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -35,9 +35,9 @@ class BasicRoomEvent extends BasicEvent { type: type, ); - BasicRoomEvent.fromJson(Map json) : super.fromJson(json) { - roomId = json['room_id']; - } + BasicRoomEvent.fromJson(Map json) + : roomId = json['room_id'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/device.dart b/lib/src/model/device.dart index 01b027b2..825c828d 100644 --- a/lib/src/model/device.dart +++ b/lib/src/model/device.dart @@ -27,12 +27,12 @@ class Device { String lastSeenIp; DateTime lastSeenTs; - Device.fromJson(Map json) { - deviceId = json['device_id']; - displayName = json['display_name']; - lastSeenIp = json['last_seen_ip']; - lastSeenTs = DateTime.fromMillisecondsSinceEpoch(json['last_seen_ts'] ?? 0); - } + Device.fromJson(Map json) + : deviceId = json['device_id'], + displayName = json['display_name'], + lastSeenIp = json['last_seen_ip'], + lastSeenTs = + DateTime.fromMillisecondsSinceEpoch(json['last_seen_ts'] ?? 0); Map toJson() { final data = {}; diff --git a/lib/src/model/event_context.dart b/lib/src/model/event_context.dart index aeee869e..90620915 100644 --- a/lib/src/model/event_context.dart +++ b/lib/src/model/event_context.dart @@ -31,25 +31,26 @@ class EventContext { String start; List state; - EventContext.fromJson(Map json) { - end = json['end']; - if (json['events_after'] != null) { - eventsAfter = (json['events_after'] as List) - .map((v) => MatrixEvent.fromJson(v)) - .toList(); - } - event = json['event'] != null ? MatrixEvent.fromJson(json['event']) : null; - if (json['events_before'] != null) { - eventsBefore = (json['events_before'] as List) - .map((v) => MatrixEvent.fromJson(v)) - .toList(); - } - start = json['start']; - if (json['state'] != null) { - state = - (json['state'] as List).map((v) => MatrixEvent.fromJson(v)).toList(); - } - } + EventContext.fromJson(Map json) + : end = json['end'], + eventsAfter = (json['events_after'] != null) + ? (json['events_after'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList() + : null, + event = + json['event'] != null ? MatrixEvent.fromJson(json['event']) : null, + eventsBefore = (json['events_before'] != null) + ? (json['events_before'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList() + : null, + start = json['start'], + state = (json['state'] != null) + ? (json['state'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList() + : null; Map toJson() { final data = {}; diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart index 6ea08df5..1e53d9ee 100644 --- a/lib/src/model/events_sync_update.dart +++ b/lib/src/model/events_sync_update.dart @@ -28,13 +28,14 @@ class EventsSyncUpdate { String end; List chunk; - EventsSyncUpdate.fromJson(Map json) { - start = json['start']; - end = json['end']; - chunk = json['chunk'] != null - ? (json['chunk'] as List).map((i) => MatrixEvent.fromJson(i)).toList() - : null; - } + EventsSyncUpdate.fromJson(Map json) + : start = json['start'], + end = json['end'], + chunk = json['chunk'] != null + ? (json['chunk'] as List) + .map((i) => MatrixEvent.fromJson(i)) + .toList() + : null; Map toJson() { final data = {}; diff --git a/lib/src/model/filter.dart b/lib/src/model/filter.dart index 391537cf..68146542 100644 --- a/lib/src/model/filter.dart +++ b/lib/src/model/filter.dart @@ -38,22 +38,21 @@ class Filter { this.eventFields, }); - Filter.fromJson(Map json) { - room = json['room'] != null ? RoomFilter.fromJson(json['room']) : null; - presence = json['presence'] != null - ? EventFilter.fromJson(json['presence']) - : null; - accountData = json['account_data'] != null - ? EventFilter.fromJson(json['account_data']) - : null; - eventFormat = json['event_format'] != null - ? EventFormat.values.firstWhere( - (e) => e.toString().split('.').last == json['event_format']) - : null; - eventFields = json['event_fields'] != null - ? json['event_fields'].cast() - : null; - } + Filter.fromJson(Map json) + : room = json['room'] != null ? RoomFilter.fromJson(json['room']) : null, + presence = json['presence'] != null + ? EventFilter.fromJson(json['presence']) + : null, + accountData = json['account_data'] != null + ? EventFilter.fromJson(json['account_data']) + : null, + eventFormat = json['event_format'] != null + ? EventFormat.values.firstWhere( + (e) => e.toString().split('.').last == json['event_format']) + : null, + eventFields = json['event_fields'] != null + ? json['event_fields'].cast() + : null; Map toJson() { final data = {}; diff --git a/lib/src/model/keys_query_response.dart b/lib/src/model/keys_query_response.dart index c705ab1b..ccbc80ff 100644 --- a/lib/src/model/keys_query_response.dart +++ b/lib/src/model/keys_query_response.dart @@ -31,48 +31,45 @@ class KeysQueryResponse { Map selfSigningKeys; Map userSigningKeys; - KeysQueryResponse.fromJson(Map json) { - failures = (json['failures'] as Map)?.copy(); - deviceKeys = json['device_keys'] != null - ? (json['device_keys'] as Map).map( - (k, v) => MapEntry( - k, - (v as Map).map( + KeysQueryResponse.fromJson(Map json) + : failures = (json['failures'] as Map)?.copy(), + deviceKeys = json['device_keys'] != null + ? (json['device_keys'] as Map).map( (k, v) => MapEntry( k, - MatrixDeviceKeys.fromJson(v), + (v as Map).map( + (k, v) => MapEntry( + k, + MatrixDeviceKeys.fromJson(v), + ), + ), ), - ), - ), - ) - : null; - masterKeys = json['master_keys'] != null - ? (json['master_keys'] as Map).map( - (k, v) => MapEntry( - k, - MatrixCrossSigningKey.fromJson(v), - ), - ) - : null; - - selfSigningKeys = json['self_signing_keys'] != null - ? (json['self_signing_keys'] as Map).map( - (k, v) => MapEntry( - k, - MatrixCrossSigningKey.fromJson(v), - ), - ) - : null; - - userSigningKeys = json['user_signing_keys'] != null - ? (json['user_signing_keys'] as Map).map( - (k, v) => MapEntry( - k, - MatrixCrossSigningKey.fromJson(v), - ), - ) - : null; - } + ) + : null, + masterKeys = json['master_keys'] != null + ? (json['master_keys'] as Map).map( + (k, v) => MapEntry( + k, + MatrixCrossSigningKey.fromJson(v), + ), + ) + : null, + selfSigningKeys = json['self_signing_keys'] != null + ? (json['self_signing_keys'] as Map).map( + (k, v) => MapEntry( + k, + MatrixCrossSigningKey.fromJson(v), + ), + ) + : null, + userSigningKeys = json['user_signing_keys'] != null + ? (json['user_signing_keys'] as Map).map( + (k, v) => MapEntry( + k, + MatrixCrossSigningKey.fromJson(v), + ), + ) + : null; Map toJson() { final data = {}; diff --git a/lib/src/model/login_response.dart b/lib/src/model/login_response.dart index d64b1cd2..625739e7 100644 --- a/lib/src/model/login_response.dart +++ b/lib/src/model/login_response.dart @@ -29,14 +29,13 @@ class LoginResponse { String deviceId; WellKnownInformation wellKnownInformation; - LoginResponse.fromJson(Map json) { - userId = json['user_id']; - accessToken = json['access_token']; - deviceId = json['device_id']; - if (json['well_known'] is Map) { - wellKnownInformation = WellKnownInformation.fromJson(json['well_known']); - } - } + LoginResponse.fromJson(Map json) + : userId = json['user_id'], + accessToken = json['access_token'], + deviceId = json['device_id'], + wellKnownInformation = (json['well_known'] is Map) + ? WellKnownInformation.fromJson(json['well_known']) + : null; Map toJson() { final data = {}; diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index 705f2f04..c45e2615 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -34,15 +34,15 @@ class MatrixEvent extends StrippedStateEvent { MatrixEvent(); - MatrixEvent.fromJson(Map json) : super.fromJson(json) { - eventId = json['event_id']; - roomId = json['room_id']; - originServerTs = - DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']); - unsigned = (json['unsigned'] as Map)?.copy(); - prevContent = (json['prev_content'] as Map)?.copy(); - redacts = json['redacts']; - } + MatrixEvent.fromJson(Map json) + : eventId = json['event_id'], + roomId = json['room_id'], + originServerTs = + DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']), + unsigned = (json['unsigned'] as Map)?.copy(), + prevContent = (json['prev_content'] as Map)?.copy(), + redacts = json['redacts'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index 81819f78..44ebbc8e 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -36,17 +36,16 @@ class MatrixSignableKey { // This object is used for signing so we need the raw json too Map _json; - MatrixSignableKey.fromJson(Map json) { - _json = json; - userId = json['user_id']; - keys = Map.from(json['keys']); - // we need to manually copy to ensure that our map is Map> - signatures = json['signatures'] is Map - ? Map>.from((json['signatures'] as Map) - .map((k, v) => MapEntry(k, Map.from(v)))) - : null; - unsigned = (json['unsigned'] as Map)?.copy(); - } + MatrixSignableKey.fromJson(Map json) + : _json = json, + userId = json['user_id'], + keys = Map.from(json['keys']), + // we need to manually copy to ensure that our map is Map> + signatures = json['signatures'] is Map + ? Map>.from((json['signatures'] as Map) + .map((k, v) => MapEntry(k, Map.from(v)))) + : null, + unsigned = (json['unsigned'] as Map)?.copy(); Map toJson() { final data = _json ?? {}; diff --git a/lib/src/model/notifications_query_response.dart b/lib/src/model/notifications_query_response.dart index aaeadbda..83e0d767 100644 --- a/lib/src/model/notifications_query_response.dart +++ b/lib/src/model/notifications_query_response.dart @@ -27,12 +27,11 @@ class NotificationsQueryResponse { String nextToken; List notifications; - NotificationsQueryResponse.fromJson(Map json) { - nextToken = json['next_token']; - notifications = (json['notifications'] as List) - .map((v) => Notification.fromJson(v)) - .toList(); - } + NotificationsQueryResponse.fromJson(Map json) + : nextToken = json['next_token'], + notifications = (json['notifications'] as List) + .map((v) => Notification.fromJson(v)) + .toList(); Map toJson() { final data = {}; diff --git a/lib/src/model/one_time_keys_claim_response.dart b/lib/src/model/one_time_keys_claim_response.dart index b3bab36d..525d2c9c 100644 --- a/lib/src/model/one_time_keys_claim_response.dart +++ b/lib/src/model/one_time_keys_claim_response.dart @@ -27,12 +27,11 @@ class OneTimeKeysClaimResponse { Map failures; Map> oneTimeKeys; - OneTimeKeysClaimResponse.fromJson(Map json) { - failures = (json['failures'] as Map)?.copy() ?? {}; - // We still need a Map<...>.from(...) to ensure all second-level entries are also maps - oneTimeKeys = Map>.from( - (json['one_time_keys'] as Map).copy()); - } + OneTimeKeysClaimResponse.fromJson(Map json) + : failures = (json['failures'] as Map)?.copy() ?? {}, + // We still need a Map<...>.from(...) to ensure all second-level entries are also maps + oneTimeKeys = Map>.from( + (json['one_time_keys'] as Map).copy()); Map toJson() { final data = {}; diff --git a/lib/src/model/open_graph_data.dart b/lib/src/model/open_graph_data.dart index 7ba8f5aa..48a8b1f4 100644 --- a/lib/src/model/open_graph_data.dart +++ b/lib/src/model/open_graph_data.dart @@ -30,15 +30,14 @@ class OpenGraphData { int ogImageWidth; int matrixImageSize; - OpenGraphData.fromJson(Map json) { - ogTitle = json['og:title']; - ogDescription = json['og:description']; - ogImage = json['og:image']; - ogImageType = json['og:image:type']; - ogImageHeight = json['og:image:height']; - ogImageWidth = json['og:image:width']; - matrixImageSize = json['matrix:image:size']; - } + OpenGraphData.fromJson(Map json) + : ogTitle = json['og:title'], + ogDescription = json['og:description'], + ogImage = json['og:image'], + ogImageType = json['og:image:type'], + ogImageHeight = json['og:image:height'], + ogImageWidth = json['og:image:width'], + matrixImageSize = json['matrix:image:size']; Map toJson() { final data = {}; diff --git a/lib/src/model/open_id_credentials.dart b/lib/src/model/open_id_credentials.dart index 4ead2f91..e398ffa3 100644 --- a/lib/src/model/open_id_credentials.dart +++ b/lib/src/model/open_id_credentials.dart @@ -27,12 +27,11 @@ class OpenIdCredentials { String matrixServerName; double expiresIn; - OpenIdCredentials.fromJson(Map json) { - accessToken = json['access_token']; - tokenType = json['token_type']; - matrixServerName = json['matrix_server_name']; - expiresIn = json['expires_in']; - } + OpenIdCredentials.fromJson(Map json) + : accessToken = json['access_token'], + tokenType = json['token_type'], + matrixServerName = json['matrix_server_name'], + expiresIn = json['expires_in']; Map toJson() { final data = {}; diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index 7d9fb753..73848c2e 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -27,7 +27,7 @@ import 'presence_content.dart'; class Presence extends BasicEventWithSender { PresenceContent presence; - Presence.fromJson(Map json) : super.fromJson(json) { - presence = PresenceContent.fromJson(content); - } + Presence.fromJson(Map json) + : presence = PresenceContent.fromJson(json['content']), + super.fromJson(json); } diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index 99d926cf..597082f3 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -29,13 +29,12 @@ class PresenceContent { String statusMsg; bool currentlyActive; - PresenceContent.fromJson(Map json) { - presence = PresenceType.values - .firstWhere((p) => p.toString().split('.').last == json['presence']); - lastActiveAgo = json['last_active_ago']; - statusMsg = json['status_msg']; - currentlyActive = json['currently_active']; - } + PresenceContent.fromJson(Map json) + : presence = PresenceType.values.firstWhere( + (p) => p.toString().split('.').last == json['presence']), + lastActiveAgo = json['last_active_ago'], + statusMsg = json['status_msg'], + currentlyActive = json['currently_active']; Map toJson() { final data = {}; diff --git a/lib/src/model/public_rooms_response.dart b/lib/src/model/public_rooms_response.dart index 34ae0bf7..7fdfabdd 100644 --- a/lib/src/model/public_rooms_response.dart +++ b/lib/src/model/public_rooms_response.dart @@ -27,12 +27,12 @@ class PublicRoomsResponse { String prevBatch; int totalRoomCountEstimate; - PublicRoomsResponse.fromJson(Map json) { - chunk = (json['chunk'] as List).map((v) => PublicRoom.fromJson(v)).toList(); - nextBatch = json['next_batch']; - prevBatch = json['prev_batch']; - totalRoomCountEstimate = json['total_room_count_estimate']; - } + PublicRoomsResponse.fromJson(Map json) + : chunk = + (json['chunk'] as List).map((v) => PublicRoom.fromJson(v)).toList(), + nextBatch = json['next_batch'], + prevBatch = json['prev_batch'], + totalRoomCountEstimate = json['total_room_count_estimate']; Map toJson() { final data = {}; @@ -61,17 +61,16 @@ class PublicRoom { bool worldReadable; String canonicalAlias; - PublicRoom.fromJson(Map json) { - aliases = json['aliases']?.cast(); - avatarUrl = json['avatar_url']; - guestCanJoin = json['guest_can_join']; - canonicalAlias = json['canonical_alias']; - name = json['name']; - numJoinedMembers = json['num_joined_members']; - roomId = json['room_id']; - topic = json['topic']; - worldReadable = json['world_readable']; - } + PublicRoom.fromJson(Map json) + : aliases = json['aliases']?.cast(), + avatarUrl = json['avatar_url'], + guestCanJoin = json['guest_can_join'], + canonicalAlias = json['canonical_alias'], + name = json['name'], + numJoinedMembers = json['num_joined_members'], + roomId = json['room_id'], + topic = json['topic'], + worldReadable = json['world_readable']; Map toJson() { final data = {}; diff --git a/lib/src/model/pusher.dart b/lib/src/model/pusher.dart index 4068e2c9..08d36577 100644 --- a/lib/src/model/pusher.dart +++ b/lib/src/model/pusher.dart @@ -42,16 +42,15 @@ class Pusher { this.kind, }); - Pusher.fromJson(Map json) { - pushkey = json['pushkey']; - kind = json['kind']; - appId = json['app_id']; - appDisplayName = json['app_display_name']; - deviceDisplayName = json['device_display_name']; - profileTag = json['profile_tag']; - lang = json['lang']; - data = PusherData.fromJson(json['data']); - } + Pusher.fromJson(Map json) + : pushkey = json['pushkey'], + kind = json['kind'], + appId = json['app_id'], + appDisplayName = json['app_display_name'], + deviceDisplayName = json['device_display_name'], + profileTag = json['profile_tag'], + lang = json['lang'], + data = PusherData.fromJson(json['data']); Map toJson() { final data = {}; @@ -78,12 +77,9 @@ class PusherData { this.format, }); - PusherData.fromJson(Map json) { - if (json.containsKey('url')) { - url = Uri.parse(json['url']); - } - format = json['format']; - } + PusherData.fromJson(Map json) + : format = json['format'], + url = json.containsKey('url') ? Uri.parse(json['url']) : null; Map toJson() { final data = {}; diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart index e7b41c7c..e2001826 100644 --- a/lib/src/model/request_token_response.dart +++ b/lib/src/model/request_token_response.dart @@ -25,10 +25,9 @@ class RequestTokenResponse { String sid; String submitUrl; - RequestTokenResponse.fromJson(Map json) { - sid = json['sid']; - submitUrl = json['submit_url']; - } + RequestTokenResponse.fromJson(Map json) + : sid = json['sid'], + submitUrl = json['submit_url']; Map toJson() { final data = {}; diff --git a/lib/src/model/room_alias_information.dart b/lib/src/model/room_alias_information.dart index ae675991..050b6b2c 100644 --- a/lib/src/model/room_alias_information.dart +++ b/lib/src/model/room_alias_information.dart @@ -25,10 +25,9 @@ class RoomAliasInformation { String roomId; List servers; - RoomAliasInformation.fromJson(Map json) { - roomId = json['room_id']; - servers = json['servers'].cast(); - } + RoomAliasInformation.fromJson(Map json) + : roomId = json['room_id'], + servers = json['servers'].cast(); Map toJson() { final data = {}; diff --git a/lib/src/model/room_keys_info.dart b/lib/src/model/room_keys_info.dart index 9deaea3d..c300b298 100644 --- a/lib/src/model/room_keys_info.dart +++ b/lib/src/model/room_keys_info.dart @@ -52,15 +52,14 @@ class RoomKeysVersionResponse { String etag; String version; - RoomKeysVersionResponse.fromJson(Map json) { - algorithm = - RoomKeysAlgorithmTypeExtension.fromAlgorithmString(json['algorithm']); - authData = json['auth_data']; - count = json['count']; - etag = - json['etag'].toString(); // synapse replies an int but docs say string? - version = json['version']; - } + RoomKeysVersionResponse.fromJson(Map json) + : algorithm = RoomKeysAlgorithmTypeExtension.fromAlgorithmString( + json['algorithm']), + authData = json['auth_data'], + count = json['count'], + etag = json['etag'] + .toString(), // synapse replies an int but docs say string? + version = json['version']; Map toJson() { final data = {}; diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart index fb8c20fc..54c2f102 100644 --- a/lib/src/model/room_keys_keys.dart +++ b/lib/src/model/room_keys_keys.dart @@ -33,12 +33,11 @@ class RoomKeysSingleKey { this.isVerified, this.sessionData}); - RoomKeysSingleKey.fromJson(Map json) { - firstMessageIndex = json['first_message_index']; - forwardedCount = json['forwarded_count']; - isVerified = json['is_verified']; - sessionData = json['session_data']; - } + RoomKeysSingleKey.fromJson(Map json) + : firstMessageIndex = json['first_message_index'], + forwardedCount = json['forwarded_count'], + isVerified = json['is_verified'], + sessionData = json['session_data']; Map toJson() { final data = {}; @@ -57,10 +56,9 @@ class RoomKeysRoom { sessions ??= {}; } - RoomKeysRoom.fromJson(Map json) { - sessions = (json['sessions'] as Map) - .map((k, v) => MapEntry(k, RoomKeysSingleKey.fromJson(v))); - } + RoomKeysRoom.fromJson(Map json) + : sessions = (json['sessions'] as Map) + .map((k, v) => MapEntry(k, RoomKeysSingleKey.fromJson(v))); Map toJson() { final data = {}; @@ -76,10 +74,9 @@ class RoomKeys { rooms ??= {}; } - RoomKeys.fromJson(Map json) { - rooms = (json['rooms'] as Map) - .map((k, v) => MapEntry(k, RoomKeysRoom.fromJson(v))); - } + RoomKeys.fromJson(Map json) + : rooms = (json['rooms'] as Map) + .map((k, v) => MapEntry(k, RoomKeysRoom.fromJson(v))); Map toJson() { final data = {}; @@ -92,10 +89,9 @@ class RoomKeysUpdateResponse { String etag; int count; - RoomKeysUpdateResponse.fromJson(Map json) { - etag = json['etag']; // synapse replies an int but docs say string? - count = json['count']; - } + RoomKeysUpdateResponse.fromJson(Map json) + : etag = json['etag'], // synapse replies an int but docs say string? + count = json['count']; Map toJson() { final data = {}; diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index 78d505ee..664cd229 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -25,12 +25,13 @@ class RoomSummary { List mHeroes; int mJoinedMemberCount; int mInvitedMemberCount; - RoomSummary.fromJson(Map json) { - mHeroes = - json['m.heroes'] != null ? List.from(json['m.heroes']) : null; - mJoinedMemberCount = json['m.joined_member_count']; - mInvitedMemberCount = json['m.invited_member_count']; - } + RoomSummary.fromJson(Map json) + : mHeroes = json['m.heroes'] != null + ? List.from(json['m.heroes']) + : null, + mJoinedMemberCount = json['m.joined_member_count'], + mInvitedMemberCount = json['m.invited_member_count']; + Map toJson() { final data = {}; if (mHeroes != null) { diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart index 0e11e1f9..b7053f84 100644 --- a/lib/src/model/server_capabilities.dart +++ b/lib/src/model/server_capabilities.dart @@ -30,17 +30,16 @@ class ServerCapabilities { MRoomVersions mRoomVersions; Map customCapabilities; - ServerCapabilities.fromJson(Map json) { - mChangePassword = json['m.change_password'] != null - ? MChangePassword.fromJson(json['m.change_password']) - : null; - mRoomVersions = json['m.room_versions'] != null - ? MRoomVersions.fromJson(json['m.room_versions']) - : null; - customCapabilities = json.copy() - ..remove('m.change_password') - ..remove('m.room_versions'); - } + ServerCapabilities.fromJson(Map json) + : mChangePassword = json['m.change_password'] != null + ? MChangePassword.fromJson(json['m.change_password']) + : null, + mRoomVersions = json['m.room_versions'] != null + ? MRoomVersions.fromJson(json['m.room_versions']) + : null, + customCapabilities = json.copy() + ..remove('m.change_password') + ..remove('m.room_versions'); Map toJson() { final data = {}; diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index e6d1edd5..bb8ad374 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -28,9 +28,8 @@ class StrippedStateEvent extends BasicEventWithSender { StrippedStateEvent(); StrippedStateEvent.fromJson(Map json) - : super.fromJson(json) { - stateKey = json['state_key']; - } + : stateKey = json['state_key'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart index a81c6bd8..b9e4ad35 100644 --- a/lib/src/model/supported_protocol.dart +++ b/lib/src/model/supported_protocol.dart @@ -28,16 +28,15 @@ class SupportedProtocol { Map fieldTypes; List instances; - SupportedProtocol.fromJson(Map json) { - userFields = json['user_fields'].cast(); - locationFields = json['location_fields'].cast(); - icon = json['icon']; - fieldTypes = (json['field_types'] as Map) - .map((k, v) => MapEntry(k, ProtocolFieldType.fromJson(v))); - instances = (json['instances'] as List) - .map((v) => ProtocolInstance.fromJson(v)) - .toList(); - } + SupportedProtocol.fromJson(Map json) + : userFields = json['user_fields'].cast(), + locationFields = json['location_fields'].cast(), + icon = json['icon'], + fieldTypes = (json['field_types'] as Map) + .map((k, v) => MapEntry(k, ProtocolFieldType.fromJson(v))), + instances = (json['instances'] as List) + .map((v) => ProtocolInstance.fromJson(v)) + .toList(); Map toJson() { final data = {}; diff --git a/lib/src/model/supported_versions.dart b/lib/src/model/supported_versions.dart index 92b5160f..42b8bc6b 100644 --- a/lib/src/model/supported_versions.dart +++ b/lib/src/model/supported_versions.dart @@ -25,10 +25,10 @@ class SupportedVersions { List versions; Map unstableFeatures; - SupportedVersions.fromJson(Map json) { - versions = json['versions'].cast(); - unstableFeatures = Map.from(json['unstable_features'] ?? {}); - } + SupportedVersions.fromJson(Map json) + : versions = json['versions'].cast(), + unstableFeatures = + Map.from(json['unstable_features'] ?? {}); Map toJson() { final data = {}; diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index 741b3405..a847eed5 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -41,39 +41,42 @@ class SyncUpdate { SyncUpdate(); - SyncUpdate.fromJson(Map json) { - nextBatch = json['next_batch']; - rooms = json['rooms'] != null ? RoomsUpdate.fromJson(json['rooms']) : null; - presence = (json['presence'] != null && json['presence']['events'] != null) - ? (json['presence']['events'] as List) - .map((i) => Presence.fromJson(i)) - .toList() - : null; - accountData = - (json['account_data'] != null && json['account_data']['events'] != null) + SyncUpdate.fromJson(Map json) + : nextBatch = json['next_batch'], + rooms = + json['rooms'] != null ? RoomsUpdate.fromJson(json['rooms']) : null, + presence = + (json['presence'] != null && json['presence']['events'] != null) + ? (json['presence']['events'] as List) + .map((i) => Presence.fromJson(i)) + .toList() + : null, + accountData = (json['account_data'] != null && + json['account_data']['events'] != null) ? (json['account_data']['events'] as List) .map((i) => BasicEvent.fromJson(i)) .toList() + : null, + toDevice = + (json['to_device'] != null && json['to_device']['events'] != null) + ? (json['to_device']['events'] as List) + .map((i) => BasicEventWithSender.fromJson(i)) + .toList() + : null, + deviceLists = json['device_lists'] != null + ? DeviceListsUpdate.fromJson(json['device_lists']) + : null, + deviceOneTimeKeysCount = json['device_one_time_keys_count'] != null + ? Map.from(json['device_one_time_keys_count']) + : null, + deviceUnusedFallbackKeyTypes = (json[ + 'device_unused_fallback_key_types'] ?? + json[ + 'org.matrix.msc2732.device_unused_fallback_key_types']) != + null + ? List.from(json['device_unused_fallback_key_types'] ?? + json['org.matrix.msc2732.device_unused_fallback_key_types']) : null; - toDevice = - (json['to_device'] != null && json['to_device']['events'] != null) - ? (json['to_device']['events'] as List) - .map((i) => BasicEventWithSender.fromJson(i)) - .toList() - : null; - deviceLists = json['device_lists'] != null - ? DeviceListsUpdate.fromJson(json['device_lists']) - : null; - deviceOneTimeKeysCount = json['device_one_time_keys_count'] != null - ? Map.from(json['device_one_time_keys_count']) - : null; - deviceUnusedFallbackKeyTypes = (json['device_unused_fallback_key_types'] ?? - json['org.matrix.msc2732.device_unused_fallback_key_types']) != - null - ? List.from(json['device_unused_fallback_key_types'] ?? - json['org.matrix.msc2732.device_unused_fallback_key_types']) - : null; - } Map toJson() { final data = {}; diff --git a/lib/src/model/tag.dart b/lib/src/model/tag.dart index 5b3968a1..3329b551 100644 --- a/lib/src/model/tag.dart +++ b/lib/src/model/tag.dart @@ -24,9 +24,8 @@ class Tag { double order; - Tag.fromJson(Map json) { - order = double.tryParse(json['order'].toString()); - } + Tag.fromJson(Map json) + : order = double.tryParse(json['order'].toString()); Map toJson() { final data = {}; diff --git a/lib/src/model/third_party_identifier.dart b/lib/src/model/third_party_identifier.dart index 7ca0c2ad..b6ab7b90 100644 --- a/lib/src/model/third_party_identifier.dart +++ b/lib/src/model/third_party_identifier.dart @@ -29,13 +29,12 @@ class ThirdPartyIdentifier { int validatedAt; int addedAt; - ThirdPartyIdentifier.fromJson(Map json) { - medium = ThirdPartyIdentifierMedium.values - .firstWhere((medium) => describeEnum(medium) == json['medium']); - address = json['address']; - validatedAt = json['validated_at']; - addedAt = json['added_at']; - } + ThirdPartyIdentifier.fromJson(Map json) + : medium = ThirdPartyIdentifierMedium.values + .firstWhere((medium) => describeEnum(medium) == json['medium']), + address = json['address'], + validatedAt = json['validated_at'], + addedAt = json['added_at']; Map toJson() { final data = {}; diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index 0206a283..a2271f9b 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -28,11 +28,10 @@ class ThirdPartyLocation { String protocol; Map fields; - ThirdPartyLocation.fromJson(Map json) { - alias = json['alias']; - protocol = json['protocol']; - fields = (json['fields'] as Map).copy(); - } + ThirdPartyLocation.fromJson(Map json) + : alias = json['alias'], + protocol = json['protocol'], + fields = (json['fields'] as Map).copy(); Map toJson() { final data = {}; diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index 40a67893..a4289b2a 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -28,11 +28,10 @@ class ThirdPartyUser { String protocol; Map fields; - ThirdPartyUser.fromJson(Map json) { - userId = json['userid']; - protocol = json['protocol']; - fields = (json['fields'] as Map).copy(); - } + ThirdPartyUser.fromJson(Map json) + : userId = json['userid'], + protocol = json['protocol'], + fields = (json['fields'] as Map).copy(); Map toJson() { final data = {}; diff --git a/lib/src/model/timeline_history_response.dart b/lib/src/model/timeline_history_response.dart index 84a68fb2..e9806b89 100644 --- a/lib/src/model/timeline_history_response.dart +++ b/lib/src/model/timeline_history_response.dart @@ -29,16 +29,19 @@ class TimelineHistoryResponse { List chunk; List state; - TimelineHistoryResponse.fromJson(Map json) { - start = json['start']; - end = json['end']; - chunk = json['chunk'] != null - ? (json['chunk'] as List).map((i) => MatrixEvent.fromJson(i)).toList() - : null; - state = json['state'] != null - ? (json['state'] as List).map((i) => MatrixEvent.fromJson(i)).toList() - : null; - } + TimelineHistoryResponse.fromJson(Map json) + : start = json['start'], + end = json['end'], + chunk = json['chunk'] != null + ? (json['chunk'] as List) + .map((i) => MatrixEvent.fromJson(i)) + .toList() + : null, + state = json['state'] != null + ? (json['state'] as List) + .map((i) => MatrixEvent.fromJson(i)) + .toList() + : null; Map toJson() { final data = {}; diff --git a/lib/src/model/turn_server_credentials.dart b/lib/src/model/turn_server_credentials.dart index 67fca47a..81b36c9e 100644 --- a/lib/src/model/turn_server_credentials.dart +++ b/lib/src/model/turn_server_credentials.dart @@ -27,12 +27,11 @@ class TurnServerCredentials { List uris; num ttl; - TurnServerCredentials.fromJson(Map json) { - username = json['username']; - password = json['password']; - uris = json['uris'].cast(); - ttl = json['ttl']; - } + TurnServerCredentials.fromJson(Map json) + : username = json['username'], + password = json['password'], + uris = json['uris'].cast(), + ttl = json['ttl']; Map toJson() { final data = {}; diff --git a/lib/src/model/upload_key_signatures_response.dart b/lib/src/model/upload_key_signatures_response.dart index cf845766..b53e01a2 100644 --- a/lib/src/model/upload_key_signatures_response.dart +++ b/lib/src/model/upload_key_signatures_response.dart @@ -26,19 +26,18 @@ import 'matrix_exception.dart'; class UploadKeySignaturesResponse { Map> failures; - UploadKeySignaturesResponse.fromJson(Map json) { - failures = json['failures'] != null - ? (json['failures'] as Map).map( - (k, v) => MapEntry( - k, - (v as Map).map((k, v) => MapEntry( - k, - MatrixException.fromJson(v), - )), - ), - ) - : null; - } + UploadKeySignaturesResponse.fromJson(Map json) + : failures = json['failures'] != null + ? (json['failures'] as Map).map( + (k, v) => MapEntry( + k, + (v as Map).map((k, v) => MapEntry( + k, + MatrixException.fromJson(v), + )), + ), + ) + : null; Map toJson() { final data = {}; diff --git a/lib/src/model/user_search_result.dart b/lib/src/model/user_search_result.dart index 27c84d7c..8da4b82a 100644 --- a/lib/src/model/user_search_result.dart +++ b/lib/src/model/user_search_result.dart @@ -27,11 +27,10 @@ class UserSearchResult { List results; bool limited; - UserSearchResult.fromJson(Map json) { - results = - (json['results'] as List).map((v) => Profile.fromJson(v)).toList(); - limited = json['limited']; - } + UserSearchResult.fromJson(Map json) + : results = + (json['results'] as List).map((v) => Profile.fromJson(v)).toList(), + limited = json['limited']; Map toJson() { final data = {}; diff --git a/lib/src/model/well_known_information.dart b/lib/src/model/well_known_information.dart index 631ef698..dbeb1a84 100644 --- a/lib/src/model/well_known_information.dart +++ b/lib/src/model/well_known_information.dart @@ -28,18 +28,23 @@ class WellKnownInformation { MHomeserver mIdentityServer; Map content; - WellKnownInformation.fromJson(Map json) { - content = json; - final mHomeserverMap = json.tryGetMap('m.homeserver'); - if (mHomeserverMap != null) { - mHomeserver = MHomeserver.fromJson(mHomeserverMap); - } - final mIdentityServerMap = - json.tryGetMap('m.identity_server'); - if (mIdentityServerMap != null) { - mIdentityServer = MHomeserver.fromJson(mIdentityServerMap); - } - } + factory WellKnownInformation.fromJson(Map json) => + WellKnownInformation._fromJson( + json, + json.tryGetMap('m.homeserver'), + json.tryGetMap('m.identity_server')); + + WellKnownInformation._fromJson( + Map json, + Map mHomeserverMap, + Map mIdentityServerMap) + : content = json, + mHomeserver = mHomeserverMap != null + ? MHomeserver.fromJson(mHomeserverMap) + : null, + mIdentityServer = mIdentityServerMap != null + ? MHomeserver.fromJson(mIdentityServerMap) + : null; Map toJson() { final data = content; diff --git a/lib/src/model/who_is_info.dart b/lib/src/model/who_is_info.dart index 5504a24d..3d47930c 100644 --- a/lib/src/model/who_is_info.dart +++ b/lib/src/model/who_is_info.dart @@ -25,13 +25,12 @@ class WhoIsInfo { String userId; Map devices; - WhoIsInfo.fromJson(Map json) { - userId = json['user_id']; - devices = json['devices'] != null - ? (json['devices'] as Map) - .map((k, v) => MapEntry(k, DeviceInfo.fromJson(v))) - : null; - } + WhoIsInfo.fromJson(Map json) + : userId = json['user_id'], + devices = json['devices'] != null + ? (json['devices'] as Map) + .map((k, v) => MapEntry(k, DeviceInfo.fromJson(v))) + : null; Map toJson() { final data = {}; From 4069f0a02f5461bc7ae0ba7cdb2f5eda224173cb Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Wed, 5 May 2021 12:05:26 +0200 Subject: [PATCH 052/174] refactor: avoid string conversion for comparison --- lib/src/matrix_api.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index d32e3524..4d623a0e 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -163,25 +163,25 @@ class MatrixApi { http.Response resp; var jsonResp = {}; try { - switch (describeEnum(type)) { - case 'GET': + switch (type) { + case RequestType.GET: resp = await httpClient.get(url, headers: headers).timeout( Duration(seconds: timeout), ); break; - case 'POST': + case RequestType.POST: resp = await httpClient.post(url, body: json, headers: headers).timeout( Duration(seconds: timeout), ); break; - case 'PUT': + case RequestType.PUT: resp = await httpClient.put(url, body: json, headers: headers).timeout( Duration(seconds: timeout), ); break; - case 'DELETE': + case RequestType.DELETE: resp = await httpClient.delete(url, headers: headers).timeout( Duration(seconds: timeout), ); From 2fdf3e828479ba23a713a986099f6eaaec634cf5 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Wed, 5 May 2021 12:05:26 +0200 Subject: [PATCH 053/174] refactor: polymorphism can be used without manual switch statement --- .../model/auth/authentication_password.dart | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index bfc85546..77ed95d4 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -68,23 +68,7 @@ class AuthenticationPassword extends AuthenticationData { final data = super.toJson(); if (user != null) data['user'] = user; data['password'] = password; - switch (identifier.type) { - case AuthenticationIdentifierTypes.userId: - data['identifier'] = - (identifier as AuthenticationUserIdentifier).toJson(); - break; - case AuthenticationIdentifierTypes.phone: - data['identifier'] = - (identifier as AuthenticationPhoneIdentifier).toJson(); - break; - case AuthenticationIdentifierTypes.thirdParty: - data['identifier'] = - (identifier as AuthenticationThirdPartyIdentifier).toJson(); - break; - default: - data['identifier'] = identifier.toJson(); - break; - } + data['identifier'] = identifier.toJson(); return data; } } From 846c96e90d38a354730c5b6819dee206573ecd66 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Wed, 5 May 2021 12:08:03 +0200 Subject: [PATCH 054/174] refactor: move identifier type detection into AuthenticationIdentifier --- .../model/auth/authentication_identifier.dart | 18 ++++++++++++++++++ .../model/auth/authentication_password.dart | 19 ++----------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index e46613b8..29242a83 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -21,6 +21,11 @@ * SOFTWARE. */ +import 'authentication_types.dart'; +import 'authentication_user_identifier.dart'; +import 'authentication_phone_identifier.dart'; +import 'authentication_third_party_identifier.dart'; + class AuthenticationIdentifier { String type; @@ -29,6 +34,19 @@ class AuthenticationIdentifier { AuthenticationIdentifier.fromJson(Map json) : type = json['type']; + factory AuthenticationIdentifier.subFromJson(Map json) { + switch (json['type']) { + case AuthenticationIdentifierTypes.userId: + return AuthenticationUserIdentifier.fromJson(json); + case AuthenticationIdentifierTypes.phone: + return AuthenticationPhoneIdentifier.fromJson(json); + case AuthenticationIdentifierTypes.thirdParty: + return AuthenticationThirdPartyIdentifier.fromJson(json); + default: + return AuthenticationIdentifier.fromJson(json); + } + } + Map toJson() { final data = {}; data['type'] = type; diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index 77ed95d4..f727c6c0 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -25,8 +25,6 @@ import 'authentication_user_identifier.dart'; import 'authentication_data.dart'; import 'authentication_identifier.dart'; -import 'authentication_phone_identifier.dart'; -import 'authentication_third_party_identifier.dart'; import 'authentication_types.dart'; class AuthenticationPassword extends AuthenticationData { @@ -47,21 +45,8 @@ class AuthenticationPassword extends AuthenticationData { AuthenticationPassword.fromJson(Map json) : user = json['user'], password = json['password'], - identifier = AuthenticationIdentifier.fromJson(json['identifier']), - super.fromJson(json) { - switch (identifier.type) { - case AuthenticationIdentifierTypes.userId: - identifier = AuthenticationUserIdentifier.fromJson(json['identifier']); - break; - case AuthenticationIdentifierTypes.phone: - identifier = AuthenticationPhoneIdentifier.fromJson(json['identifier']); - break; - case AuthenticationIdentifierTypes.thirdParty: - identifier = - AuthenticationThirdPartyIdentifier.fromJson(json['identifier']); - break; - } - } + identifier = AuthenticationIdentifier.subFromJson(json['identifier']), + super.fromJson(json); @override Map toJson() { From d667f636756706e5dca222a38ba29d6d2ec6e977 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 5 May 2021 12:24:49 +0200 Subject: [PATCH 055/174] refactor: Enable more lints --- analysis_options.yaml | 20 ++++++++++---------- lib/src/matrix_api.dart | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index a686c1b4..7efcbfc1 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,14 +1,14 @@ -# Defines a default set of lint rules enforced for -# projects at Google. For details and rationale, -# see https://github.com/dart-lang/pedantic#enabled-lints. include: package:pedantic/analysis_options.yaml -# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. -# Uncomment to specify additional rules. -# linter: -# rules: -# - camel_case_types +linter: + rules: + - camel_case_types + - avoid_print + - prefer_final_locals + - prefer_final_in_for_each analyzer: -# exclude: -# - path/to/excluded/files/** + errors: + todo: ignore + exclude: + - example/matrix_api_lite_example.dart diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 4d623a0e..07d59273 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -152,7 +152,7 @@ class MatrixApi { final url = homeserver .resolveUri(Uri(path: '_matrix$action', queryParameters: query)); - var headers = {}; + final headers = {}; if (type == RequestType.PUT || type == RequestType.POST) { headers['Content-Type'] = contentType; } @@ -1291,7 +1291,7 @@ class MatrixApi { {String contentType}) async { fileName = fileName.split('/').last; final length = file.length; - var headers = {}; + final headers = {}; headers['Authorization'] = 'Bearer $accessToken'; headers['Content-Type'] = contentType ?? lookupMimeType(fileName, headerBytes: file); @@ -1306,8 +1306,8 @@ class MatrixApi { streamedRequest.contentLength = length; streamedRequest.sink.add(file); streamedRequest.sink.close(); - var streamedResponse = _testMode ? null : await streamedRequest.send(); - Map jsonResponse = json.decode( + final streamedResponse = _testMode ? null : await streamedRequest.send(); + final Map jsonResponse = json.decode( String.fromCharCodes(_testMode ? ((fileName == 'file.jpeg') ? '{"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"}' @@ -1325,7 +1325,7 @@ class MatrixApi { /// URL in a message and wants to render a preview for the user. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-preview-url Future requestOpenGraphDataForUrl(Uri url, {int ts}) async { - var action = homeserver + final action = homeserver .resolveUri(Uri(path: '_matrix/media/r0/preview_url', queryParameters: { 'url': url.toString(), if (ts != null) 'ts': ts.toString(), @@ -1338,7 +1338,7 @@ class MatrixApi { /// This endpoint allows clients to retrieve the configuration of the content repository, such as upload limitations. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-config Future requestMaxUploadSize() async { - var action = homeserver.resolve('_matrix/media/r0/config'); + final action = homeserver.resolve('_matrix/media/r0/config'); final response = await httpClient.get(action); final rawJson = json.decode(response.body.isEmpty ? '{}' : response.body); return rawJson['m.upload.size']; @@ -1553,7 +1553,7 @@ class MatrixApi { /// values in the JSON body. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-pushers-set Future setPusher(Pusher pusher, {bool append}) async { - var data = pusher.toJson(); + final data = pusher.toJson(); if (append != null) { data['append'] = append; } From 3eaf4ef99abce41452c7f3fc5ca8460a2b64fb67 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Fri, 7 May 2021 13:43:06 +0200 Subject: [PATCH 056/174] feat!: operation names from OpenAPI spec --- lib/src/matrix_api.dart | 154 ++++++++++++++++++------------------ test/matrix_api_test.dart | 162 +++++++++++++++++++------------------- 2 files changed, 157 insertions(+), 159 deletions(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 07d59273..9e601ef7 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -219,7 +219,7 @@ class MatrixApi { /// Gets the versions of the specification supported by the server. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-versions - Future requestSupportedVersions() async { + Future getVersions() async { final response = await request( RequestType.GET, '/client/versions', @@ -229,14 +229,14 @@ class MatrixApi { /// Gets discovery information about the domain. The file may include additional keys. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-well-known-matrix-client - Future requestWellKnownInformation() async { + Future getWellknown() async { final response = await httpClient.get(homeserver.resolve('.well-known/matrix/client')); final rawJson = json.decode(response.body); return WellKnownInformation.fromJson(rawJson); } - Future requestLoginTypes() async { + Future getLoginFlows() async { final response = await request( RequestType.GET, '/client/r0/login', @@ -473,7 +473,7 @@ class MatrixApi { ); } - Future usernameAvailable(String username) async { + Future checkUsernameAvailability(String username) async { final response = await request( RequestType.GET, '/client/r0/register/available', @@ -487,7 +487,7 @@ class MatrixApi { /// Gets a list of the third party identifiers that the homeserver has /// associated with the user's account. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-register-available - Future> requestThirdPartyIdentifiers() async { + Future> getAccount3PIDs() async { final response = await request( RequestType.GET, '/client/r0/account/3pid', @@ -501,7 +501,7 @@ class MatrixApi { /// should use 3PIDs added through this endpoint for password resets /// instead of relying on the identity server. /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-add - Future addThirdPartyIdentifier( + Future add3PID( String clientSecret, String sid, { AuthenticationData auth, @@ -516,7 +516,7 @@ class MatrixApi { /// Binds a 3PID to the user's account through the specified identity server. /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-bind - Future bindThirdPartyIdentifier( + Future bind3PID( String clientSecret, String sid, String idServer, @@ -533,7 +533,7 @@ class MatrixApi { /// Removes a third party identifier from the user's account. This might not cause an unbind of the identifier from the identity server. /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-delete - Future deleteThirdPartyIdentifier( + Future delete3pidFromAccount( String address, ThirdPartyIdentifierMedium medium, { String idServer, @@ -552,7 +552,7 @@ class MatrixApi { /// Removes a user's third party identifier from the provided identity server without removing it from the homeserver. /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-unbind - Future unbindThirdPartyIdentifier( + Future unbind3pidFromAccount( String address, ThirdPartyIdentifierMedium medium, String idServer, @@ -619,7 +619,7 @@ class MatrixApi { /// Gets information about the owner of a given access token. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-account-whoami - Future whoAmI() async { + Future getTokenOwner() async { final response = await request( RequestType.GET, '/client/r0/account/whoami', @@ -629,7 +629,7 @@ class MatrixApi { /// Gets information about the server's supported feature set and other relevant capabilities. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-capabilities - Future requestServerCapabilities() async { + Future getCapabilities() async { final response = await request( RequestType.GET, '/client/r0/capabilities', @@ -640,7 +640,7 @@ class MatrixApi { /// Uploads a new filter definition to the homeserver. Returns a filter ID that may be used /// in future requests to restrict which events are returned to the client. /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-filter - Future uploadFilter( + Future defineFilter( String userId, Filter filter, ) async { @@ -654,7 +654,7 @@ class MatrixApi { /// Download a filter /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-filter - Future downloadFilter(String userId, String filterId) async { + Future getFilter(String userId, String filterId) async { final response = await request( RequestType.GET, '/client/r0/user/${Uri.encodeComponent(userId)}/filter/${Uri.encodeComponent(filterId)}', @@ -690,7 +690,7 @@ class MatrixApi { /// Get a single event based on roomId/eventId. You must have permission to /// retrieve this event e.g. by being a member in the room for this event. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-event-eventid - Future requestEvent(String roomId, String eventId) async { + Future getOneRoomEvent(String roomId, String eventId) async { final response = await request( RequestType.GET, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/event/${Uri.encodeComponent(eventId)}', @@ -719,7 +719,7 @@ class MatrixApi { /// Get the state events for the current state of a room. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-state - Future> requestStates(String roomId) async { + Future> getRoomState(String roomId) async { final response = await request( RequestType.GET, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state', @@ -731,7 +731,7 @@ class MatrixApi { /// Get the list of members for this room. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-members - Future> requestMembers( + Future> getMembersByRoom( String roomId, { String at, Membership membership, @@ -754,7 +754,7 @@ class MatrixApi { /// This API returns a map of MXIDs to member info objects for members of the room. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-joined-members - Future> requestJoinedMembers(String roomId) async { + Future> getJoinedMembersByRoom(String roomId) async { final response = await request( RequestType.GET, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/joined_members', @@ -767,7 +767,7 @@ class MatrixApi { /// This API returns a list of message and state events for a room. It uses pagination query /// parameters to paginate history in the room. /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-messages - Future requestMessages( + Future getRoomEvents( String roomId, String from, Direction dir, { @@ -789,7 +789,7 @@ class MatrixApi { /// State events can be sent using this endpoint. /// https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey - Future sendState( + Future setRoomStateWithKey( String roomId, String eventType, Map content, [ @@ -820,7 +820,7 @@ class MatrixApi { /// Strips all information out of an event which isn't critical to the integrity of /// the server-side representation of the room. /// https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid - Future redact( + Future redactEvent( String roomId, String eventId, String txnId, { @@ -869,7 +869,7 @@ class MatrixApi { /// Create a new mapping from room alias to room ID. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-directory-room-roomalias - Future createRoomAlias(String alias, String roomId) async { + Future setRoomAlias(String alias, String roomId) async { await request( RequestType.PUT, '/client/r0/directory/room/${Uri.encodeComponent(alias)}', @@ -880,7 +880,7 @@ class MatrixApi { /// Requests that the server resolve a room alias to a room ID. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-room-roomalias - Future requestRoomAliasInformation(String alias) async { + Future getRoomIdByAlias(String alias) async { final response = await request( RequestType.GET, '/client/r0/directory/room/${Uri.encodeComponent(alias)}', @@ -890,7 +890,7 @@ class MatrixApi { /// Remove a mapping of room alias to room ID. /// https://matrix.org/docs/spec/client_server/r0.6.1#delete-matrix-client-r0-directory-room-roomalias - Future removeRoomAlias(String alias) async { + Future deleteRoomAlias(String alias) async { await request( RequestType.DELETE, '/client/r0/directory/room/${Uri.encodeComponent(alias)}', @@ -900,7 +900,7 @@ class MatrixApi { /// Get a list of aliases maintained by the local server for the given room. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-aliases - Future> requestRoomAliases(String roomId) async { + Future> getLocalAliases(String roomId) async { final response = await request( RequestType.GET, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/aliases', @@ -910,7 +910,7 @@ class MatrixApi { /// This API returns a list of the user's current rooms. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-joined-rooms - Future> requestJoinedRooms() async { + Future> getJoinedRooms() async { final response = await request( RequestType.GET, '/client/r0/joined_rooms', @@ -933,7 +933,7 @@ class MatrixApi { /// This API starts a user participating in a particular room, if that user is allowed to participate in that room. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-invite - Future joinRoom( + Future joinRoomById( String roomId, { String thirdPidSignedSender, String thirdPidSignedmxid, @@ -958,7 +958,7 @@ class MatrixApi { /// This API starts a user participating in a particular room, if that user is allowed to participate in that room. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-join-roomidoralias - Future joinRoomOrAlias( + Future joinRoom( String roomIdOrAlias, { List servers, String thirdPidSignedSender, @@ -1006,8 +1006,7 @@ class MatrixApi { /// Kick a user from the room. /// The caller must have the required power level in order to perform this operation. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-kick - Future kickFromRoom(String roomId, String userId, - {String reason}) async { + Future kick(String roomId, String userId, {String reason}) async { await request(RequestType.POST, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/kick', data: { @@ -1019,8 +1018,7 @@ class MatrixApi { /// Ban a user in the room. If the user is currently in the room, also kick them. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-ban - Future banFromRoom(String roomId, String userId, - {String reason}) async { + Future ban(String roomId, String userId, {String reason}) async { await request( RequestType.POST, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/ban', data: { @@ -1033,7 +1031,7 @@ class MatrixApi { /// Unban a user from the room. This allows them to be invited to the room, and join if they /// would otherwise be allowed to join according to its join rules. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-unban - Future unbanInRoom(String roomId, String userId) async { + Future unban(String roomId, String userId) async { await request(RequestType.POST, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/unban', data: { @@ -1044,7 +1042,7 @@ class MatrixApi { /// Gets the visibility of a given room on the server's public room directory. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-list-room-roomid - Future requestRoomVisibility(String roomId) async { + Future getRoomVisibilityOnDirectory(String roomId) async { final response = await request( RequestType.GET, '/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}', @@ -1055,7 +1053,8 @@ class MatrixApi { /// Sets the visibility of a given room in the server's public room directory. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-directory-list-room-roomid - Future setRoomVisibility(String roomId, Visibility visibility) async { + Future setRoomVisibilityOnDirectory( + String roomId, Visibility visibility) async { await request( RequestType.PUT, '/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}', @@ -1068,7 +1067,7 @@ class MatrixApi { /// Lists the public rooms on the server. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-publicrooms - Future requestPublicRooms({ + Future getPublicRooms({ int limit, String since, String server, @@ -1087,7 +1086,7 @@ class MatrixApi { /// Lists the public rooms on the server, with optional filter. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-publicrooms - Future searchPublicRooms({ + Future queryPublicRooms({ String genericSearchTerm, int limit, String since, @@ -1122,7 +1121,7 @@ class MatrixApi { /// room with and those who reside in public rooms (known to the homeserver). The search MUST /// consider local users to the homeserver, and SHOULD query remote users as part of the search. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-user-directory-search - Future searchUser( + Future searchUserDirectory( String searchTerm, { int limit, }) async { @@ -1140,7 +1139,7 @@ class MatrixApi { /// This API sets the given user's display name. You must have permission to /// set this user's display name, e.g. you need to have their access_token. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-profile-userid-displayname - Future setDisplayname(String userId, String displayname) async { + Future setDisplayName(String userId, String displayname) async { await request( RequestType.PUT, '/client/r0/profile/${Uri.encodeComponent(userId)}/displayname', @@ -1154,7 +1153,7 @@ class MatrixApi { /// Get the user's display name. This API may be used to fetch the user's own /// displayname or to query the name of other users; either locally or on remote homeservers. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-displayname - Future requestDisplayname(String userId) async { + Future getDisplayName(String userId) async { final response = await request( RequestType.GET, '/client/r0/profile/${Uri.encodeComponent(userId)}/displayname', @@ -1179,7 +1178,7 @@ class MatrixApi { /// Get the user's avatar URL. This API may be used to fetch the user's own avatar URL or to /// query the URL of other users; either locally or on remote homeservers. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-avatar-url - Future requestAvatarUrl(String userId) async { + Future getAvatarUrl(String userId) async { final response = await request( RequestType.GET, '/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url', @@ -1190,7 +1189,7 @@ class MatrixApi { /// Get the combined profile information for this user. This API may be used to fetch the user's /// own profile information or other users; either locally or on remote homeservers. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-avatar-url - Future requestProfile(String userId) async { + Future getUserProfile(String userId) async { final response = await request( RequestType.GET, '/client/r0/profile/${Uri.encodeComponent(userId)}', @@ -1200,7 +1199,7 @@ class MatrixApi { /// This API provides credentials for the client to use when initiating calls. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-voip-turnserver - Future requestTurnServerCredentials() async { + Future getTurnServer() async { final response = await request( RequestType.GET, '/client/r0/voip/turnServer', @@ -1212,7 +1211,7 @@ class MatrixApi { /// where N is the value specified in the timeout key. Alternatively, if typing is false, /// it tells the server that the user has stopped typing. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-typing-userid - Future sendTypingNotification( + Future setTyping( String userId, String roomId, bool typing, { @@ -1230,7 +1229,7 @@ class MatrixApi { /// This API updates the marker for the given receipt type to the event ID specified. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-receipt-receipttype-eventid /// - Future sendReceiptMarker(String roomId, String eventId) async { + Future postReceipt(String roomId, String eventId) async { await request( RequestType.POST, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/receipt/m.read/${Uri.encodeComponent(eventId)}', @@ -1240,7 +1239,7 @@ class MatrixApi { /// Sets the position of the read marker for a given room, and optionally the read receipt's location. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-read-markers - Future sendReadMarker(String roomId, String eventId, + Future setReadMarker(String roomId, String eventId, {String readReceiptLocationEventId}) async { await request( RequestType.POST, @@ -1258,7 +1257,7 @@ class MatrixApi { /// the activity time is updated to reflect that activity; the client does not need /// to specify the last_active_ago field. You cannot set the presence state of another user. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-presence-userid-status - Future sendPresence( + Future setPresence( String userId, PresenceType presenceType, { String statusMsg, @@ -1276,7 +1275,7 @@ class MatrixApi { /// Get the given user's presence state. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-presence-userid-status - Future requestPresence(String userId) async { + Future getPresence(String userId) async { final response = await request( RequestType.GET, '/client/r0/presence/${Uri.encodeComponent(userId)}/status', @@ -1287,7 +1286,7 @@ class MatrixApi { /// Uploads a file with the name [fileName] as base64 encoded to the server /// and returns the mxc url as a string. /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-media-r0-upload - Future upload(Uint8List file, String fileName, + Future uploadContent(Uint8List file, String fileName, {String contentType}) async { fileName = fileName.split('/').last; final length = file.length; @@ -1324,7 +1323,7 @@ class MatrixApi { /// Get information about a URL for the client. Typically this is called when a client sees a /// URL in a message and wants to render a preview for the user. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-preview-url - Future requestOpenGraphDataForUrl(Uri url, {int ts}) async { + Future getUrlPreview(Uri url, {int ts}) async { final action = homeserver .resolveUri(Uri(path: '_matrix/media/r0/preview_url', queryParameters: { 'url': url.toString(), @@ -1337,7 +1336,7 @@ class MatrixApi { /// This endpoint allows clients to retrieve the configuration of the content repository, such as upload limitations. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-config - Future requestMaxUploadSize() async { + Future getConfig() async { final action = homeserver.resolve('_matrix/media/r0/config'); final response = await httpClient.get(action); final rawJson = json.decode(response.body.isEmpty ? '{}' : response.body); @@ -1363,7 +1362,7 @@ class MatrixApi { /// Gets information about all devices for the current user. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-devices - Future> requestDevices() async { + Future> getDevices() async { final response = await request( RequestType.GET, '/client/r0/devices', @@ -1375,7 +1374,7 @@ class MatrixApi { /// Gets information on a single device, by device id. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-devices-deviceid - Future requestDevice(String deviceId) async { + Future getDevice(String deviceId) async { final response = await request( RequestType.GET, '/client/r0/devices/${Uri.encodeComponent(deviceId)}', @@ -1385,7 +1384,7 @@ class MatrixApi { /// Updates the metadata on the given device. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-devices-deviceid - Future setDeviceMetadata(String deviceId, {String displayName}) async { + Future updateDevice(String deviceId, {String displayName}) async { await request( RequestType.PUT, '/client/r0/devices/${Uri.encodeComponent(deviceId)}', data: { @@ -1418,7 +1417,7 @@ class MatrixApi { /// Publishes end-to-end encryption keys for the device. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query - Future> uploadDeviceKeys( + Future> uploadKeys( {MatrixDeviceKeys deviceKeys, Map oneTimeKeys, Map fallbackKeys}) async { @@ -1439,7 +1438,7 @@ class MatrixApi { /// Returns the current devices and identity keys for the given users. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query - Future requestDeviceKeys( + Future queryKeys( Map deviceKeys, { int timeout, String token, @@ -1458,7 +1457,7 @@ class MatrixApi { /// Claims one-time keys for use in pre-key messages. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-claim - Future requestOneTimeKeys( + Future claimKeys( Map> oneTimeKeys, { int timeout, }) async { @@ -1475,8 +1474,7 @@ class MatrixApi { /// Gets a list of users who have updated their device identity keys since a previous sync token. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-upload - Future requestDeviceListsUpdate( - String from, String to) async { + Future getKeysChanges(String from, String to) async { final response = await request(RequestType.GET, '/client/r0/keys/changes', query: { 'from': from, @@ -1538,7 +1536,7 @@ class MatrixApi { /// Gets all currently active pushers for the authenticated user. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushers - Future> requestPushers() async { + Future> getPushers() async { final response = await request( RequestType.GET, '/client/r0/pushers', @@ -1552,7 +1550,7 @@ class MatrixApi { /// for this user ID. The behaviour of this endpoint varies depending on the /// values in the JSON body. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-pushers-set - Future setPusher(Pusher pusher, {bool append}) async { + Future postPusher(Pusher pusher, {bool append}) async { final data = pusher.toJson(); if (append != null) { data['append'] = append; @@ -1568,7 +1566,7 @@ class MatrixApi { /// This API is used to paginate through the list of events that the user has /// been, or would have been notified about. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-notifications - Future requestNotifications({ + Future getNotifications({ String from, int limit, String only, @@ -1589,7 +1587,7 @@ class MatrixApi { /// on the rulesets by suffixing a scope to this path e.g. /pushrules/global/. /// This will return a subset of this data under the specified key e.g. the global key. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules - Future requestPushRules() async { + Future getPushRules() async { final response = await request( RequestType.GET, '/client/r0/pushrules', @@ -1599,7 +1597,7 @@ class MatrixApi { /// Retrieve a single specified push rule. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid - Future requestPushRule( + Future getPushRule( String scope, PushRuleKind kind, String ruleId, @@ -1655,7 +1653,7 @@ class MatrixApi { /// This endpoint gets whether the specified push rule is enabled. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid-enabled - Future requestPushRuleEnabled( + Future isPushRuleEnabled( String scope, PushRuleKind kind, String ruleId, @@ -1669,7 +1667,7 @@ class MatrixApi { /// This endpoint allows clients to enable or disable the specified push rule. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-pushrules-scope-kind-ruleid-enabled - Future enablePushRule( + Future setPushRuleEnabled( String scope, PushRuleKind kind, String ruleId, @@ -1685,7 +1683,7 @@ class MatrixApi { /// This endpoint get the actions for the specified push rule. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid-actions - Future> requestPushRuleActions( + Future> getPushRuleActions( String scope, PushRuleKind kind, String ruleId, @@ -1720,7 +1718,7 @@ class MatrixApi { /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-search /// Please note: The specification is not 100% clear what it is expecting and sending here. /// So we stick with pure json until we have more information. - Future> globalSearch(Map query) async { + Future> search(Map query) async { return await request( RequestType.POST, '/client/r0/search', @@ -1731,7 +1729,7 @@ class MatrixApi { /// This will listen for new events related to a particular room and return them to the /// caller. This will block until an event is received, or until the timeout is reached. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-events - Future requestEvents({ + Future getEvents({ String from, int timeout, String roomId, @@ -1747,7 +1745,7 @@ class MatrixApi { /// List the tags set by a user on a room. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-rooms-roomid-tags - Future> requestRoomTags(String userId, String roomId) async { + Future> getRoomTags(String userId, String roomId) async { final response = await request( RequestType.GET, '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags', @@ -1759,7 +1757,7 @@ class MatrixApi { /// Add a tag to the room. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-tags-tag - Future addRoomTag( + Future setRoomTag( String userId, String roomId, String tag, { @@ -1775,7 +1773,7 @@ class MatrixApi { /// Remove a tag from the room. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-tags-tag - Future removeRoomTag(String userId, String roomId, String tag) async { + Future deleteRoomTag(String userId, String roomId, String tag) async { await request( RequestType.DELETE, '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}', @@ -1801,7 +1799,7 @@ class MatrixApi { /// Get some account_data for the client. This config is only visible to the user that set the account_data. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-account-data-type - Future> requestAccountData( + Future> getAccountData( String userId, String type, ) async { @@ -1814,7 +1812,7 @@ class MatrixApi { /// Set some account_data for the client on a given room. This config is only visible to the user that set /// the account_data. The config will be synced to clients in the per-room account_data. /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-account-data-type - Future setRoomAccountData( + Future setAccountDataPerRoom( String userId, String roomId, String type, @@ -1830,7 +1828,7 @@ class MatrixApi { /// Get some account_data for the client on a given room. This config is only visible to the user that set the account_data. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-rooms-roomid-account-data-type - Future> requestRoomAccountData( + Future> getAccountDataPerRoom( String userId, String roomId, String type, @@ -1843,7 +1841,7 @@ class MatrixApi { /// Gets information about a particular user. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-admin-whois-userid - Future requestWhoIsInfo(String userId) async { + Future getWhoIs(String userId) async { final response = await request( RequestType.GET, '/client/r0/admin/whois/${Uri.encodeComponent(userId)}', @@ -1854,7 +1852,7 @@ class MatrixApi { /// This API returns a number of events that happened just before and after the specified event. /// This allows clients to get the context surrounding an event. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-context-eventid - Future requestEventContext( + Future getEventContext( String roomId, String eventId, { int limit, @@ -1871,7 +1869,7 @@ class MatrixApi { /// Reports an event as inappropriate to the server, which may then notify the appropriate people. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-report-eventid - Future reportEvent( + Future reportContent( String roomId, String eventId, String reason, @@ -1961,7 +1959,7 @@ class MatrixApi { .toList(); } - Future requestOpenIdCredentials(String userId) async { + Future requestOpenIdToken(String userId) async { final response = await request( RequestType.POST, '/client/r0/user/${Uri.encodeComponent(userId)}/openid/request_token', diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index c25f8430..31b54564 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -122,7 +122,7 @@ void main() { }); test('getSupportedVersions', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final supportedVersions = await matrixApi.requestSupportedVersions(); + final supportedVersions = await matrixApi.getVersions(); expect(supportedVersions.versions.contains('r0.5.0'), true); expect(supportedVersions.unstableFeatures['m.lazy_load_members'], true); expect(FakeMatrixApi.api['GET']['/client/versions']({}), @@ -131,8 +131,7 @@ void main() { }); test('getWellKnownInformation', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final wellKnownInformation = - await matrixApi.requestWellKnownInformation(); + final wellKnownInformation = await matrixApi.getWellknown(); expect(wellKnownInformation.mHomeserver.baseUrl, 'https://fakeserver.notexisting'); expect(wellKnownInformation.toJson(), { @@ -147,7 +146,7 @@ void main() { }); test('getLoginTypes', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final loginTypes = await matrixApi.requestLoginTypes(); + final loginTypes = await matrixApi.getLoginFlows(); expect(loginTypes.flows.first.type, 'm.login.password'); expect(FakeMatrixApi.api['GET']['/client/r0/login']({}), loginTypes.toJson()); @@ -273,14 +272,15 @@ void main() { }); test('usernameAvailable', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final loginResponse = await matrixApi.usernameAvailable('testuser'); + final loginResponse = + await matrixApi.checkUsernameAvailability('testuser'); expect(loginResponse, true); matrixApi.homeserver = null; }); test('getThirdPartyIdentifiers', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestThirdPartyIdentifiers(); + final response = await matrixApi.getAccount3PIDs(); expect(FakeMatrixApi.api['GET']['/client/r0/account/3pid']({}), {'threepids': response.map((t) => t.toJson()).toList()}); matrixApi.homeserver = matrixApi.accessToken = null; @@ -288,14 +288,14 @@ void main() { test('addThirdPartyIdentifier', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.addThirdPartyIdentifier('1234', '1234', + await matrixApi.add3PID('1234', '1234', auth: AuthenticationData.fromJson({'type': 'm.login.dummy'})); matrixApi.homeserver = matrixApi.accessToken = null; }); test('bindThirdPartyIdentifier', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.bindThirdPartyIdentifier( + await matrixApi.bind3PID( '1234', '1234', 'https://example.com', @@ -306,7 +306,7 @@ void main() { test('deleteThirdPartyIdentifier', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.deleteThirdPartyIdentifier( + final response = await matrixApi.delete3pidFromAccount( 'alice@example.com', ThirdPartyIdentifierMedium.email, idServer: 'https://example.com', @@ -317,7 +317,7 @@ void main() { test('unbindThirdPartyIdentifier', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.unbindThirdPartyIdentifier( + final response = await matrixApi.unbind3pidFromAccount( 'alice@example.com', ThirdPartyIdentifierMedium.email, 'https://example.com', @@ -355,14 +355,14 @@ void main() { test('requestMsisdnValidationToken', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.whoAmI(); + final response = await matrixApi.getTokenOwner(); expect(response, 'alice@example.com'); matrixApi.homeserver = matrixApi.accessToken = null; }); test('getServerCapabilities', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestServerCapabilities(); + final response = await matrixApi.getCapabilities(); expect(FakeMatrixApi.api['GET']['/client/r0/capabilities']({}), {'capabilities': response.toJson()}); matrixApi.homeserver = matrixApi.accessToken = null; @@ -371,7 +371,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = - await matrixApi.uploadFilter('alice@example.com', Filter()); + await matrixApi.defineFilter('alice@example.com', Filter()); expect(response, '1234'); final filter = Filter( room: RoomFilter( @@ -442,7 +442,7 @@ void main() { 'not_senders': ['@alice:example.com'] }, }); - await matrixApi.uploadFilter( + await matrixApi.defineFilter( 'alice@example.com', filter, ); @@ -481,7 +481,7 @@ void main() { test('downloadFilter', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.downloadFilter('alice@example.com', '1234'); + await matrixApi.getFilter('alice@example.com', '1234'); matrixApi.homeserver = matrixApi.accessToken = null; }); test('sync', () async { @@ -506,7 +506,7 @@ void main() { matrixApi.accessToken = '1234'; final event = - await matrixApi.requestEvent('!localpart:server.abc', '1234'); + await matrixApi.getOneRoomEvent('!localpart:server.abc', '1234'); expect(event.eventId, '143273582443PhrSn:example.org'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -525,7 +525,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final states = await matrixApi.requestStates('!localpart:server.abc'); + final states = await matrixApi.getRoomState('!localpart:server.abc'); expect(states.length, 4); matrixApi.homeserver = matrixApi.accessToken = null; @@ -534,7 +534,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final states = await matrixApi.requestMembers( + final states = await matrixApi.getMembersByRoom( '!localpart:server.abc', at: '1234', membership: Membership.join, @@ -548,7 +548,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final states = await matrixApi.requestJoinedMembers( + final states = await matrixApi.getJoinedMembersByRoom( '!localpart:server.abc', ); expect(states.length, 1); @@ -563,7 +563,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final timelineHistoryResponse = await matrixApi.requestMessages( + final timelineHistoryResponse = await matrixApi.getRoomEvents( '!localpart:server.abc', '1234', Direction.b, @@ -584,7 +584,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final eventId = await matrixApi.sendState( + final eventId = await matrixApi.setRoomStateWithKey( '!localpart:server.abc', 'm.room.avatar', {'url': 'mxc://1234'}); expect(eventId, 'YUwRidLecu:example.com'); @@ -610,7 +610,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final eventId = await matrixApi.redact( + final eventId = await matrixApi.redactEvent( '!localpart:server.abc', '1234', '1234', @@ -648,7 +648,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.createRoomAlias( + await matrixApi.setRoomAlias( '#testalias:example.com', '!1234:example.com', ); @@ -659,7 +659,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final roomAliasInformation = await matrixApi.requestRoomAliasInformation( + final roomAliasInformation = await matrixApi.getRoomIdByAlias( '#testalias:example.com', ); @@ -674,7 +674,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.removeRoomAlias('#testalias:example.com'); + await matrixApi.deleteRoomAlias('#testalias:example.com'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -682,7 +682,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final list = await matrixApi.requestRoomAliases('!localpart:example.com'); + final list = await matrixApi.getLocalAliases('!localpart:example.com'); expect(list.length, 3); matrixApi.homeserver = matrixApi.accessToken = null; @@ -691,7 +691,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final list = await matrixApi.requestJoinedRooms(); + final list = await matrixApi.getJoinedRooms(); expect(list.length, 1); matrixApi.homeserver = matrixApi.accessToken = null; @@ -710,7 +710,7 @@ void main() { matrixApi.accessToken = '1234'; final roomId = '!localpart:example.com'; - final response = await matrixApi.joinRoom( + final response = await matrixApi.joinRoomById( roomId, thirdPidSignedSender: '@bob:example.com', thirdPidSignedmxid: '@alice:example.com', @@ -728,7 +728,7 @@ void main() { matrixApi.accessToken = '1234'; final roomId = '!localpart:example.com'; - final response = await matrixApi.joinRoomOrAlias( + final response = await matrixApi.joinRoom( roomId, servers: ['example.com', 'example.abc'], thirdPidSignedSender: '@bob:example.com', @@ -762,7 +762,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.kickFromRoom( + await matrixApi.kick( '!localpart:example.com', '@bob:example.com', reason: 'test', @@ -774,7 +774,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.banFromRoom( + await matrixApi.ban( '!localpart:example.com', '@bob:example.com', reason: 'test', @@ -786,7 +786,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.unbanInRoom( + await matrixApi.unban( '!localpart:example.com', '@bob:example.com', ); @@ -797,8 +797,8 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final visibility = - await matrixApi.requestRoomVisibility('!localpart:example.com'); + final visibility = await matrixApi + .getRoomVisibilityOnDirectory('!localpart:example.com'); expect(visibility, Visibility.public); matrixApi.homeserver = matrixApi.accessToken = null; @@ -807,7 +807,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.setRoomVisibility( + await matrixApi.setRoomVisibilityOnDirectory( '!localpart:example.com', Visibility.private); matrixApi.homeserver = matrixApi.accessToken = null; @@ -816,7 +816,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestPublicRooms( + final response = await matrixApi.getPublicRooms( limit: 10, since: '1234', server: 'example.com', @@ -833,7 +833,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.searchPublicRooms( + final response = await matrixApi.queryPublicRooms( limit: 10, since: '1234', server: 'example.com', @@ -853,7 +853,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.searchUser( + final response = await matrixApi.searchUserDirectory( 'test', limit: 10, ); @@ -867,7 +867,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.setDisplayname('@alice:example.com', 'Alice M'); + await matrixApi.setDisplayName('@alice:example.com', 'Alice M'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -875,7 +875,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestDisplayname('@alice:example.com'); + await matrixApi.getDisplayName('@alice:example.com'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -894,7 +894,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestAvatarUrl('@alice:example.com'); + final response = await matrixApi.getAvatarUrl('@alice:example.com'); expect(response, Uri.parse('mxc://test')); matrixApi.homeserver = matrixApi.accessToken = null; @@ -903,7 +903,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestProfile('@alice:example.com'); + final response = await matrixApi.getUserProfile('@alice:example.com'); expect( FakeMatrixApi.api['GET'] ['/client/r0/profile/%40alice%3Aexample.com']({}), @@ -915,7 +915,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestTurnServerCredentials(); + final response = await matrixApi.getTurnServer(); expect(FakeMatrixApi.api['GET']['/client/r0/voip/turnServer']({}), response.toJson()); @@ -925,7 +925,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.sendTypingNotification( + await matrixApi.setTyping( '@alice:example.com', '!localpart:example.com', true, @@ -938,7 +938,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.sendReceiptMarker( + await matrixApi.postReceipt( '!localpart:example.com', '\$1234:example.com', ); @@ -949,7 +949,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.sendReadMarker( + await matrixApi.setReadMarker( '!localpart:example.com', '\$1234:example.com', readReceiptLocationEventId: '\$1234:example.com', @@ -961,7 +961,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.sendPresence( + await matrixApi.setPresence( '@alice:example.com', PresenceType.offline, statusMsg: 'test', @@ -973,7 +973,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestPresence( + final response = await matrixApi.getPresence( '@alice:example.com', ); expect( @@ -985,11 +985,11 @@ void main() { }); test('upload', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final response = await matrixApi.upload(Uint8List(0), 'file.jpeg'); + final response = await matrixApi.uploadContent(Uint8List(0), 'file.jpeg'); expect(response, 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'); var throwsException = false; try { - await matrixApi.upload(Uint8List(0), 'file.jpg'); + await matrixApi.uploadContent(Uint8List(0), 'file.jpg'); } on MatrixException catch (_) { throwsException = true; } @@ -1000,7 +1000,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final openGraphData = await matrixApi.requestOpenGraphDataForUrl( + final openGraphData = await matrixApi.getUrlPreview( Uri.parse('https://matrix.org'), ts: 10, ); @@ -1015,7 +1015,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestMaxUploadSize(); + final response = await matrixApi.getConfig(); expect(response, 50000000); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1036,7 +1036,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final devices = await matrixApi.requestDevices(); + final devices = await matrixApi.getDevices(); expect(FakeMatrixApi.api['GET']['/client/r0/devices']({})['devices'], devices.map((i) => i.toJson()).toList()); @@ -1046,7 +1046,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestDevice('QBUAZIFURK'); + await matrixApi.getDevice('QBUAZIFURK'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1054,7 +1054,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.setDeviceMetadata('QBUAZIFURK', displayName: 'test'); + await matrixApi.updateDevice('QBUAZIFURK', displayName: 'test'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1080,7 +1080,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.uploadDeviceKeys( + await matrixApi.uploadKeys( deviceKeys: MatrixDeviceKeys( '@alice:example.com', 'ABCD', @@ -1097,7 +1097,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestDeviceKeys( + final response = await matrixApi.queryKeys( { '@alice:example.com': [], }, @@ -1119,7 +1119,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestOneTimeKeys( + final response = await matrixApi.claimKeys( { '@alice:example.com': {'JLAFKJWSCS': 'signed_curve25519'} }, @@ -1139,7 +1139,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestDeviceListsUpdate('1234', '1234'); + await matrixApi.getKeysChanges('1234', '1234'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1230,7 +1230,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestPushers(); + final response = await matrixApi.getPushers(); expect( FakeMatrixApi.api['GET']['/client/r0/pushers']({}), {'pushers': response.map((i) => i.toJson()).toList()}, @@ -1242,7 +1242,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.setPusher( + await matrixApi.postPusher( Pusher( '1234', 'app.id', @@ -1263,7 +1263,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestNotifications( + final response = await matrixApi.getNotifications( from: '1234', limit: 10, only: '1234', @@ -1280,7 +1280,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestPushRules(); + final response = await matrixApi.getPushRules(); expect( FakeMatrixApi.api['GET']['/client/r0/pushrules']({}), {'global': response.toJson()}, @@ -1292,8 +1292,8 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestPushRule( - 'global', PushRuleKind.content, 'nocake'); + final response = + await matrixApi.getPushRule('global', PushRuleKind.content, 'nocake'); expect( FakeMatrixApi.api['GET'] ['/client/r0/pushrules/global/content/nocake']({}), @@ -1338,7 +1338,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final enabled = await matrixApi.requestPushRuleEnabled( + final enabled = await matrixApi.isPushRuleEnabled( 'global', PushRuleKind.content, 'nocake'); expect(enabled, true); @@ -1348,7 +1348,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.enablePushRule( + await matrixApi.setPushRuleEnabled( 'global', PushRuleKind.content, 'nocake', @@ -1361,7 +1361,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final actions = await matrixApi.requestPushRuleActions( + final actions = await matrixApi.getPushRuleActions( 'global', PushRuleKind.content, 'nocake'); expect(actions.first, PushRuleAction.notify); @@ -1384,7 +1384,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.globalSearch({}); + await matrixApi.search({}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1392,8 +1392,8 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestEvents( - from: '1234', roomId: '!1234', timeout: 10); + final response = + await matrixApi.getEvents(from: '1234', roomId: '!1234', timeout: 10); expect( FakeMatrixApi.api['GET'] ['/client/r0/events?from=1234&timeout=10&roomId=%211234']({}), @@ -1406,7 +1406,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestRoomTags( + final response = await matrixApi.getRoomTags( '@alice:example.com', '!localpart:example.com'); expect( FakeMatrixApi.api['GET'][ @@ -1420,7 +1420,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.addRoomTag( + await matrixApi.setRoomTag( '@alice:example.com', '!localpart:example.com', 'testtag', @@ -1433,7 +1433,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.removeRoomTag( + await matrixApi.deleteRoomTag( '@alice:example.com', '!localpart:example.com', 'testtag', @@ -1457,7 +1457,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestAccountData( + await matrixApi.getAccountData( '@alice:example.com', 'test.account.data', ); @@ -1468,7 +1468,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.setRoomAccountData( + await matrixApi.setAccountDataPerRoom( '@alice:example.com', '1234', 'test.account.data', @@ -1481,7 +1481,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestRoomAccountData( + await matrixApi.getAccountDataPerRoom( '@alice:example.com', '1234', 'test.account.data', @@ -1493,7 +1493,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestWhoIsInfo('@alice:example.com'); + final response = await matrixApi.getWhoIs('@alice:example.com'); expect( FakeMatrixApi.api['GET'] ['/client/r0/admin/whois/%40alice%3Aexample.com']({}), @@ -1506,7 +1506,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestEventContext('1234', '1234', + final response = await matrixApi.getEventContext('1234', '1234', limit: 10, filter: '{}'); expect( FakeMatrixApi.api['GET'] @@ -1520,7 +1520,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.reportEvent( + await matrixApi.reportContent( '1234', '1234', 'test', @@ -1607,7 +1607,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestOpenIdCredentials('1234'); + final response = await matrixApi.requestOpenIdToken('1234'); expect( FakeMatrixApi.api['POST'] ['/client/r0/user/1234/openid/request_token']({}), From adb6d0a564093b5988df0abd27a9acebc4a9c2c9 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 10 May 2021 12:08:26 +0200 Subject: [PATCH 057/174] bump version --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d30a93d8..f793aeb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.3.0 +- feat: operation names from OpenAPI spec + ## 0.2.6 - fix: Missing RoomCreationTypes diff --git a/pubspec.yaml b/pubspec.yaml index 9c1b9de8..a4f92970 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.2.6 +version: 0.3.0 homepage: https://famedly.com environment: From c70b149c204a23c46836b3de380f88bc21d79408 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 12 May 2021 11:53:58 +0200 Subject: [PATCH 058/174] change: Remove logger The logger package has a lot of issues. The colors are not working in web and on iOS. Emojis are not working on some platforms. It introduced a not very important library in a SDk which is intended to be as minimal as possible. This simplifies the logging to a format which works everywhere. The # Syntax makes it also look good as markdown. It is not very far away from the default syntax of errors and stacktraces. It still provides several log levels, the same API and a list of output events for the logviewer. --- lib/src/utils/logs.dart | 141 ++++++++++++++++++++------- pubspec.yaml | 1 - test/matrix_api_test.dart | 9 +- test/try_get_map_extension_test.dart | 1 - 4 files changed, 111 insertions(+), 41 deletions(-) diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index a6a64be5..58314a71 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -21,50 +21,123 @@ * SOFTWARE. */ -import 'package:logger/logger.dart'; +enum Level { + wtf, + error, + warning, + info, + debug, + verbose, +} -class Logs extends Logger { +class Logs { static final Logs _singleton = Logs._internal(); factory Logs() { return _singleton; } - set level(Level newLevel) => Logger.level = newLevel; + Level level = Level.info; - final List outputEvents = []; + final List outputEvents = []; - Logs._internal() - : super( - printer: _MatrixSdkPrinter(), - filter: _MatrixSdkFilter(), - output: _CacheOutput(), - ); -} + Logs._internal(); -class _MatrixSdkFilter extends LogFilter { - @override - bool shouldLog(LogEvent event) => event.level.index >= Logger.level.index; -} - -class _CacheOutput extends ConsoleOutput { - @override - void output(OutputEvent event) { - Logs().outputEvents.add(event); - super.output(event); - } -} - -class _MatrixSdkPrinter extends PrettyPrinter { - _MatrixSdkPrinter() : super(methodCount: 0, lineLength: 100); - - @override - List log(LogEvent event) { - if (event.error == null && event.stackTrace == null) { - return [ - '${PrettyPrinter.levelColors[event.level]}${PrettyPrinter.levelEmojis[event.level]} ${event.message.toString()}' - ]; + void addLogEvent(LogEvent logEvent) { + logEvent.printOut(); + if (logEvent.level.index >= level.index) { + outputEvents.add(logEvent); + } + } + + void wtf(String title, [Object exception, StackTrace stackTrace]) => + addLogEvent( + LogEvent( + title, + exception: exception, + stackTrace: stackTrace, + level: Level.wtf, + ), + ); + + void e(String title, [Object exception, StackTrace stackTrace]) => + addLogEvent( + LogEvent( + title, + exception: exception, + stackTrace: stackTrace, + level: Level.error, + ), + ); + + void w(String title, [Object exception, StackTrace stackTrace]) => + addLogEvent( + LogEvent( + title, + exception: exception, + stackTrace: stackTrace, + level: Level.warning, + ), + ); + + void i(String title, [Object exception, StackTrace stackTrace]) => + addLogEvent( + LogEvent( + title, + exception: exception, + stackTrace: stackTrace, + level: Level.info, + ), + ); + + void d(String title, [Object exception, StackTrace stackTrace]) => + addLogEvent( + LogEvent( + title, + exception: exception, + stackTrace: stackTrace, + level: Level.debug, + ), + ); + + void v(String title, [Object exception, StackTrace stackTrace]) => + addLogEvent( + LogEvent( + title, + exception: exception, + stackTrace: stackTrace, + level: Level.verbose, + ), + ); +} + +// ignore: avoid_print +class LogEvent { + final String title; + final Object exception; + final StackTrace stackTrace; + final Level level; + + LogEvent( + this.title, { + this.exception, + this.stackTrace, + this.level = Level.debug, + }); + + void printOut() { + var logsStr = + '# [${level.toString().split('.').last.toUpperCase()}] $title'; + if (exception != null) { + logsStr += ' - ' + exception.toString(); + } + // ignore: avoid_print + print(logsStr); + if (stackTrace != null) { + // ignore: avoid_print + print('## Stacktrace:'); + // ignore: avoid_print + print(stackTrace.toString()); } - return super.log(event); } } diff --git a/pubspec.yaml b/pubspec.yaml index a4f92970..0ef76bf5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,6 @@ environment: dependencies: http: ^0.13.0 - logger: ^1.0.0 mime: ^1.0.0 dev_dependencies: diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 31b54564..e58464a6 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -22,7 +22,6 @@ */ import 'dart:typed_data'; -import 'package:logger/logger.dart'; import 'package:matrix_api_lite/fake_matrix_api.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; @@ -37,11 +36,11 @@ void main() { Logs().w('Test log'); Logs().e('Test log'); Logs().wtf('Test log'); - Logs().v('Test log', Exception('Test')); + Logs().v('Test log', Exception('There has been a verbose')); Logs().d('Test log', Exception('Test')); - Logs().w('Test log', Exception('Test')); - Logs().e('Test log', Exception('Test')); - Logs().wtf('Test log', Exception('Test')); + Logs().w('Test log', Exception('Very bad error')); + Logs().e('Test log', Exception('Test'), StackTrace.current); + Logs().wtf('Test log', Exception('Test'), StackTrace.current); }); Logs().level = Level.error; final matrixApi = MatrixApi( diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index 45a4503b..d38a1e68 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -21,7 +21,6 @@ * SOFTWARE. */ -import 'package:logger/logger.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; From 73a2f386982ae8a697ce5d9c1dbbae227493ff5f Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 12 May 2021 13:37:35 +0200 Subject: [PATCH 059/174] Update version --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f793aeb7..51c34def 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.3.1 +- change: Remove logger package + ## 0.3.0 - feat: operation names from OpenAPI spec diff --git a/pubspec.yaml b/pubspec.yaml index 0ef76bf5..ae9a51dd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.3.0 +version: 0.3.1 homepage: https://famedly.com environment: From 9b3768300e2f249b4a11b807ae6bfadf49747c1d Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Wed, 9 Jun 2021 10:11:56 +0200 Subject: [PATCH 060/174] fix: Logs should only printed if loglevel is high enough --- CHANGELOG.md | 3 +++ lib/src/utils/logs.dart | 4 ++-- pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51c34def..130b20c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.3.2 +- fix: Logs should only printed if loglevel is high enough + ## 0.3.1 - change: Remove logger package diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index 58314a71..8fe7fca6 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -44,9 +44,9 @@ class Logs { Logs._internal(); void addLogEvent(LogEvent logEvent) { - logEvent.printOut(); + outputEvents.add(logEvent); if (logEvent.level.index >= level.index) { - outputEvents.add(logEvent); + logEvent.printOut(); } } diff --git a/pubspec.yaml b/pubspec.yaml index ae9a51dd..6e20d760 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.3.1 +version: 0.3.2 homepage: https://famedly.com environment: From 3a6d2243481cdd531063ac977e023a64209565e0 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 10 Jun 2021 09:21:20 +0200 Subject: [PATCH 061/174] fix: Log filter in wrong direction --- CHANGELOG.md | 3 +++ lib/src/utils/logs.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 130b20c7..b668fe74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.3.3 +- fix: Log filter in wrong direction + ## 0.3.2 - fix: Logs should only printed if loglevel is high enough diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index 8fe7fca6..298e1985 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -45,7 +45,7 @@ class Logs { void addLogEvent(LogEvent logEvent) { outputEvents.add(logEvent); - if (logEvent.level.index >= level.index) { + if (logEvent.level.index <= level.index) { logEvent.printOut(); } } diff --git a/pubspec.yaml b/pubspec.yaml index 6e20d760..828a9cbf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.3.2 +version: 0.3.3 homepage: https://famedly.com environment: From e3a1b6aa7717f5ec8fee1f8e693110fa1ae7ab49 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Thu, 24 Jun 2021 17:36:35 +0200 Subject: [PATCH 062/174] refactor: mostly use dart_openapi_codegen --- README.md | 7 +- analysis_options.yaml | 1 + example/matrix_api_lite_example.dart | 1 + lib/fake_matrix_api.dart | 12 +- lib/matrix_api_lite.dart | 28 +- lib/src/generated/api.dart | 3553 +++++++++++++++++ lib/src/generated/fixed_model.dart | 7 + lib/src/generated/internal.dart | 6 + lib/src/generated/model.dart | 3113 +++++++++++++++ lib/src/matrix_api.dart | 1538 +------ lib/src/model/algorithm_types.dart | 1 + lib/src/model/auth/authentication_data.dart | 1 + .../model/auth/authentication_identifier.dart | 1 + .../model/auth/authentication_password.dart | 1 + .../auth/authentication_phone_identifier.dart | 1 + .../model/auth/authentication_recaptcha.dart | 1 + ...authentication_third_party_identifier.dart | 1 + .../auth/authentication_three_pid_creds.dart | 1 + lib/src/model/auth/authentication_token.dart | 1 + lib/src/model/auth/authentication_types.dart | 1 + .../auth/authentication_user_identifier.dart | 1 + lib/src/model/basic_event.dart | 1 + lib/src/model/basic_event_with_sender.dart | 1 + lib/src/model/basic_room_event.dart | 1 + lib/src/model/device.dart | 51 - lib/src/model/event_context.dart | 75 - lib/src/model/event_types.dart | 1 + .../events/forwarded_room_key_content.dart | 1 + .../model/events/olm_plaintext_payload.dart | 1 + .../model/events/room_encrypted_content.dart | 1 + .../model/events/room_encryption_content.dart | 1 + lib/src/model/events/room_key_content.dart | 1 + .../events/room_key_request_content.dart | 1 + .../secret_storage_default_key_content.dart | 1 + .../events/secret_storage_key_content.dart | 1 + lib/src/model/events/tombstone_content.dart | 1 + lib/src/model/events_sync_update.dart | 1 + lib/src/model/filter.dart | 219 - lib/src/model/keys_query_response.dart | 118 - lib/src/model/login_response.dart | 50 - lib/src/model/login_types.dart | 54 - .../model/matrix_connection_exception.dart | 1 + lib/src/model/matrix_event.dart | 1 + lib/src/model/matrix_exception.dart | 1 + lib/src/model/matrix_keys.dart | 1 + lib/src/model/message_types.dart | 1 + .../model/notifications_query_response.dart | 75 - .../model/one_time_keys_claim_response.dart | 46 - lib/src/model/open_graph_data.dart | 67 - lib/src/model/open_id_credentials.dart | 44 - lib/src/model/presence.dart | 1 + lib/src/model/presence_content.dart | 3 +- lib/src/model/profile.dart | 49 - lib/src/model/public_rooms_response.dart | 98 - lib/src/model/push_rule_set.dart | 148 - lib/src/model/pusher.dart | 94 - lib/src/model/request_token_response.dart | 1 + lib/src/model/room_alias_information.dart | 38 - lib/src/model/room_creation_types.dart | 1 + lib/src/model/room_keys_info.dart | 73 - lib/src/model/room_keys_keys.dart | 19 +- lib/src/model/room_summary.dart | 1 + lib/src/model/room_types.dart | 1 + lib/src/model/server_capabilities.dart | 95 - lib/src/model/stripped_state_event.dart | 1 + lib/src/model/supported_protocol.dart | 1 + lib/src/model/supported_versions.dart | 41 - lib/src/model/sync_update.dart | 1 + lib/src/model/tag.dart | 46 - lib/src/model/third_party_identifier.dart | 47 - lib/src/model/third_party_location.dart | 1 + lib/src/model/third_party_user.dart | 1 + lib/src/model/timeline_history_response.dart | 54 - lib/src/model/turn_server_credentials.dart | 44 - .../model/upload_key_signatures_response.dart | 1 + lib/src/model/user_search_result.dart | 42 - lib/src/model/well_known_information.dart | 73 - lib/src/model/who_is_info.dart | 108 - lib/src/utils/logs.dart | 1 + lib/src/utils/map_copy_extension.dart | 1 + lib/src/utils/try_get_map_extension.dart | 1 + lib/src/values.dart | 20 + pubspec.yaml | 2 +- test/event_content_test.dart | 1 + test/map_copy_extension_test.dart | 1 + test/matrix_api_test.dart | 143 +- test/try_get_map_extension_test.dart | 1 + 87 files changed, 6865 insertions(+), 3484 deletions(-) create mode 100644 lib/src/generated/api.dart create mode 100644 lib/src/generated/fixed_model.dart create mode 100644 lib/src/generated/internal.dart create mode 100644 lib/src/generated/model.dart delete mode 100644 lib/src/model/device.dart delete mode 100644 lib/src/model/event_context.dart delete mode 100644 lib/src/model/filter.dart delete mode 100644 lib/src/model/keys_query_response.dart delete mode 100644 lib/src/model/login_response.dart delete mode 100644 lib/src/model/login_types.dart delete mode 100644 lib/src/model/notifications_query_response.dart delete mode 100644 lib/src/model/one_time_keys_claim_response.dart delete mode 100644 lib/src/model/open_graph_data.dart delete mode 100644 lib/src/model/open_id_credentials.dart delete mode 100644 lib/src/model/profile.dart delete mode 100644 lib/src/model/public_rooms_response.dart delete mode 100644 lib/src/model/push_rule_set.dart delete mode 100644 lib/src/model/pusher.dart delete mode 100644 lib/src/model/room_alias_information.dart delete mode 100644 lib/src/model/room_keys_info.dart delete mode 100644 lib/src/model/server_capabilities.dart delete mode 100644 lib/src/model/supported_versions.dart delete mode 100644 lib/src/model/tag.dart delete mode 100644 lib/src/model/third_party_identifier.dart delete mode 100644 lib/src/model/timeline_history_response.dart delete mode 100644 lib/src/model/turn_server_credentials.dart delete mode 100644 lib/src/model/user_search_result.dart delete mode 100644 lib/src/model/well_known_information.dart delete mode 100644 lib/src/model/who_is_info.dart create mode 100644 lib/src/values.dart diff --git a/README.md b/README.md index c407e7d1..3fabe921 100644 --- a/README.md +++ b/README.md @@ -18,4 +18,9 @@ void main() async { print(capabilities.toJson()); } -``` \ No newline at end of file +``` + +## Generated code + +The files in `lib/src/generated` are generated by [dart_openapi_codegen](https://gitlab.com/famedly/company/frontend/dart_openapi_codegen) +from [matrix-doc](https://github.com/matrix-org/matrix-doc/). See the README.md in dart_openapi_codegen for more information. diff --git a/analysis_options.yaml b/analysis_options.yaml index 7efcbfc1..8e8f9513 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -12,3 +12,4 @@ analyzer: todo: ignore exclude: - example/matrix_api_lite_example.dart + - lib/src/generated/**.dart diff --git a/example/matrix_api_lite_example.dart b/example/matrix_api_lite_example.dart index 0699acc4..70876234 100644 --- a/example/matrix_api_lite_example.dart +++ b/example/matrix_api_lite_example.dart @@ -1,3 +1,4 @@ +// @dart=2.9 import 'package:matrix_api_lite/src/matrix_api.dart'; void main() async { diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 7786b4ea..f2b3f6de 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -753,12 +754,7 @@ class FakeMatrixApi extends MockClient { 'error': 'Blabla', }, '/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10': (var req) => { - 'og:title': 'Matrix Blog Post', - 'og:description': 'This is a really cool blog post from matrix.org', 'og:image': 'mxc://example.com/ascERGshawAWawugaAcauga', - 'og:image:type': 'image/png', - 'og:image:height': 48, - 'og:image:width': 48, 'matrix:image:size': 102400 }, '/media/r0/config': (var req) => {'m.upload.size': 50000000}, @@ -910,7 +906,7 @@ class FakeMatrixApi extends MockClient { 'com.example.custom.ratelimit': {'max_requests_per_hour': 600} } }, - '/client/r0/rooms/1234/context/1234?filter=%7B%7D&limit=10': (var req) => + '/client/r0/rooms/1234/context/1234?limit=10&filter=%7B%7D': (var req) => { 'end': 't29-57_2_0_2', 'events_after': [ @@ -1271,7 +1267,7 @@ class FakeMatrixApi extends MockClient { 'origin_server_ts': 1432735824653, 'unsigned': {'age': 1234} }, - '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&dir=b&to=1234&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': + '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': (var req) => messagesResponse, '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': (var req) => messagesResponse, @@ -1989,7 +1985,7 @@ class FakeMatrixApi extends MockClient { 'access_token': 'SomeT0kenHere', 'token_type': 'Bearer', 'matrix_server_name': 'example.com', - 'expires_in': 3600.0 + 'expires_in': 3600 }, '/client/r0/user/@test:fakeServer.notExisting/openid/request_token': (var req) => { diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index afd709b0..6695187e 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -24,6 +25,8 @@ library matrix_api_lite; export 'src/matrix_api.dart'; +export 'src/values.dart'; +export 'src/generated/model.dart'; export 'src/utils/logs.dart'; export 'src/utils/map_copy_extension.dart'; export 'src/utils/try_get_map_extension.dart'; @@ -31,50 +34,25 @@ export 'src/model/algorithm_types.dart'; export 'src/model/basic_event.dart'; export 'src/model/basic_event_with_sender.dart'; export 'src/model/basic_room_event.dart'; -export 'src/model/device.dart'; -export 'src/model/event_context.dart'; export 'src/model/event_types.dart'; export 'src/model/events_sync_update.dart'; -export 'src/model/filter.dart'; -export 'src/model/keys_query_response.dart'; -export 'src/model/login_response.dart'; -export 'src/model/login_types.dart'; export 'src/model/matrix_connection_exception.dart'; export 'src/model/matrix_event.dart'; export 'src/model/matrix_exception.dart'; export 'src/model/matrix_keys.dart'; export 'src/model/message_types.dart'; -export 'src/model/notifications_query_response.dart'; -export 'src/model/one_time_keys_claim_response.dart'; -export 'src/model/open_graph_data.dart'; -export 'src/model/open_id_credentials.dart'; export 'src/model/presence.dart'; export 'src/model/presence_content.dart'; -export 'src/model/profile.dart'; -export 'src/model/public_rooms_response.dart'; -export 'src/model/push_rule_set.dart'; -export 'src/model/pusher.dart'; export 'src/model/request_token_response.dart'; -export 'src/model/room_alias_information.dart'; export 'src/model/room_creation_types.dart'; -export 'src/model/room_keys_info.dart'; export 'src/model/room_keys_keys.dart'; export 'src/model/room_summary.dart'; -export 'src/model/server_capabilities.dart'; export 'src/model/stripped_state_event.dart'; export 'src/model/supported_protocol.dart'; -export 'src/model/supported_versions.dart'; export 'src/model/sync_update.dart'; -export 'src/model/tag.dart'; -export 'src/model/third_party_identifier.dart'; export 'src/model/third_party_location.dart'; export 'src/model/third_party_user.dart'; -export 'src/model/timeline_history_response.dart'; -export 'src/model/turn_server_credentials.dart'; export 'src/model/upload_key_signatures_response.dart'; -export 'src/model/user_search_result.dart'; -export 'src/model/well_known_information.dart'; -export 'src/model/who_is_info.dart'; export 'src/model/auth/authentication_data.dart'; export 'src/model/auth/authentication_identifier.dart'; export 'src/model/auth/authentication_password.dart'; diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart new file mode 100644 index 00000000..87a8ad4f --- /dev/null +++ b/lib/src/generated/api.dart @@ -0,0 +1,3553 @@ +import '../model/auth/authentication_data.dart'; +import '../model/auth/authentication_types.dart'; +import '../model/auth/authentication_identifier.dart'; +import '../model/matrix_keys.dart'; +import '../model/sync_update.dart'; +import '../model/matrix_event.dart'; + +import 'model.dart'; +import 'fixed_model.dart'; +import 'internal.dart'; + +import 'package:http/http.dart'; +import 'dart:convert'; +import 'dart:typed_data'; + +class Api { + Client httpClient; + Uri? baseUri; + String? bearerToken; + Api({Client? httpClient, this.baseUri, this.bearerToken}) + : httpClient = httpClient ?? Client(); + Never unexpectedResponse(BaseResponse response, Uint8List body) { + throw Exception('http error response'); + } + + /// Gets discovery information about the domain. The file may include + /// additional keys, which MUST follow the Java package naming convention, + /// e.g. `com.example.myapp.property`. This ensures property names are + /// suitably namespaced for each application and reduces the risk of + /// clashes. + /// + /// Note that this endpoint is not necessarily handled by the homeserver, + /// but by another webserver, to be used for discovering the homeserver URL. + Future getWellknown() async { + final requestUri = Uri(path: '.well-known/matrix/client'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return DiscoveryInformation.fromJson(json); + } + + /// Gets a list of the third party identifiers that the homeserver has + /// associated with the user's account. + /// + /// This is *not* the same as the list of third party identifiers bound to + /// the user's Matrix ID in identity servers. + /// + /// Identifiers in this list may be used by the homeserver as, for example, + /// identifiers that it will accept to reset the user's account password. + /// + /// returns `threepids` + Future?> getAccount3PIDs() async { + final requestUri = Uri(path: '_matrix/client/r0/account/3pid'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as List).map((v) => ThirdPartyIdentifier.fromJson(v)).toList() + : null)(json['threepids']); + } + + /// Adds contact information to the user's account. + /// + /// This endpoint is deprecated in favour of the more specific `/3pid/add` + /// and `/3pid/bind` endpoints. + /// + /// **Note:** + /// Previously this endpoint supported a `bind` parameter. This parameter + /// has been removed, making this endpoint behave as though it was `false`. + /// This results in this endpoint being an equivalent to `/3pid/bind` rather + /// than dual-purpose. + /// + /// [threePidCreds] The third party credentials to associate with the account. + @deprecated + Future post3PIDs(ThreePidCredentials threePidCreds) async { + final requestUri = Uri(path: '_matrix/client/r0/account/3pid'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'three_pid_creds': threePidCreds.toJson(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return null; + } + + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api). + /// + /// Adds contact information to the user's account. Homeservers should use 3PIDs added + /// through this endpoint for password resets instead of relying on the identity server. + /// + /// Homeservers should prevent the caller from adding a 3PID to their account if it has + /// already been added to another user's account on the homeserver. + /// + /// [auth] Additional authentication information for the + /// user-interactive authentication API. + /// + /// [clientSecret] The client secret used in the session with the homeserver. + /// + /// [sid] The session identifier given by the homeserver. + Future add3PID(String clientSecret, String sid, + {AuthenticationData? auth}) async { + final requestUri = Uri(path: '_matrix/client/r0/account/3pid/add'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (auth != null) 'auth': auth.toJson(), + 'client_secret': clientSecret, + 'sid': sid, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Binds a 3PID to the user's account through the specified identity server. + /// + /// Homeservers should not prevent this request from succeeding if another user + /// has bound the 3PID. Homeservers should simply proxy any errors received by + /// the identity server to the caller. + /// + /// Homeservers should track successful binds so they can be unbound later. + /// + /// [clientSecret] The client secret used in the session with the identity server. + /// + /// [idAccessToken] An access token previously registered with the identity server. + /// + /// [idServer] The identity server to use. + /// + /// [sid] The session identifier given by the identity server. + Future bind3PID(String clientSecret, String idAccessToken, + String idServer, String sid) async { + final requestUri = Uri(path: '_matrix/client/r0/account/3pid/bind'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'id_access_token': idAccessToken, + 'id_server': idServer, + 'sid': sid, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Removes a third party identifier from the user's account. This might not + /// cause an unbind of the identifier from the identity server. + /// + /// Unlike other endpoints, this endpoint does not take an `id_access_token` + /// parameter because the homeserver is expected to sign the request to the + /// identity server instead. + /// + /// [address] The third party address being removed. + /// + /// [idServer] The identity server to unbind from. If not provided, the homeserver + /// MUST use the `id_server` the identifier was added through. If the + /// homeserver does not know the original `id_server`, it MUST return + /// a `id_server_unbind_result` of `no-support`. + /// + /// [medium] The medium of the third party identifier being removed. + /// + /// returns `id_server_unbind_result`: + /// An indicator as to whether or not the homeserver was able to unbind + /// the 3PID from the identity server. `success` indicates that the + /// indentity server has unbound the identifier whereas `no-support` + /// indicates that the identity server refuses to support the request + /// or the homeserver was not able to determine an identity server to + /// unbind from. + Future delete3pidFromAccount( + String address, ThirdPartyIdentifierMedium medium, + {String? idServer}) async { + final requestUri = Uri(path: '_matrix/client/r0/account/3pid/delete'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'address': address, + if (idServer != null) 'id_server': idServer, + 'medium': { + ThirdPartyIdentifierMedium.email: 'email', + ThirdPartyIdentifierMedium.msisdn: 'msisdn' + }[medium]!, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return { + 'no-support': IdServerUnbindResult.noSupport, + 'success': IdServerUnbindResult.success + }[json['id_server_unbind_result']]!; + } + + /// Removes a user's third party identifier from the provided identity server + /// without removing it from the homeserver. + /// + /// Unlike other endpoints, this endpoint does not take an `id_access_token` + /// parameter because the homeserver is expected to sign the request to the + /// identity server instead. + /// + /// [address] The third party address being removed. + /// + /// [idServer] The identity server to unbind from. If not provided, the homeserver + /// MUST use the `id_server` the identifier was added through. If the + /// homeserver does not know the original `id_server`, it MUST return + /// a `id_server_unbind_result` of `no-support`. + /// + /// [medium] The medium of the third party identifier being removed. + /// + /// returns `id_server_unbind_result`: + /// An indicator as to whether or not the identity server was able to unbind + /// the 3PID. `success` indicates that the identity server has unbound the + /// identifier whereas `no-support` indicates that the identity server + /// refuses to support the request or the homeserver was not able to determine + /// an identity server to unbind from. + Future unbind3pidFromAccount( + String address, ThirdPartyIdentifierMedium medium, + {String? idServer}) async { + final requestUri = Uri(path: '_matrix/client/r0/account/3pid/unbind'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'address': address, + if (idServer != null) 'id_server': idServer, + 'medium': { + ThirdPartyIdentifierMedium.email: 'email', + ThirdPartyIdentifierMedium.msisdn: 'msisdn' + }[medium]!, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return { + 'no-support': IdServerUnbindResult.noSupport, + 'success': IdServerUnbindResult.success + }[json['id_server_unbind_result']]!; + } + + /// Deactivate the user's account, removing all ability for the user to + /// login again. + /// + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api). + /// + /// An access token should be submitted to this endpoint if the client has + /// an active session. + /// + /// The homeserver may change the flows available depending on whether a + /// valid access token is provided. + /// + /// Unlike other endpoints, this endpoint does not take an `id_access_token` + /// parameter because the homeserver is expected to sign the request to the + /// identity server instead. + /// + /// [auth] Additional authentication information for the user-interactive authentication API. + /// + /// [idServer] The identity server to unbind all of the user's 3PIDs from. + /// If not provided, the homeserver MUST use the `id_server` + /// that was originally use to bind each identifier. If the + /// homeserver does not know which `id_server` that was, + /// it must return an `id_server_unbind_result` of + /// `no-support`. + /// + /// returns `id_server_unbind_result`: + /// An indicator as to whether or not the homeserver was able to unbind + /// the user's 3PIDs from the identity server(s). `success` indicates + /// that all identifiers have been unbound from the identity server while + /// `no-support` indicates that one or more identifiers failed to unbind + /// due to the identity server refusing the request or the homeserver + /// being unable to determine an identity server to unbind from. This + /// must be `success` if the homeserver has no identifiers to unbind + /// for the user. + Future deactivateAccount( + {AuthenticationData? auth, String? idServer}) async { + final requestUri = Uri(path: '_matrix/client/r0/account/deactivate'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (auth != null) 'auth': auth.toJson(), + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return { + 'no-support': IdServerUnbindResult.noSupport, + 'success': IdServerUnbindResult.success + }[json['id_server_unbind_result']]!; + } + + /// Changes the password for an account on this homeserver. + /// + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api) to + /// ensure the user changing the password is actually the owner of the + /// account. + /// + /// An access token should be submitted to this endpoint if the client has + /// an active session. + /// + /// The homeserver may change the flows available depending on whether a + /// valid access token is provided. The homeserver SHOULD NOT revoke the + /// access token provided in the request. Whether other access tokens for + /// the user are revoked depends on the request parameters. + /// + /// [auth] Additional authentication information for the user-interactive authentication API. + /// + /// [logoutDevices] Whether the user's other access tokens, and their associated devices, should be + /// revoked if the request succeeds. Defaults to true. + /// + /// When `false`, the server can still take advantage of the [soft logout method](https://spec.matrix.org/unstable/client-server-api/#soft-logout) + /// for the user's remaining devices. + /// + /// [newPassword] The new password for the account. + Future changePassword(String newPassword, + {AuthenticationData? auth, bool? logoutDevices}) async { + final requestUri = Uri(path: '_matrix/client/r0/account/password'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (auth != null) 'auth': auth.toJson(), + if (logoutDevices != null) 'logout_devices': logoutDevices, + 'new_password': newPassword, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Gets information about the owner of a given access token. + /// + /// Note that, as with the rest of the Client-Server API, + /// Application Services may masquerade as users within their + /// namespace by giving a `user_id` query parameter. In this + /// situation, the server should verify that the given `user_id` + /// is registered by the appservice, and return it in the response + /// body. + Future getTokenOwner() async { + final requestUri = Uri(path: '_matrix/client/r0/account/whoami'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return TokenOwnerInfo.fromJson(json); + } + + /// Gets information about a particular user. + /// + /// This API may be restricted to only be called by the user being looked + /// up, or by a server admin. Server-local administrator privileges are not + /// specified in this document. + /// + /// [userId] The user to look up. + Future getWhoIs(String userId) async { + final requestUri = Uri( + path: '_matrix/client/r0/admin/whois/${Uri.encodeComponent(userId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return WhoIsInfo.fromJson(json); + } + + /// Gets information about the server's supported feature set + /// and other relevant capabilities. + /// + /// returns `capabilities`: + /// The custom capabilities the server supports, using the + /// Java package naming convention. + Future getCapabilities() async { + final requestUri = Uri(path: '_matrix/client/r0/capabilities'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return Capabilities.fromJson(json['capabilities']); + } + + /// Create a new room with various configuration options. + /// + /// The server MUST apply the normal state resolution rules when creating + /// the new room, including checking power levels for each event. It MUST + /// apply the events implied by the request in the following order: + /// + /// 1. The `m.room.create` event itself. Must be the first event in the + /// room. + /// + /// 2. An `m.room.member` event for the creator to join the room. This is + /// needed so the remaining events can be sent. + /// + /// 3. A default `m.room.power_levels` event, giving the room creator + /// (and not other members) permission to send state events. Overridden + /// by the `power_level_content_override` parameter. + /// + /// 4. Events set by the `preset`. Currently these are the `m.room.join_rules`, + /// `m.room.history_visibility`, and `m.room.guest_access` state events. + /// + /// 5. Events listed in `initial_state`, in the order that they are + /// listed. + /// + /// 6. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` + /// state events). + /// + /// 7. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with + /// `membership: invite` and `m.room.third_party_invite`). + /// + /// The available presets do the following with respect to room state: + /// + /// | Preset | `join_rules` | `history_visibility` | `guest_access` | Other | + /// |------------------------|--------------|----------------------|----------------|-------| + /// | `private_chat` | `invite` | `shared` | `can_join` | | + /// | `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. | + /// | `public_chat` | `public` | `shared` | `forbidden` | | + /// + /// The server will create a `m.room.create` event in the room with the + /// requesting user as the creator, alongside other keys provided in the + /// `creation_content`. + /// + /// [creationContent] Extra keys, such as `m.federate`, to be added to the content + /// of the [`m.room.create`](client-server-api/#mroomcreate) event. The server will clobber the following + /// keys: `creator`, `room_version`. Future versions of the specification + /// may allow the server to clobber other keys. + /// + /// [initialState] A list of state events to set in the new room. This allows + /// the user to override the default state events set in the new + /// room. The expected format of the state events are an object + /// with type, state_key and content keys set. + /// + /// Takes precedence over events set by `preset`, but gets + /// overriden by `name` and `topic` keys. + /// + /// [invite] A list of user IDs to invite to the room. This will tell the + /// server to invite everyone in the list to the newly created room. + /// + /// [invite3pid] A list of objects representing third party IDs to invite into + /// the room. + /// + /// [isDirect] This flag makes the server set the `is_direct` flag on the + /// `m.room.member` events sent to the users in `invite` and + /// `invite_3pid`. See [Direct Messaging](https://spec.matrix.org/unstable/client-server-api/#direct-messaging) for more information. + /// + /// [name] If this is included, an `m.room.name` event will be sent + /// into the room to indicate the name of the room. See Room + /// Events for more information on `m.room.name`. + /// + /// [powerLevelContentOverride] The power level content to override in the default power level + /// event. This object is applied on top of the generated + /// [`m.room.power_levels`](client-server-api/#mroompower_levels) + /// event content prior to it being sent to the room. Defaults to + /// overriding nothing. + /// + /// [preset] Convenience parameter for setting various default state events + /// based on a preset. + /// + /// If unspecified, the server should use the `visibility` to determine + /// which preset to use. A visbility of `public` equates to a preset of + /// `public_chat` and `private` visibility equates to a preset of + /// `private_chat`. + /// + /// [roomAliasName] The desired room alias **local part**. If this is included, a + /// room alias will be created and mapped to the newly created + /// room. The alias will belong on the *same* homeserver which + /// created the room. For example, if this was set to "foo" and + /// sent to the homeserver "example.com" the complete room alias + /// would be `#foo:example.com`. + /// + /// The complete room alias will become the canonical alias for + /// the room. + /// + /// [roomVersion] The room version to set for the room. If not provided, the homeserver is + /// to use its configured default. If provided, the homeserver will return a + /// 400 error with the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not + /// support the room version. + /// + /// [topic] If this is included, an `m.room.topic` event will be sent + /// into the room to indicate the topic for the room. See Room + /// Events for more information on `m.room.topic`. + /// + /// [visibility] A `public` visibility indicates that the room will be shown + /// in the published room list. A `private` visibility will hide + /// the room from the published room list. Rooms default to + /// `private` visibility if this key is not included. NB: This + /// should not be confused with `join_rules` which also uses the + /// word `public`. + /// + /// returns `room_id`: + /// The created room's ID. + Future createRoom( + {Map? creationContent, + List? initialState, + List? invite, + List? invite3pid, + bool? isDirect, + String? name, + Map? powerLevelContentOverride, + CreateRoomPreset? preset, + String? roomAliasName, + String? roomVersion, + String? topic, + Visibility? visibility}) async { + final requestUri = Uri(path: '_matrix/client/r0/createRoom'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (creationContent != null) 'creation_content': creationContent, + if (initialState != null) + 'initial_state': initialState.map((v) => v.toJson()).toList(), + if (invite != null) 'invite': invite.map((v) => v).toList(), + if (invite3pid != null) + 'invite_3pid': invite3pid.map((v) => v.toJson()).toList(), + if (isDirect != null) 'is_direct': isDirect, + if (name != null) 'name': name, + if (powerLevelContentOverride != null) + 'power_level_content_override': powerLevelContentOverride, + if (preset != null) + 'preset': { + CreateRoomPreset.privateChat: 'private_chat', + CreateRoomPreset.publicChat: 'public_chat', + CreateRoomPreset.trustedPrivateChat: 'trusted_private_chat' + }[preset]!, + if (roomAliasName != null) 'room_alias_name': roomAliasName, + if (roomVersion != null) 'room_version': roomVersion, + if (topic != null) 'topic': topic, + if (visibility != null) + 'visibility': { + Visibility.public: 'public', + Visibility.private: 'private' + }[visibility]!, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['room_id'] as String; + } + + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api). + /// + /// Deletes the given devices, and invalidates any access token associated with them. + /// + /// [auth] Additional authentication information for the + /// user-interactive authentication API. + /// + /// [devices] The list of device IDs to delete. + Future deleteDevices(List devices, + {AuthenticationData? auth}) async { + final requestUri = Uri(path: '_matrix/client/r0/delete_devices'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (auth != null) 'auth': auth.toJson(), + 'devices': devices.map((v) => v).toList(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Gets information about all devices for the current user. + /// + /// returns `devices`: + /// A list of all registered devices for this user. + Future?> getDevices() async { + final requestUri = Uri(path: '_matrix/client/r0/devices'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as List).map((v) => Device.fromJson(v)).toList() + : null)(json['devices']); + } + + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api). + /// + /// Deletes the given device, and invalidates any access token associated with it. + /// + /// [deviceId] The device to delete. + /// + /// [auth] Additional authentication information for the + /// user-interactive authentication API. + Future deleteDevice(String deviceId, {AuthenticationData? auth}) async { + final requestUri = + Uri(path: '_matrix/client/r0/devices/${Uri.encodeComponent(deviceId)}'); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (auth != null) 'auth': auth.toJson(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Gets information on a single device, by device id. + /// + /// [deviceId] The device to retrieve. + Future getDevice(String deviceId) async { + final requestUri = + Uri(path: '_matrix/client/r0/devices/${Uri.encodeComponent(deviceId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return Device.fromJson(json); + } + + /// Updates the metadata on the given device. + /// + /// [deviceId] The device to update. + /// + /// [displayName] The new display name for this device. If not given, the + /// display name is unchanged. + Future updateDevice(String deviceId, {String? displayName}) async { + final requestUri = + Uri(path: '_matrix/client/r0/devices/${Uri.encodeComponent(deviceId)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (displayName != null) 'display_name': displayName, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Updates the visibility of a given room on the application service's room + /// directory. + /// + /// This API is similar to the room directory visibility API used by clients + /// to update the homeserver's more general room directory. + /// + /// This API requires the use of an application service access token (`as_token`) + /// instead of a typical client's access_token. This API cannot be invoked by + /// users who are not identified as application services. + /// + /// [networkId] The protocol (network) ID to update the room list for. This would + /// have been provided by the application service as being listed as + /// a supported protocol. + /// + /// [roomId] The room ID to add to the directory. + /// + /// [visibility] Whether the room should be visible (public) in the directory + /// or not (private). + Future> updateAppserviceRoomDirectoryVisibility( + String networkId, String roomId, Visibility visibility) async { + final requestUri = Uri( + path: + '_matrix/client/r0/directory/list/appservice/${Uri.encodeComponent(networkId)}/${Uri.encodeComponent(roomId)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'visibility': { + Visibility.public: 'public', + Visibility.private: 'private' + }[visibility]!, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json as Map; + } + + /// Remove a mapping of room alias to room ID. + /// + /// Servers may choose to implement additional access control checks here, for instance that + /// room aliases can only be deleted by their creator or a server administrator. + /// + /// **Note:** + /// Servers may choose to update the `alt_aliases` for the `m.room.canonical_alias` + /// state event in the room when an alias is removed. Servers which choose to update the + /// canonical alias event are recommended to, in addition to their other relevant permission + /// checks, delete the alias and return a successful response even if the user does not + /// have permission to update the `m.room.canonical_alias` event. + /// + /// [roomAlias] The room alias to remove. + Future deleteRoomAlias(String roomAlias) async { + final requestUri = Uri( + path: + '_matrix/client/r0/directory/room/${Uri.encodeComponent(roomAlias)}'); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Requests that the server resolve a room alias to a room ID. + /// + /// The server will use the federation API to resolve the alias if the + /// domain part of the alias does not correspond to the server's own + /// domain. + /// + /// [roomAlias] The room alias. + Future getRoomIdByAlias(String roomAlias) async { + final requestUri = Uri( + path: + '_matrix/client/r0/directory/room/${Uri.encodeComponent(roomAlias)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetRoomIdByAliasResponse.fromJson(json); + } + + /// setRoomAlias + /// + /// [roomAlias] The room alias to set. + /// + /// [roomId] The room ID to set. + Future setRoomAlias(String roomAlias, String roomId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/directory/room/${Uri.encodeComponent(roomAlias)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'room_id': roomId, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Get a single event based on `event_id`. You must have permission to + /// retrieve this event e.g. by being a member in the room for this event. + /// + /// This endpoint was deprecated in r0 of this specification. Clients + /// should instead call the + /// [/rooms/{roomId}/event/{eventId}](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0roomsroomideventeventid) API + /// or the [/rooms/{roomId}/context/{eventId](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0roomsroomidcontexteventid) API. + /// + /// [eventId] The event ID to get. + @deprecated + Future getOneEvent(String eventId) async { + final requestUri = + Uri(path: '_matrix/client/r0/events/${Uri.encodeComponent(eventId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return MatrixEvent.fromJson(json); + } + + /// *Note that this API takes either a room ID or alias, unlike* `/room/{roomId}/join`. + /// + /// This API starts a user participating in a particular room, if that user + /// is allowed to participate in that room. After this call, the client is + /// allowed to see all current state events in the room, and all subsequent + /// events associated with the room until the user leaves the room. + /// + /// After a user has joined a room, the room will appear as an entry in the + /// response of the [`/initialSync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0initialsync) + /// and [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) APIs. + /// + /// [roomIdOrAlias] The room identifier or alias to join. + /// + /// [serverName] The servers to attempt to join the room through. One of the servers + /// must be participating in the room. + /// + /// [reason] Optional reason to be included as the `reason` on the subsequent + /// membership event. + /// + /// [thirdPartySigned] If a `third_party_signed` was supplied, the homeserver must verify + /// that it matches a pending `m.room.third_party_invite` event in the + /// room, and perform key validity checking if required by the event. + /// + /// returns `room_id`: + /// The joined room ID. + Future joinRoom(String roomIdOrAlias, + {List? serverName, + String? reason, + ThirdPartySigned? thirdPartySigned}) async { + final requestUri = Uri( + path: '_matrix/client/r0/join/${Uri.encodeComponent(roomIdOrAlias)}', + queryParameters: { + if (serverName != null) + 'server_name': serverName.map((v) => v).toList(), + }); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + if (thirdPartySigned != null) + 'third_party_signed': thirdPartySigned.toJson(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['room_id'] as String; + } + + /// This API returns a list of the user's current rooms. + /// + /// returns `joined_rooms`: + /// The ID of each room in which the user has `joined` membership. + Future> getJoinedRooms() async { + final requestUri = Uri(path: '_matrix/client/r0/joined_rooms'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json['joined_rooms'] as List).map((v) => v as String).toList(); + } + + /// Gets a list of users who have updated their device identity keys since a + /// previous sync token. + /// + /// The server should include in the results any users who: + /// + /// * currently share a room with the calling user (ie, both users have + /// membership state `join`); *and* + /// * added new device identity keys or removed an existing device with + /// identity keys, between `from` and `to`. + /// + /// [from] The desired start point of the list. Should be the `next_batch` field + /// from a response to an earlier call to [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync). Users who have not + /// uploaded new device identity keys since this point, nor deleted + /// existing devices with identity keys since then, will be excluded + /// from the results. + /// + /// [to] The desired end point of the list. Should be the `next_batch` + /// field from a recent call to [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) - typically the most recent + /// such call. This may be used by the server as a hint to check its + /// caches are up to date. + Future getKeysChanges(String from, String to) async { + final requestUri = + Uri(path: '_matrix/client/r0/keys/changes', queryParameters: { + 'from': from, + 'to': to, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetKeysChangesResponse.fromJson(json); + } + + /// Claims one-time keys for use in pre-key messages. + /// + /// [oneTimeKeys] The keys to be claimed. A map from user ID, to a map from + /// device ID to algorithm name. + /// + /// [timeout] The time (in milliseconds) to wait when downloading keys from + /// remote servers. 10 seconds is the recommended default. + Future claimKeys( + Map> oneTimeKeys, + {int? timeout}) async { + final requestUri = Uri(path: '_matrix/client/r0/keys/claim'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'one_time_keys': oneTimeKeys + .map((k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v)))), + if (timeout != null) 'timeout': timeout, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ClaimKeysResponse.fromJson(json); + } + + /// Returns the current devices and identity keys for the given users. + /// + /// [deviceKeys] The keys to be downloaded. A map from user ID, to a list of + /// device IDs, or to an empty list to indicate all devices for the + /// corresponding user. + /// + /// [timeout] The time (in milliseconds) to wait when downloading keys from + /// remote servers. 10 seconds is the recommended default. + /// + /// [token] 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. + Future queryKeys(Map> deviceKeys, + {int? timeout, String? token}) async { + final requestUri = Uri(path: '_matrix/client/r0/keys/query'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'device_keys': + deviceKeys.map((k, v) => MapEntry(k, v.map((v) => v).toList())), + if (timeout != null) 'timeout': timeout, + if (token != null) 'token': token, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return QueryKeysResponse.fromJson(json); + } + + /// *Note that this API takes either a room ID or alias, unlike other membership APIs.* + /// + /// This API "knocks" on the room to ask for permission to join, if the user + /// is allowed to knock on the room. Acceptance of the knock happens out of + /// band from this API, meaning that the client will have to watch for updates + /// regarding the acceptance/rejection of the knock. + /// + /// If the room history settings allow, the user will still be able to see + /// history of the room while being in the "knock" state. The user will have + /// to accept the invitation to join the room (acceptance of knock) to see + /// messages reliably. See the `/join` endpoints for more information about + /// history visibility to the user. + /// + /// The knock will appear as an entry in the response of the + /// [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) API. + /// + /// [roomIdOrAlias] The room identifier or alias to knock upon. + /// + /// [serverName] The servers to attempt to knock on the room through. One of the servers + /// must be participating in the room. + /// + /// [reason] Optional reason to be included as the `reason` on the subsequent + /// membership event. + /// + /// returns `room_id`: + /// The knocked room ID. + Future knockRoom(String roomIdOrAlias, + {List? serverName, String? reason}) async { + final requestUri = Uri( + path: '_matrix/client/r0/knock/${Uri.encodeComponent(roomIdOrAlias)}', + queryParameters: { + if (serverName != null) + 'server_name': serverName.map((v) => v).toList(), + }); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['room_id'] as String; + } + + /// Gets the homeserver's supported login types to authenticate users. Clients + /// should pick one of these and supply it as the `type` when logging in. + /// + /// returns `flows`: + /// The homeserver's supported login types + Future?> getLoginFlows() async { + final requestUri = Uri(path: '_matrix/client/r0/login'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as List).map((v) => LoginFlow.fromJson(v)).toList() + : null)(json['flows']); + } + + /// Authenticates the user, and issues an access token they can + /// use to authorize themself in subsequent requests. + /// + /// If the client does not supply a `device_id`, the server must + /// auto-generate one. + /// + /// The returned access token must be associated with the `device_id` + /// supplied by the client or generated by the server. The server may + /// invalidate any access token previously associated with that device. See + /// [Relationship between access tokens and devices](https://spec.matrix.org/unstable/client-server-api/#relationship-between-access-tokens-and-devices). + /// + /// [address] Third party identifier for the user. Deprecated in favour of `identifier`. + /// + /// [deviceId] ID of the client device. If this does not correspond to a + /// known client device, a new device will be created. The given + /// device ID must not be the same as a + /// [cross-signing](https://spec.matrix.org/unstable/client-server-api/#cross-signing) key ID. + /// The server will auto-generate a device_id + /// if this is not specified. + /// + /// [identifier] Identification information for a user + /// + /// [initialDeviceDisplayName] A display name to assign to the newly-created device. Ignored + /// if `device_id` corresponds to a known device. + /// + /// [medium] When logging in using a third party identifier, the medium of the identifier. Must be 'email'. Deprecated in favour of `identifier`. + /// + /// [password] Required when `type` is `m.login.password`. The user's + /// password. + /// + /// [token] Required when `type` is `m.login.token`. Part of Token-based login. + /// + /// [type] The login type being used. + /// + /// [user] The fully qualified user ID or just local part of the user ID, to log in. Deprecated in favour of `identifier`. + Future login(LoginType type, + {String? address, + String? deviceId, + AuthenticationIdentifier? identifier, + String? initialDeviceDisplayName, + String? medium, + String? password, + String? token, + String? user}) async { + final requestUri = Uri(path: '_matrix/client/r0/login'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (address != null) 'address': address, + if (deviceId != null) 'device_id': deviceId, + if (identifier != null) 'identifier': identifier.toJson(), + if (initialDeviceDisplayName != null) + 'initial_device_display_name': initialDeviceDisplayName, + if (medium != null) 'medium': medium, + if (password != null) 'password': password, + if (token != null) 'token': token, + 'type': { + LoginType.mLoginPassword: 'm.login.password', + LoginType.mLoginToken: 'm.login.token' + }[type]!, + if (user != null) 'user': user, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return LoginResponse.fromJson(json); + } + + /// Invalidates an existing access token, so that it can no longer be used for + /// authorization. The device associated with the access token is also deleted. + /// [Device keys](https://spec.matrix.org/unstable/client-server-api/#device-keys) for the device are deleted alongside the device. + Future logout() async { + final requestUri = Uri(path: '_matrix/client/r0/logout'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Invalidates all access tokens for a user, so that they can no longer be used for + /// authorization. This includes the access token that made this request. All devices + /// for the user are also deleted. [Device keys](https://spec.matrix.org/unstable/client-server-api/#device-keys) for the device are + /// deleted alongside the device. + /// + /// This endpoint does not use the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api) because + /// User-Interactive Authentication is designed to protect against attacks where the + /// someone gets hold of a single access token then takes over the account. This + /// endpoint invalidates all access tokens for the user, including the token used in + /// the request, and therefore the attacker is unable to take over the account in + /// this way. + Future logoutAll() async { + final requestUri = Uri(path: '_matrix/client/r0/logout/all'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// This API is used to paginate through the list of events that the + /// user has been, or would have been notified about. + /// + /// [from] Pagination token given to retrieve the next set of events. + /// + /// [limit] Limit on the number of events to return in this request. + /// + /// [only] Allows basic filtering of events returned. Supply `highlight` + /// to return only events where the notification had the highlight + /// tweak set. + Future getNotifications( + {String? from, int? limit, String? only}) async { + final requestUri = + Uri(path: '_matrix/client/r0/notifications', queryParameters: { + if (from != null) 'from': from, + if (limit != null) 'limit': limit.toString(), + if (only != null) 'only': only, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetNotificationsResponse.fromJson(json); + } + + /// Get the given user's presence state. + /// + /// [userId] The user whose presence state to get. + Future getPresence(String userId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/presence/${Uri.encodeComponent(userId)}/status'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetPresenceResponse.fromJson(json); + } + + /// This API sets the given user's presence state. When setting the status, + /// the activity time is updated to reflect that activity; the client does + /// not need to specify the `last_active_ago` field. You cannot set the + /// presence state of another user. + /// + /// [userId] The user whose presence state to update. + /// + /// [presence] The new presence state. + /// + /// [statusMsg] The status message to attach to this state. + Future setPresence(String userId, PresenceType presence, + {String? statusMsg}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/presence/${Uri.encodeComponent(userId)}/status'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'presence': { + PresenceType.online: 'online', + PresenceType.offline: 'offline', + PresenceType.unavailable: 'unavailable' + }[presence]!, + if (statusMsg != null) 'status_msg': statusMsg, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Get the combined profile information for this user. This API may be used + /// to fetch the user's own profile information or other users; either + /// locally or on remote homeservers. This API may return keys which are not + /// limited to `displayname` or `avatar_url`. + /// + /// [userId] The user whose profile information to get. + Future getUserProfile(String userId) async { + final requestUri = + Uri(path: '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ProfileInformation.fromJson(json); + } + + /// Get the user's avatar URL. This API may be used to fetch the user's + /// own avatar URL or to query the URL of other users; either locally or + /// on remote homeservers. + /// + /// [userId] The user whose avatar URL to get. + /// + /// returns `avatar_url`: + /// The user's avatar URL if they have set one, otherwise not present. + Future getAvatarUrl(String userId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']); + } + + /// This API sets the given user's avatar URL. You must have permission to + /// set this user's avatar URL, e.g. you need to have their `access_token`. + /// + /// [userId] The user whose avatar URL to set. + /// + /// [avatarUrl] The new avatar URL for this user. + Future setAvatarUrl(String userId, Uri? avatarUrl) async { + final requestUri = Uri( + path: + '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Get the user's display name. This API may be used to fetch the user's + /// own displayname or to query the name of other users; either locally or + /// on remote homeservers. + /// + /// [userId] The user whose display name to get. + /// + /// returns `displayname`: + /// The user's display name if they have set one, otherwise not present. + Future getDisplayName(String userId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}/displayname'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null ? v as String : null)(json['displayname']); + } + + /// This API sets the given user's display name. You must have permission to + /// set this user's display name, e.g. you need to have their `access_token`. + /// + /// [userId] The user whose display name to set. + /// + /// [displayname] The new display name for this user. + Future setDisplayName(String userId, String? displayname) async { + final requestUri = Uri( + path: + '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}/displayname'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (displayname != null) 'displayname': displayname, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Lists the public rooms on the server. + /// + /// This API returns paginated responses. The rooms are ordered by the number + /// of joined members, with the largest rooms first. + /// + /// [limit] Limit the number of results returned. + /// + /// [since] A pagination token from a previous request, allowing clients to + /// get the next (or previous) batch of rooms. + /// The direction of pagination is specified solely by which token + /// is supplied, rather than via an explicit flag. + /// + /// [server] The server to fetch the public room lists from. Defaults to the + /// local server. + Future getPublicRooms( + {int? limit, String? since, String? server}) async { + final requestUri = + Uri(path: '_matrix/client/r0/publicRooms', queryParameters: { + if (limit != null) 'limit': limit.toString(), + if (since != null) 'since': since, + if (server != null) 'server': server, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetPublicRoomsResponse.fromJson(json); + } + + /// Lists the public rooms on the server, with optional filter. + /// + /// This API returns paginated responses. The rooms are ordered by the number + /// of joined members, with the largest rooms first. + /// + /// [server] The server to fetch the public room lists from. Defaults to the + /// local server. + /// + /// [filter] Filter to apply to the results. + /// + /// [includeAllNetworks] Whether or not to include all known networks/protocols from + /// application services on the homeserver. Defaults to false. + /// + /// [limit] Limit the number of results returned. + /// + /// [since] A pagination token from a previous request, allowing clients + /// to get the next (or previous) batch of rooms. The direction + /// of pagination is specified solely by which token is supplied, + /// rather than via an explicit flag. + /// + /// [thirdPartyInstanceId] The specific third party network/protocol to request from the + /// homeserver. Can only be used if `include_all_networks` is false. + Future queryPublicRooms( + {String? server, + PublicRoomQueryFilter? filter, + bool? includeAllNetworks, + int? limit, + String? since, + String? thirdPartyInstanceId}) async { + final requestUri = + Uri(path: '_matrix/client/r0/publicRooms', queryParameters: { + if (server != null) 'server': server, + }); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (filter != null) 'filter': filter.toJson(), + if (includeAllNetworks != null) + 'include_all_networks': includeAllNetworks, + if (limit != null) 'limit': limit, + if (since != null) 'since': since, + if (thirdPartyInstanceId != null) + 'third_party_instance_id': thirdPartyInstanceId, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return QueryPublicRoomsResponse.fromJson(json); + } + + /// Gets all currently active pushers for the authenticated user. + /// + /// returns `pushers`: + /// An array containing the current pushers for the user + Future?> getPushers() async { + final requestUri = Uri(path: '_matrix/client/r0/pushers'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as List).map((v) => Pusher.fromJson(v)).toList() + : null)(json['pushers']); + } + + /// Retrieve all push rulesets for this user. Clients can "drill-down" on + /// the rulesets by suffixing a `scope` to this path e.g. + /// `/pushrules/global/`. This will return a subset of this data under the + /// specified key e.g. the `global` key. + /// + /// returns `global`: + /// The global ruleset. + Future getPushRules() async { + final requestUri = Uri(path: '_matrix/client/r0/pushrules'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return PushRuleSet.fromJson(json['global']); + } + + /// This endpoint removes the push rule defined in the path. + /// + /// [scope] `global` to specify global rules. + /// + /// [kind] The kind of rule + /// + /// + /// [ruleId] The identifier for the rule. + /// + Future deletePushRule( + String scope, PushRuleKind kind, String ruleId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ + PushRuleKind.override: 'override', + PushRuleKind.underride: 'underride', + PushRuleKind.sender: 'sender', + PushRuleKind.room: 'room', + PushRuleKind.content: 'content' + }[kind]!)}/${Uri.encodeComponent(ruleId)}'); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Retrieve a single specified push rule. + /// + /// [scope] `global` to specify global rules. + /// + /// [kind] The kind of rule + /// + /// + /// [ruleId] The identifier for the rule. + /// + Future getPushRule( + String scope, PushRuleKind kind, String ruleId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ + PushRuleKind.override: 'override', + PushRuleKind.underride: 'underride', + PushRuleKind.sender: 'sender', + PushRuleKind.room: 'room', + PushRuleKind.content: 'content' + }[kind]!)}/${Uri.encodeComponent(ruleId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return PushRule.fromJson(json); + } + + /// This endpoint allows the creation, modification and deletion of pushers + /// for this user ID. The behaviour of this endpoint varies depending on the + /// values in the JSON body. + /// + /// When creating push rules, they MUST be enabled by default. + /// + /// [scope] `global` to specify global rules. + /// + /// [kind] The kind of rule + /// + /// + /// [ruleId] The identifier for the rule. + /// + /// + /// [before] Use 'before' with a `rule_id` as its value to make the new rule the + /// next-most important rule with respect to the given user defined rule. + /// It is not possible to add a rule relative to a predefined server rule. + /// + /// [after] This makes the new rule the next-less important rule relative to the + /// given user defined rule. It is not possible to add a rule relative + /// to a predefined server rule. + /// + /// [actions] The action(s) to perform when the conditions for this rule are met. + /// + /// [conditions] 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. + /// + /// [pattern] Only applicable to `content` rules. The glob-style pattern to match against. + Future setPushRule( + String scope, PushRuleKind kind, String ruleId, List actions, + {String? before, + String? after, + List? conditions, + String? pattern}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ + PushRuleKind.override: 'override', + PushRuleKind.underride: 'underride', + PushRuleKind.sender: 'sender', + PushRuleKind.room: 'room', + PushRuleKind.content: 'content' + }[kind]!)}/${Uri.encodeComponent(ruleId)}', + queryParameters: { + if (before != null) 'before': before, + if (after != null) 'after': after, + }); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'actions': actions.map((v) => v).toList(), + if (conditions != null) + 'conditions': conditions.map((v) => v.toJson()).toList(), + if (pattern != null) 'pattern': pattern, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// This endpoint get the actions for the specified push rule. + /// + /// [scope] Either `global` or `device/` to specify global + /// rules or device rules for the given `profile_tag`. + /// + /// [kind] The kind of rule + /// + /// + /// [ruleId] The identifier for the rule. + /// + /// + /// returns `actions`: + /// The action(s) to perform for this rule. + Future> getPushRuleActions( + String scope, PushRuleKind kind, String ruleId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ + PushRuleKind.override: 'override', + PushRuleKind.underride: 'underride', + PushRuleKind.sender: 'sender', + PushRuleKind.room: 'room', + PushRuleKind.content: 'content' + }[kind]!)}/${Uri.encodeComponent(ruleId)}/actions'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json['actions'] as List).map((v) => v as dynamic).toList(); + } + + /// This endpoint allows clients to change the actions of a push rule. + /// This can be used to change the actions of builtin rules. + /// + /// [scope] `global` to specify global rules. + /// + /// [kind] The kind of rule + /// + /// + /// [ruleId] The identifier for the rule. + /// + /// + /// [actions] The action(s) to perform for this rule. + Future setPushRuleActions(String scope, PushRuleKind kind, + String ruleId, List actions) async { + final requestUri = Uri( + path: + '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ + PushRuleKind.override: 'override', + PushRuleKind.underride: 'underride', + PushRuleKind.sender: 'sender', + PushRuleKind.room: 'room', + PushRuleKind.content: 'content' + }[kind]!)}/${Uri.encodeComponent(ruleId)}/actions'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'actions': actions.map((v) => v).toList(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// This endpoint gets whether the specified push rule is enabled. + /// + /// [scope] Either `global` or `device/` to specify global + /// rules or device rules for the given `profile_tag`. + /// + /// [kind] The kind of rule + /// + /// + /// [ruleId] The identifier for the rule. + /// + /// + /// returns `enabled`: + /// Whether the push rule is enabled or not. + Future isPushRuleEnabled( + String scope, PushRuleKind kind, String ruleId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ + PushRuleKind.override: 'override', + PushRuleKind.underride: 'underride', + PushRuleKind.sender: 'sender', + PushRuleKind.room: 'room', + PushRuleKind.content: 'content' + }[kind]!)}/${Uri.encodeComponent(ruleId)}/enabled'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['enabled'] as bool; + } + + /// This endpoint allows clients to enable or disable the specified push rule. + /// + /// [scope] `global` to specify global rules. + /// + /// [kind] The kind of rule + /// + /// + /// [ruleId] The identifier for the rule. + /// + /// + /// [enabled] Whether the push rule is enabled or not. + Future setPushRuleEnabled( + String scope, PushRuleKind kind, String ruleId, bool enabled) async { + final requestUri = Uri( + path: + '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ + PushRuleKind.override: 'override', + PushRuleKind.underride: 'underride', + PushRuleKind.sender: 'sender', + PushRuleKind.room: 'room', + PushRuleKind.content: 'content' + }[kind]!)}/${Uri.encodeComponent(ruleId)}/enabled'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'enabled': enabled, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api), except in + /// the cases where a guest account is being registered. + /// + /// Register for an account on this homeserver. + /// + /// There are two kinds of user account: + /// + /// - `user` accounts. These accounts may use the full API described in this specification. + /// + /// - `guest` accounts. These accounts may have limited permissions and may not be supported by all servers. + /// + /// If registration is successful, this endpoint will issue an access token + /// the client can use to authorize itself in subsequent requests. + /// + /// If the client does not supply a `device_id`, the server must + /// auto-generate one. + /// + /// The server SHOULD register an account with a User ID based on the + /// `username` provided, if any. Note that the grammar of Matrix User ID + /// localparts is restricted, so the server MUST either map the provided + /// `username` onto a `user_id` in a logical manner, or reject + /// `username`\s which do not comply to the grammar, with + /// `M_INVALID_USERNAME`. + /// + /// Matrix clients MUST NOT assume that localpart of the registered + /// `user_id` matches the provided `username`. + /// + /// The returned access token must be associated with the `device_id` + /// supplied by the client or generated by the server. The server may + /// invalidate any access token previously associated with that device. See + /// [Relationship between access tokens and devices](https://spec.matrix.org/unstable/client-server-api/#relationship-between-access-tokens-and-devices). + /// + /// When registering a guest account, all parameters in the request body + /// with the exception of `initial_device_display_name` MUST BE ignored + /// by the server. The server MUST pick a `device_id` for the account + /// regardless of input. + /// + /// Any user ID returned by this API must conform to the grammar given in the + /// [Matrix specification](https://spec.matrix.org/unstable/appendices/#user-identifiers). + /// + /// [kind] The kind of account to register. Defaults to `user`. + /// + /// [auth] 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. + /// + /// [deviceId] 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. + /// + /// [inhibitLogin] If true, an `access_token` and `device_id` should not be + /// returned from this call, therefore preventing an automatic + /// login. Defaults to false. + /// + /// [initialDeviceDisplayName] A display name to assign to the newly-created device. Ignored + /// if `device_id` corresponds to a known device. + /// + /// [password] The desired password for the account. + /// + /// [username] The basis for the localpart of the desired Matrix ID. If omitted, + /// the homeserver MUST generate a Matrix ID local part. + Future register( + {AccountKind? kind, + AuthenticationData? auth, + String? deviceId, + bool? inhibitLogin, + String? initialDeviceDisplayName, + String? password, + String? username}) async { + final requestUri = + Uri(path: '_matrix/client/r0/register', queryParameters: { + if (kind != null) + 'kind': {AccountKind.guest: 'guest', AccountKind.user: 'user'}[kind]!, + }); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (auth != null) 'auth': auth.toJson(), + if (deviceId != null) 'device_id': deviceId, + if (inhibitLogin != null) 'inhibit_login': inhibitLogin, + if (initialDeviceDisplayName != null) + 'initial_device_display_name': initialDeviceDisplayName, + if (password != null) 'password': password, + if (username != null) 'username': username, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RegisterResponse.fromJson(json); + } + + /// Checks to see if a username is available, and valid, for the server. + /// + /// The server should check to ensure that, at the time of the request, the + /// username requested is available for use. This includes verifying that an + /// application service has not claimed the username and that the username + /// fits the server's desired requirements (for example, a server could dictate + /// that it does not permit usernames with underscores). + /// + /// Matrix clients may wish to use this API prior to attempting registration, + /// however the clients must also be aware that using this API does not normally + /// reserve the username. This can mean that the username becomes unavailable + /// between checking its availability and attempting to register it. + /// + /// [username] The username to check the availability of. + /// + /// returns `available`: + /// A flag to indicate that the username is available. This should always + /// be `true` when the server replies with 200 OK. + Future checkUsernameAvailability(String username) async { + final requestUri = + Uri(path: '_matrix/client/r0/register/available', queryParameters: { + 'username': username, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null ? v as bool : null)(json['available']); + } + + /// Store several keys in the backup. + /// + /// [version] The backup in which to store the keys. Must be the current backup. + /// + /// [backupData] The backup data. + Future postRoomKeysKey( + String version, RoomKeys backupData) async { + final requestUri = + Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { + 'version': version, + }); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(backupData)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return PostRoomKeysKeyResponse.fromJson(json); + } + + /// Store a key in the backup. + /// + /// [roomId] The ID of the room that the keys are for. + /// + /// [version] The backup in which to store the keys. Must be the current backup. + /// + /// [backupData] The backup data + Future postRoomKeysKeyRoomId( + String roomId, String version, RoomKeyBackup backupData) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + queryParameters: { + 'version': version, + }); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(backupData)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return PostRoomKeysKeyRoomIdResponse.fromJson(json); + } + + /// Store a key in the backup. + /// + /// [roomId] The ID of the room that the key is for. + /// + /// [sessionId] The ID of the megolm session that the key is for. + /// + /// [version] The backup in which to store the key. Must be the current backup. + /// + /// [data] The key data. + Future postRoomKeysKeyRoomIdSessionId( + String roomId, + String sessionId, + String version, + KeyBackupData data) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + queryParameters: { + 'version': version, + }); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(data)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return PostRoomKeysKeyRoomIdSessionIdResponse.fromJson(json); + } + + /// Get information about the latest backup version. + Future getRoomKeysVersionCurrent() async { + final requestUri = Uri(path: '_matrix/client/unstable/room_keys/version'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetRoomKeysVersionCurrentResponse.fromJson(json); + } + + /// Creates a new backup. + /// + /// [algorithm] The algorithm used for storing backups. + /// + /// [authData] Algorithm-dependent data. See the documentation for the backup + /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the + /// expected format of the data. + /// + /// returns `version`: + /// The backup version. This is an opaque string. + Future postRoomKeysVersion( + BackupAlgorithm algorithm, Map authData) async { + final requestUri = Uri(path: '_matrix/client/unstable/room_keys/version'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'algorithm': { + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: + 'm.megolm_backup.v1.curve25519-aes-sha2' + }[algorithm]!, + 'auth_data': authData, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['version'] as String; + } + + /// Delete an existing key backup. Both the information about the backup, + /// as well as all key data related to the backup will be deleted. + /// + /// [version] The backup version to delete, as returned in the `version` + /// parameter in the response of + /// [`POST /_matrix/client/r0/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0room_keysversion) + /// or [`GET /_matrix/client/r0/room_keys/version/{version}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0room_keysversionversion). + Future deleteRoomKeysVersion(String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/version/${Uri.encodeComponent(version)}'); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Get information about an existing backup. + /// + /// [version] The backup version to get, as returned in the `version` parameter + /// of the response in + /// [`POST /_matrix/client/r0/room_keys/version`](https://spec.matrix.org/unstable/client-server/#post_matrixclientr0room_keysversion) + /// or this endpoint. + Future getRoomKeysVersion(String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/version/${Uri.encodeComponent(version)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetRoomKeysVersionResponse.fromJson(json); + } + + /// Update information about an existing backup. Only `auth_data` can be modified. + /// + /// [version] The backup version to update, as returned in the `version` + /// parameter in the response of + /// [`POST /_matrix/client/r0/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0room_keysversion) + /// or [`GET /_matrix/client/r0/room_keys/version/{version}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0room_keysversionversion). + /// + /// [algorithm] The algorithm used for storing backups. Must be the same as + /// the algorithm currently used by the backup. + /// + /// [authData] Algorithm-dependent data. See the documentation for the backup + /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the + /// expected format of the data. + Future putRoomKeysVersion(String version, BackupAlgorithm algorithm, + Map authData) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/version/${Uri.encodeComponent(version)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'algorithm': { + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: + 'm.megolm_backup.v1.curve25519-aes-sha2' + }[algorithm]!, + 'auth_data': authData, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Get a list of aliases maintained by the local server for the + /// given room. + /// + /// This endpoint can be called by users who are in the room (external + /// users receive an `M_FORBIDDEN` error response). If the room's + /// `m.room.history_visibility` maps to `world_readable`, any + /// user can call this endpoint. + /// + /// Servers may choose to implement additional access control checks here, + /// such as allowing server administrators to view aliases regardless of + /// membership. + /// + /// **Note:** + /// Clients are recommended not to display this list of aliases prominently + /// as they are not curated, unlike those listed in the `m.room.canonical_alias` + /// state event. + /// + /// [roomId] The room ID to find local aliases of. + /// + /// returns `aliases`: + /// The server's local aliases on the room. Can be empty. + Future> getLocalAliases(String roomId) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/aliases'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json['aliases'] as List).map((v) => v as String).toList(); + } + + /// Ban a user in the room. If the user is currently in the room, also kick them. + /// + /// When a user is banned from a room, they may not join it or be invited to it until they are unbanned. + /// + /// The caller must have the required power level in order to perform this operation. + /// + /// [roomId] The room identifier (not alias) from which the user should be banned. + /// + /// [reason] The reason the user has been banned. This will be supplied as the `reason` on the target's updated [`m.room.member`](https://spec.matrix.org/unstable/client-server-api/#mroommember) event. + /// + /// [userId] The fully qualified user ID of the user being banned. + Future ban(String roomId, String userId, {String? reason}) async { + final requestUri = + Uri(path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/ban'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + 'user_id': userId, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// This API returns a number of events that happened just before and + /// after the specified event. This allows clients to get the context + /// surrounding an event. + /// + /// *Note*: This endpoint supports lazy-loading of room member events. See + /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) for more information. + /// + /// [roomId] The room to get events from. + /// + /// [eventId] The event to get context around. + /// + /// [limit] The maximum number of events to return. Default: 10. + /// + /// [filter] A JSON `RoomEventFilter` to filter the returned events with. The + /// filter is only applied to `events_before`, `events_after`, and + /// `state`. It is not applied to the `event` itself. The filter may + /// be applied before or/and after the `limit` parameter - whichever the + /// homeserver prefers. + /// + /// See [Filtering](https://spec.matrix.org/unstable/client-server-api/#filtering) for more information. + Future getEventContext(String roomId, String eventId, + {int? limit, String? filter}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/context/${Uri.encodeComponent(eventId)}', + queryParameters: { + if (limit != null) 'limit': limit.toString(), + if (filter != null) 'filter': filter, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return EventContext.fromJson(json); + } + + /// Get a single event based on `roomId/eventId`. You must have permission to + /// retrieve this event e.g. by being a member in the room for this event. + /// + /// [roomId] The ID of the room the event is in. + /// + /// [eventId] The event ID to get. + Future getOneRoomEvent(String roomId, String eventId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/event/${Uri.encodeComponent(eventId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return MatrixEvent.fromJson(json); + } + + /// This API stops a user remembering about a particular room. + /// + /// In general, history is a first class citizen in Matrix. After this API + /// is called, however, a user will no longer be able to retrieve history + /// for this room. If all users on a homeserver forget a room, the room is + /// eligible for deletion from that homeserver. + /// + /// If the user is currently joined to the room, they must leave the room + /// before calling this API. + /// + /// [roomId] The room identifier to forget. + Future forgetRoom(String roomId) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/forget'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// *Note that there are two forms of this API, which are documented separately. + /// This version of the API does not require that the inviter know the Matrix + /// identifier of the invitee, and instead relies on third party identifiers. + /// The homeserver uses an identity server to perform the mapping from + /// third party identifier to a Matrix identifier. The other is documented in the* + /// [joining rooms section](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0roomsroomidinvite). + /// + /// This API invites a user to participate in a particular room. + /// They do not start participating in the room until they actually join the + /// room. + /// + /// Only users currently in a particular room can invite other users to + /// join that room. + /// + /// If the identity server did know the Matrix user identifier for the + /// third party identifier, the homeserver will append a `m.room.member` + /// event to the room. + /// + /// If the identity server does not know a Matrix user identifier for the + /// passed third party identifier, the homeserver will issue an invitation + /// which can be accepted upon providing proof of ownership of the third + /// party identifier. This is achieved by the identity server generating a + /// token, which it gives to the inviting homeserver. The homeserver will + /// add an `m.room.third_party_invite` event into the graph for the room, + /// containing that token. + /// + /// When the invitee binds the invited third party identifier to a Matrix + /// user ID, the identity server will give the user a list of pending + /// invitations, each containing: + /// + /// - The room ID to which they were invited + /// + /// - The token given to the homeserver + /// + /// - A signature of the token, signed with the identity server's private key + /// + /// - The matrix user ID who invited them to the room + /// + /// If a token is requested from the identity server, the homeserver will + /// append a `m.room.third_party_invite` event to the room. + /// + /// [roomId] The room identifier (not alias) to which to invite the user. + /// + /// [address] The invitee's third party identifier. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// [idServer] The hostname+port of the identity server which should be used for third party identifier lookups. + /// + /// [medium] The kind of address being passed in the address field, for example `email`. + Future inviteBy3PID(String roomId, String address, String idAccessToken, + String idServer, String medium) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/invite'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'address': address, + 'id_access_token': idAccessToken, + 'id_server': idServer, + 'medium': medium, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// *Note that there are two forms of this API, which are documented separately. + /// This version of the API requires that the inviter knows the Matrix + /// identifier of the invitee. The other is documented in the* + /// [third party invites section](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0roomsroomidinvite-1). + /// + /// This API invites a user to participate in a particular room. + /// They do not start participating in the room until they actually join the + /// room. + /// + /// Only users currently in a particular room can invite other users to + /// join that room. + /// + /// If the user was invited to the room, the homeserver will append a + /// `m.room.member` event to the room. + /// + /// [roomId] The room identifier (not alias) to which to invite the user. + /// + /// [reason] Optional reason to be included as the `reason` on the subsequent + /// membership event. + /// + /// [userId] The fully qualified user ID of the invitee. + Future inviteUser(String roomId, String userId, + {String? reason}) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/invite'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + 'user_id': userId, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// *Note that this API requires a room ID, not alias.* + /// `/join/{roomIdOrAlias}` *exists if you have a room alias.* + /// + /// This API starts a user participating in a particular room, if that user + /// is allowed to participate in that room. After this call, the client is + /// allowed to see all current state events in the room, and all subsequent + /// events associated with the room until the user leaves the room. + /// + /// After a user has joined a room, the room will appear as an entry in the + /// response of the [`/initialSync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0initialsync) + /// and [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) APIs. + /// + /// [roomId] The room identifier (not alias) to join. + /// + /// [reason] Optional reason to be included as the `reason` on the subsequent + /// membership event. + /// + /// [thirdPartySigned] If supplied, the homeserver must verify that it matches a pending + /// `m.room.third_party_invite` event in the room, and perform + /// key validity checking if required by the event. + /// + /// returns `room_id`: + /// The joined room ID. + Future joinRoomById(String roomId, + {String? reason, ThirdPartySigned? thirdPartySigned}) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/join'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + if (thirdPartySigned != null) + 'third_party_signed': thirdPartySigned.toJson(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['room_id'] as String; + } + + /// This API returns a map of MXIDs to member info objects for members of the room. The current user must be in the room for it to work, unless it is an Application Service in which case any of the AS's users must be in the room. This API is primarily for Application Services and should be faster to respond than `/members` as it can be implemented more efficiently on the server. + /// + /// [roomId] The room to get the members of. + /// + /// returns `joined`: + /// A map from user ID to a RoomMember object. + Future?> getJoinedMembersByRoom(String roomId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/joined_members'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, RoomMember.fromJson(v))) + : null)(json['joined']); + } + + /// Kick a user from the room. + /// + /// The caller must have the required power level in order to perform this operation. + /// + /// Kicking a user adjusts the target member's membership state to be `leave` with an + /// optional `reason`. Like with other membership changes, a user can directly adjust + /// the target member's state by making a request to `/rooms//state/m.room.member/`. + /// + /// [roomId] The room identifier (not alias) from which the user should be kicked. + /// + /// [reason] The reason the user has been kicked. This will be supplied as the + /// `reason` on the target's updated [`m.room.member`](https://spec.matrix.org/unstable/client-server-api/#mroommember) event. + /// + /// [userId] The fully qualified user ID of the user being kicked. + Future kick(String roomId, String userId, {String? reason}) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/kick'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + 'user_id': userId, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// This API stops a user participating in a particular room. + /// + /// If the user was already in the room, they will no longer be able to see + /// new events in the room. If the room requires an invite to join, they + /// will need to be re-invited before they can re-join. + /// + /// If the user was invited to the room, but had not joined, this call + /// serves to reject the invite. + /// + /// The user will still be allowed to retrieve history from the room which + /// they were previously allowed to see. + /// + /// [roomId] The room identifier to leave. + /// + /// [reason] Optional reason to be included as the `reason` on the subsequent + /// membership event. + Future leaveRoom(String roomId, {String? reason}) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/leave'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Get the list of members for this room. + /// + /// [roomId] The room to get the member events for. + /// + /// [at] 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. Defaults to the current state of the room, + /// as determined by the server. + /// + /// [membership] The kind of membership 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`. + /// + /// [notMembership] The kind of membership to exclude from the results. Defaults to no + /// filtering if unspecified. + /// + /// returns `chunk` + Future?> getMembersByRoom(String roomId, + {String? at, Membership? membership, Membership? notMembership}) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/members', + queryParameters: { + if (at != null) 'at': at, + if (membership != null) + 'membership': { + Membership.invite: 'invite', + Membership.join: 'join', + Membership.leave: 'leave', + Membership.ban: 'ban' + }[membership]!, + if (notMembership != null) + 'not_membership': { + Membership.invite: 'invite', + Membership.join: 'join', + Membership.leave: 'leave', + Membership.ban: 'ban' + }[notMembership]!, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['chunk']); + } + + /// This API returns a list of message and state events for a room. It uses + /// pagination query parameters to paginate history in the room. + /// + /// *Note*: This endpoint supports lazy-loading of room member events. See + /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) for more information. + /// + /// [roomId] The room to get events from. + /// + /// [from] 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. + /// + /// [to] 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. + /// + /// [dir] The direction to return events from. + /// + /// [limit] The maximum number of events to return. Default: 10. + /// + /// [filter] A JSON RoomEventFilter to filter returned events with. + Future getRoomEvents( + String roomId, String from, Direction dir, + {String? to, int? limit, String? filter}) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/messages', + queryParameters: { + 'from': from, + if (to != null) 'to': to, + 'dir': {Direction.b: 'b', Direction.f: 'f'}[dir]!, + if (limit != null) 'limit': limit.toString(), + if (filter != null) 'filter': filter, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetRoomEventsResponse.fromJson(json); + } + + /// Sets the position of the read marker for a given room, and optionally + /// the read receipt's location. + /// + /// [roomId] The room ID to set the read marker in for the user. + /// + /// [mFullyRead] The event ID the read marker should be located at. The + /// event MUST belong to the room. + /// + /// [mRead] The event ID to set the read receipt location at. This is + /// equivalent to calling `/receipt/m.read/$elsewhere:example.org` + /// and is provided here to save that extra call. + Future setReadMarker(String roomId, String mFullyRead, + {String? mRead}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/read_markers'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'm.fully_read': mFullyRead, + if (mRead != null) 'm.read': mRead, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// This API updates the marker for the given receipt type to the event ID + /// specified. + /// + /// [roomId] The room in which to send the event. + /// + /// [receiptType] The type of receipt to send. + /// + /// [eventId] The event ID to acknowledge up to. + /// + /// [receipt] Extra receipt information to attach to `content` if any. The + /// server will automatically set the `ts` field. + Future postReceipt(String roomId, ReceiptType receiptType, + String eventId, Map receipt) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/receipt/${Uri.encodeComponent({ + ReceiptType.mRead: 'm.read' + }[receiptType]!)}/${Uri.encodeComponent(eventId)}'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(receipt)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Strips all information out of an event which isn't critical to the + /// integrity of the server-side representation of the room. + /// + /// This cannot be undone. + /// + /// Any user with a power level greater than or equal to the `m.room.redaction` + /// event power level may send redaction events in the room. If the user's power + /// level greater is also greater than or equal to the `redact` power level + /// of the room, the user may redact events sent by other users. + /// + /// Server administrators may redact events sent by users on their server. + /// + /// [roomId] The room from which to redact the event. + /// + /// [eventId] The ID of the event to redact + /// + /// [txnId] The transaction ID for this event. Clients should generate a + /// unique ID; it will be used by the server to ensure idempotency of requests. + /// + /// [reason] The reason for the event being redacted. + /// + /// returns `event_id`: + /// A unique identifier for the event. + Future redactEvent(String roomId, String eventId, String txnId, + {String? reason}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/redact/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(txnId)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null ? v as String : null)(json['event_id']); + } + + /// Reports an event as inappropriate to the server, which may then notify + /// the appropriate people. + /// + /// [roomId] The room in which the event being reported is located. + /// + /// [eventId] The event to report. + /// + /// [reason] The reason the content is being reported. May be blank. + /// + /// [score] The score to rate this content as where -100 is most offensive + /// and 0 is inoffensive. + Future reportContent(String roomId, String eventId, + {String? reason, int? score}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/report/${Uri.encodeComponent(eventId)}'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + if (score != null) 'score': score, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// This endpoint is used to send a message event to a room. Message events + /// allow access to historical events and pagination, making them suited + /// for "once-off" activity in a room. + /// + /// The body of the request should be the content object of the event; the + /// fields in this object will vary depending on the type of event. See + /// [Room Events](https://spec.matrix.org/unstable/client-server-api/#room-events) for the m. event specification. + /// + /// [roomId] The room to send the event to. + /// + /// [eventType] The type of event to send. + /// + /// [txnId] 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. + /// + /// returns `event_id`: + /// A unique identifier for the event. + Future sendMessage(String roomId, String eventType, String txnId, + Map body) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/send/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(body)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['event_id'] as String; + } + + /// Get the state events for the current state of a room. + /// + /// [roomId] The room to look up the state for. + Future> getRoomState(String roomId) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/state'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => MatrixEvent.fromJson(v)).toList(); + } + + /// Looks up the contents of a state event in a room. If the user is + /// joined to the room then the state is taken from the current + /// state of the room. If the user has left the room then the state is + /// taken from the state of the room when they left. + /// + /// [roomId] The room to look up the state in. + /// + /// [eventType] The type of state to look up. + /// + /// [stateKey] The key of the state to look up. Defaults to an empty string. When + /// an empty string, the trailing slash on this endpoint is optional. + Future> getRoomStateWithKey( + String roomId, String eventType, String stateKey) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json as Map; + } + + /// State events can be sent using this endpoint. These events will be + /// overwritten if ``, `` and `` all + /// match. + /// + /// Requests to this endpoint **cannot use transaction IDs** + /// like other `PUT` paths because they cannot be differentiated from the + /// `state_key`. Furthermore, `POST` is unsupported on state paths. + /// + /// The body of the request should be the content object of the event; the + /// fields in this object will vary depending on the type of event. See + /// [Room Events](https://spec.matrix.org/unstable/client-server-api/#room-events) for the `m.` event specification. + /// + /// If the event type being sent is `m.room.canonical_alias` servers + /// SHOULD ensure that any new aliases being listed in the event are valid + /// per their grammar/syntax and that they point to the room ID where the + /// state event is to be sent. Servers do not validate aliases which are + /// being removed or are already present in the state event. + /// + /// + /// [roomId] The room to set the state in + /// + /// [eventType] The type of event to send. + /// + /// [stateKey] The state_key for the state to send. Defaults to the empty string. When + /// an empty string, the trailing slash on this endpoint is optional. + /// + /// returns `event_id`: + /// A unique identifier for the event. + Future setRoomStateWithKey(String roomId, String eventType, + String stateKey, Map body) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(body)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['event_id'] as String; + } + + /// This tells the server that the user is typing for the next N + /// milliseconds where N is the value specified in the `timeout` key. + /// Alternatively, if `typing` is `false`, it tells the server that the + /// user has stopped typing. + /// + /// [userId] The user who has started to type. + /// + /// [roomId] The room in which the user is typing. + /// + /// [timeout] The length of time in milliseconds to mark this user as typing. + /// + /// [typing] Whether the user is typing or not. If `false`, the `timeout` + /// key can be omitted. + Future setTyping(String userId, String roomId, bool typing, + {int? timeout}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/typing/${Uri.encodeComponent(userId)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (timeout != null) 'timeout': timeout, + 'typing': typing, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Unban a user from the room. This allows them to be invited to the room, + /// and join if they would otherwise be allowed to join according to its join rules. + /// + /// The caller must have the required power level in order to perform this operation. + /// + /// [roomId] The room identifier (not alias) from which the user should be unbanned. + /// + /// [reason] Optional reason to be included as the `reason` on the subsequent + /// membership event. + /// + /// [userId] The fully qualified user ID of the user being unbanned. + Future unban(String roomId, String userId, {String? reason}) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/unban'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (reason != null) 'reason': reason, + 'user_id': userId, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Upgrades the given room to a particular room version. + /// + /// [roomId] The ID of the room to upgrade. + /// + /// [newVersion] The new version for the room. + /// + /// returns `replacement_room`: + /// The ID of the new room. + Future upgradeRoom(String roomId, String newVersion) async { + final requestUri = Uri( + path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/upgrade'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'new_version': newVersion, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['replacement_room'] as String; + } + + /// Performs a full text search across different categories. + /// + /// [nextBatch] The point to return events from. If given, this should be a + /// `next_batch` result from a previous call to this endpoint. + /// + /// [searchCategories] Describes which categories to search in and their criteria. + Future search(Categories searchCategories, + {String? nextBatch}) async { + final requestUri = Uri(path: '_matrix/client/r0/search', queryParameters: { + if (nextBatch != null) 'next_batch': nextBatch, + }); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'search_categories': searchCategories.toJson(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return SearchResults.fromJson(json); + } + + /// This endpoint is used to send send-to-device events to a set of + /// client devices. + /// + /// [eventType] The type of event to send. + /// + /// [txnId] 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. + /// + /// [messages] The messages to send. A map from user ID, to a map from + /// device ID to message body. The device ID may also be `*`, + /// meaning all known devices for the user. + Future sendToDevice(String eventType, String txnId, + Map>> messages) async { + final requestUri = Uri( + path: + '_matrix/client/r0/sendToDevice/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'messages': + messages.map((k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v)))), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Synchronise the client's state with the latest state on the server. + /// Clients use this API when they first log in to get an initial snapshot + /// of the state on the server, and then continue to call this API to get + /// incremental deltas to the state, and to receive new messages. + /// + /// *Note*: This endpoint supports lazy-loading. See [Filtering](https://spec.matrix.org/unstable/client-server-api/#filtering) + /// for more information. Lazy-loading members is only supported on a `StateFilter` + /// for this endpoint. When lazy-loading is enabled, servers MUST include the + /// syncing user's own membership event when they join a room, or when the + /// full state of rooms is requested, to aid discovering the user's avatar & + /// displayname. + /// + /// Further, like other members, the user's own membership event is eligible + /// for being considered redundant by the server. When a sync is `limited`, + /// the server MUST return membership events for events in the gap + /// (between `since` and the start of the returned timeline), regardless + /// as to whether or not they are redundant. This ensures that joins/leaves + /// and profile changes which occur during the gap are not lost. + /// + /// Note that the default behaviour of `state` is to include all membership + /// events, alongside other state, when lazy-loading is not enabled. + /// + /// [filter] The ID of a filter created using the filter API or a filter JSON + /// object encoded as a string. The server will detect whether it is + /// an ID or a JSON object by whether the first character is a `"{"` + /// open brace. Passing the JSON inline is best suited to one off + /// requests. Creating a filter using the filter API is recommended for + /// clients that reuse the same filter multiple times, for example in + /// long poll requests. + /// + /// See [Filtering](https://spec.matrix.org/unstable/client-server-api/#filtering) for more information. + /// + /// [since] A point in time to continue a sync from. + /// + /// [fullState] Controls whether to include the full state for all rooms the user + /// is a member of. + /// + /// If this is set to `true`, then all state events will be returned, + /// even if `since` is non-empty. The timeline will still be limited + /// by the `since` parameter. In this case, the `timeout` parameter + /// will be ignored and the query will return immediately, possibly with + /// an empty timeline. + /// + /// If `false`, and `since` is non-empty, only state which has + /// changed since the point indicated by `since` will be returned. + /// + /// By default, this is `false`. + /// + /// [setPresence] Controls whether the client is automatically marked as online by + /// polling this API. If this parameter is omitted then the client is + /// automatically marked as online when it uses this API. Otherwise if + /// the parameter is set to "offline" then the client is not marked as + /// being online when it uses this API. When set to "unavailable", the + /// client is marked as being idle. + /// + /// [timeout] The maximum time to wait, in milliseconds, before returning this + /// request. If no events (or other data) become available before this + /// time elapses, the server will return a response with empty fields. + /// + /// By default, this is `0`, so the server will return immediately + /// even if the response is empty. + Future sync( + {String? filter, + String? since, + bool? fullState, + PresenceType? setPresence, + int? timeout}) async { + final requestUri = Uri(path: '_matrix/client/r0/sync', queryParameters: { + if (filter != null) 'filter': filter, + if (since != null) 'since': since, + if (fullState != null) 'full_state': fullState.toString(), + if (setPresence != null) + 'set_presence': { + PresenceType.online: 'online', + PresenceType.offline: 'offline', + PresenceType.unavailable: 'unavailable' + }[setPresence]!, + if (timeout != null) 'timeout': timeout.toString(), + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return SyncUpdate.fromJson(json); + } + + /// Get some account_data for the client. This config is only visible to the user + /// that set the account_data. + /// + /// [userId] The ID of the user to get account_data for. The access token must be + /// authorized to make requests for this user ID. + /// + /// [type] The event type of the account_data to get. Custom types should be + /// namespaced to avoid clashes. + Future> getAccountData( + String userId, String type) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json as Map; + } + + /// Set some account_data for the client. This config is only visible to the user + /// that set the account_data. The config will be synced to clients in the + /// top-level `account_data`. + /// + /// [userId] The ID of the user to set account_data for. The access token must be + /// authorized to make requests for this user ID. + /// + /// [type] The event type of the account_data to set. Custom types should be + /// namespaced to avoid clashes. + /// + /// [content] The content of the account_data + Future setAccountData( + String userId, String type, Map content) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(content)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Uploads a new filter definition to the homeserver. + /// Returns a filter ID that may be used in future requests to + /// restrict which events are returned to the client. + /// + /// [userId] The id of the user uploading the filter. The access token must be authorized to make requests for this user id. + /// + /// [filter] The filter to upload. + /// + /// returns `filter_id`: + /// The ID of the filter that was created. Cannot start + /// with a `{` as this character is used to determine + /// if the filter provided is inline JSON or a previously + /// declared filter by homeservers on some APIs. + Future defineFilter(String userId, Filter filter) async { + final requestUri = Uri( + path: '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/filter'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(filter)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['filter_id'] as String; + } + + /// getFilter + /// + /// [userId] The user ID to download a filter for. + /// + /// [filterId] The filter ID to download. + Future getFilter(String userId, String filterId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/filter/${Uri.encodeComponent(filterId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return Filter.fromJson(json); + } + + /// Gets an OpenID token object that the requester may supply to another + /// service to verify their identity in Matrix. The generated token is only + /// valid for exchanging for user information from the federation API for + /// OpenID. + /// + /// The access token generated is only valid for the OpenID API. It cannot + /// be used to request another OpenID access token or call `/sync`, for + /// example. + /// + /// [userId] The user to request and OpenID token for. Should be the user who + /// is authenticated for the request. + /// + /// [body] An empty object. Reserved for future expansion. + Future requestOpenIdToken( + String userId, Map body) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/openid/request_token'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(body)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return OpenIdCredentials.fromJson(json); + } + + /// Get some account_data for the client on a given room. This config is only + /// visible to the user that set the account_data. + /// + /// [userId] The ID of the user to set account_data for. The access token must be + /// authorized to make requests for this user ID. + /// + /// [roomId] The ID of the room to get account_data for. + /// + /// [type] The event type of the account_data to get. Custom types should be + /// namespaced to avoid clashes. + Future> getAccountDataPerRoom( + String userId, String roomId, String type) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json as Map; + } + + /// Set some account_data for the client on a given room. This config is only + /// visible to the user that set the account_data. The config will be synced to + /// clients in the per-room `account_data`. + /// + /// [userId] The ID of the user to set account_data for. The access token must be + /// authorized to make requests for this user ID. + /// + /// [roomId] The ID of the room to set account_data on. + /// + /// [type] The event type of the account_data to set. Custom types should be + /// namespaced to avoid clashes. + /// + /// [content] The content of the account_data + Future setAccountDataPerRoom(String userId, String roomId, String type, + Map content) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(content)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// List the tags set by a user on a room. + /// + /// [userId] The id of the user to get tags for. The access token must be + /// authorized to make requests for this user ID. + /// + /// [roomId] The ID of the room to get tags for. + /// + /// returns `tags` + Future?> getRoomTags(String userId, String roomId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, Tag.fromJson(v))) + : null)(json['tags']); + } + + /// Remove a tag from the room. + /// + /// [userId] The id of the user to remove a tag for. The access token must be + /// authorized to make requests for this user ID. + /// + /// [roomId] The ID of the room to remove a tag from. + /// + /// [tag] The tag to remove. + Future deleteRoomTag(String userId, String roomId, String tag) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}'); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Add a tag to the room. + /// + /// [userId] The id of the user to add a tag for. The access token must be + /// authorized to make requests for this user ID. + /// + /// [roomId] The ID of the room to add a tag to. + /// + /// [tag] The tag to add. + /// + /// [order] A number in a range `[0,1]` describing a relative + /// position of the room under the given tag. + Future setRoomTag(String userId, String roomId, String tag, + {double? order, + Map additionalProperties = const {}}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + ...additionalProperties, + if (order != null) 'order': order, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + + /// Performs a search for users. The homeserver may + /// determine which subset of users are searched, however the homeserver + /// MUST at a minimum consider the users the requesting user shares a + /// room with and those who reside in public rooms (known to the homeserver). + /// The search MUST consider local users to the homeserver, and SHOULD + /// query remote users as part of the search. + /// + /// The search is performed case-insensitively on user IDs and display + /// names preferably using a collation determined based upon the + /// `Accept-Language` header provided in the request, if present. + /// + /// [limit] The maximum number of results to return. Defaults to 10. + /// + /// [searchTerm] The term to search for + Future searchUserDirectory(String searchTerm, + {int? limit}) async { + final requestUri = Uri(path: '_matrix/client/r0/user_directory/search'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (limit != null) 'limit': limit, + 'search_term': searchTerm, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return SearchUserDirectoryResponse.fromJson(json); + } + + /// This API provides credentials for the client to use when initiating + /// calls. + Future getTurnServer() async { + final requestUri = Uri(path: '_matrix/client/r0/voip/turnServer'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return TurnServerCredentials.fromJson(json); + } + + /// Gets the versions of the specification supported by the server. + /// + /// Values will take the form `rX.Y.Z`. + /// + /// Only the latest `Z` value will be reported for each supported `X.Y` value. + /// i.e. if the server implements `r0.0.0`, `r0.0.1`, and `r1.2.0`, it will report `r0.0.1` and `r1.2.0`. + /// + /// The server may additionally advertise experimental features it supports + /// through `unstable_features`. These features should be namespaced and + /// may optionally include version information within their name if desired. + /// Features listed here are not for optionally toggling parts of the Matrix + /// specification and should only be used to advertise support for a feature + /// which has not yet landed in the spec. For example, a feature currently + /// undergoing the proposal process may appear here and eventually be taken + /// off this list once the feature lands in the spec and the server deems it + /// reasonable to do so. Servers may wish to keep advertising features here + /// after they've been released into the spec to give clients a chance to + /// upgrade appropriately. Additionally, clients should avoid using unstable + /// features in their stable releases. + Future getVersions() async { + final requestUri = Uri(path: '_matrix/client/versions'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetVersionsResponse.fromJson(json); + } + + /// This endpoint allows clients to retrieve the configuration of the content + /// repository, such as upload limitations. + /// Clients SHOULD use this as a guide when using content repository endpoints. + /// All values are intentionally left optional. Clients SHOULD follow + /// the advice given in the field description when the field is not available. + /// + /// **NOTE:** Both clients and server administrators should be aware that proxies + /// between the client and the server may affect the apparent behaviour of content + /// repository APIs, for example, proxies may enforce a lower upload size limit + /// than is advertised by the server on this endpoint. + Future getConfig() async { + final requestUri = Uri(path: '_matrix/media/r0/config'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ServerConfig.fromJson(json); + } + + /// getContent + /// + /// [serverName] The server name from the `mxc://` URI (the authoritory component) + /// + /// + /// [mediaId] The media ID from the `mxc://` URI (the path component) + /// + /// + /// [allowRemote] Indicates to the server that it should not attempt to fetch the media if it is deemed + /// remote. This is to prevent routing loops where the server contacts itself. Defaults to + /// true if not provided. + /// + Future getContent(String serverName, String mediaId, + {bool? allowRemote}) async { + final requestUri = Uri( + path: + '_matrix/media/r0/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}', + queryParameters: { + if (allowRemote != null) 'allow_remote': allowRemote.toString(), + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + return FileResponse( + contentType: response.headers['content-type'], data: responseBody); + } + + /// This will download content from the content repository (same as + /// the previous endpoint) but replace the target file name with the one + /// provided by the caller. + /// + /// [serverName] The server name from the `mxc://` URI (the authoritory component) + /// + /// + /// [mediaId] The media ID from the `mxc://` URI (the path component) + /// + /// + /// [fileName] A filename to give in the `Content-Disposition` header. + /// + /// [allowRemote] Indicates to the server that it should not attempt to fetch the media if it is deemed + /// remote. This is to prevent routing loops where the server contacts itself. Defaults to + /// true if not provided. + /// + Future getContentOverrideName( + String serverName, String mediaId, String fileName, + {bool? allowRemote}) async { + final requestUri = Uri( + path: + '_matrix/media/r0/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}/${Uri.encodeComponent(fileName)}', + queryParameters: { + if (allowRemote != null) 'allow_remote': allowRemote.toString(), + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + return FileResponse( + contentType: response.headers['content-type'], data: responseBody); + } + + /// Get information about a URL for the client. Typically this is called when a + /// client sees a URL in a message and wants to render a preview for the user. + /// + /// **Note:** + /// Clients should consider avoiding this endpoint for URLs posted in encrypted + /// rooms. Encrypted rooms often contain more sensitive information the users + /// do not want to share with the homeserver, and this can mean that the URLs + /// being shared should also not be shared with the homeserver. + /// + /// [url] The URL to get a preview of. + /// + /// [ts] The preferred point in time to return a preview for. The server may + /// return a newer version if it does not have the requested version + /// available. + Future getUrlPreview(Uri url, {int? ts}) async { + final requestUri = + Uri(path: '_matrix/media/r0/preview_url', queryParameters: { + 'url': url.toString(), + if (ts != null) 'ts': ts.toString(), + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetUrlPreviewResponse.fromJson(json); + } + + /// Download a thumbnail of content from the content repository. + /// See the [Thumbnails](https://spec.matrix.org/unstable/client-server-api/#thumbnails) section for more information. + /// + /// [serverName] The server name from the `mxc://` URI (the authoritory component) + /// + /// + /// [mediaId] The media ID from the `mxc://` URI (the path component) + /// + /// + /// [width] The *desired* width of the thumbnail. The actual thumbnail may be + /// larger than the size specified. + /// + /// [height] The *desired* height of the thumbnail. The actual thumbnail may be + /// larger than the size specified. + /// + /// [method] The desired resizing method. See the [Thumbnails](https://spec.matrix.org/unstable/client-server-api/#thumbnails) + /// section for more information. + /// + /// [allowRemote] Indicates to the server that it should not attempt to fetch + /// the media if it is deemed remote. This is to prevent routing loops + /// where the server contacts itself. Defaults to true if not provided. + Future getContentThumbnail( + String serverName, String mediaId, int width, int height, + {Method? method, bool? allowRemote}) async { + final requestUri = Uri( + path: + '_matrix/media/r0/thumbnail/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}', + queryParameters: { + 'width': width.toString(), + 'height': height.toString(), + if (method != null) + 'method': {Method.crop: 'crop', Method.scale: 'scale'}[method]!, + if (allowRemote != null) 'allow_remote': allowRemote.toString(), + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + return FileResponse( + contentType: response.headers['content-type'], data: responseBody); + } + + /// uploadContent + /// + /// [contentType] The content type of the file being uploaded + /// + /// [filename] The name of the file being uploaded + /// + /// [content] The content to be uploaded. + /// + /// returns `content_uri`: + /// The [MXC URI](https://spec.matrix.org/unstable/client-server-api/#matrix-content-mxc-uris) to the uploaded content. + Future uploadContent(Uint8List content, + {String? contentType, String? filename}) async { + final requestUri = Uri(path: '_matrix/media/r0/upload', queryParameters: { + if (filename != null) 'filename': filename, + }); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + if (contentType != null) request.headers['content-type'] = contentType; + request.bodyBytes = content; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['content_uri'] as String; + } +} diff --git a/lib/src/generated/fixed_model.dart b/lib/src/generated/fixed_model.dart new file mode 100644 index 00000000..22c27070 --- /dev/null +++ b/lib/src/generated/fixed_model.dart @@ -0,0 +1,7 @@ +import 'dart:typed_data'; + +class FileResponse { + FileResponse({this.contentType, required this.data}); + String? contentType; + Uint8List data; +} diff --git a/lib/src/generated/internal.dart b/lib/src/generated/internal.dart new file mode 100644 index 00000000..48d80d0c --- /dev/null +++ b/lib/src/generated/internal.dart @@ -0,0 +1,6 @@ +import 'fixed_model.dart'; + +void ignore(Object? input) {} +FileResponse ignoreFile(dynamic input) { + throw UnimplementedError(); +} diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart new file mode 100644 index 00000000..71989bcc --- /dev/null +++ b/lib/src/generated/model.dart @@ -0,0 +1,3113 @@ +import '../model/auth/authentication_data.dart'; +import '../model/auth/authentication_types.dart'; +import '../model/auth/authentication_identifier.dart'; +import '../model/matrix_keys.dart'; +import '../model/sync_update.dart'; +import '../model/matrix_event.dart'; + +import 'internal.dart'; + +class _NameSource { + final String source; + const _NameSource(this.source); +} + +@_NameSource('spec') +class HomeserverInformation { + HomeserverInformation({ + required this.baseUrl, + }); + + HomeserverInformation.fromJson(Map json) + : baseUrl = Uri.parse(json['base_url']); + Map toJson() => { + 'base_url': baseUrl.toString(), + }; + + /// The base URL for the homeserver for client-server connections. + Uri baseUrl; +} + +@_NameSource('spec') +class IdentityServerInformation { + IdentityServerInformation({ + required this.baseUrl, + }); + + IdentityServerInformation.fromJson(Map json) + : baseUrl = Uri.parse(json['base_url']); + Map toJson() => { + 'base_url': baseUrl.toString(), + }; + + /// The base URL for the identity server for client-server connections. + Uri baseUrl; +} + +/// Used by clients to determine the homeserver, identity server, and other +/// optional components they should be interacting with. +@_NameSource('spec') +class DiscoveryInformation { + DiscoveryInformation({ + required this.mHomeserver, + this.mIdentityServer, + this.additionalProperties = const {}, + }); + + DiscoveryInformation.fromJson(Map json) + : mHomeserver = HomeserverInformation.fromJson(json['m.homeserver']), + mIdentityServer = ((v) => v != null + ? IdentityServerInformation.fromJson(v) + : null)(json['m.identity_server']), + additionalProperties = Map.fromEntries(json.entries + .where( + (e) => !['m.homeserver', 'm.identity_server'].contains(e.key)) + .map((e) => MapEntry(e.key, e.value as Map))); + Map toJson() { + final mIdentityServer = this.mIdentityServer; + return { + ...additionalProperties, + 'm.homeserver': mHomeserver.toJson(), + if (mIdentityServer != null) + 'm.identity_server': mIdentityServer.toJson(), + }; + } + + /// Used by clients to discover homeserver information. + HomeserverInformation mHomeserver; + + /// Used by clients to discover identity server information. + IdentityServerInformation? mIdentityServer; + + Map> additionalProperties; +} + +@_NameSource('rule override generated') +enum ThirdPartyIdentifierMedium { email, msisdn } + +@_NameSource('spec') +class ThirdPartyIdentifier { + ThirdPartyIdentifier({ + required this.addedAt, + required this.address, + required this.medium, + required this.validatedAt, + }); + + ThirdPartyIdentifier.fromJson(Map json) + : addedAt = json['added_at'] as int, + address = json['address'] as String, + medium = { + 'email': ThirdPartyIdentifierMedium.email, + 'msisdn': ThirdPartyIdentifierMedium.msisdn + }[json['medium']]!, + validatedAt = json['validated_at'] as int; + Map toJson() => { + 'added_at': addedAt, + 'address': address, + 'medium': { + ThirdPartyIdentifierMedium.email: 'email', + ThirdPartyIdentifierMedium.msisdn: 'msisdn' + }[medium]!, + 'validated_at': validatedAt, + }; + + /// The timestamp, in milliseconds, when the homeserver associated the third party identifier with the user. + int addedAt; + + /// The third party identifier address. + String address; + + /// The medium of the third party identifier. + ThirdPartyIdentifierMedium medium; + + /// The timestamp, in milliseconds, when the identifier was + /// validated by the identity server. + int validatedAt; +} + +@_NameSource('spec') +class ThreePidCredentials { + ThreePidCredentials({ + required this.clientSecret, + required this.idAccessToken, + required this.idServer, + required this.sid, + }); + + ThreePidCredentials.fromJson(Map json) + : clientSecret = json['client_secret'] as String, + idAccessToken = json['id_access_token'] as String, + idServer = json['id_server'] as String, + sid = json['sid'] as String; + Map toJson() => { + 'client_secret': clientSecret, + 'id_access_token': idAccessToken, + 'id_server': idServer, + 'sid': sid, + }; + + /// The client secret used in the session with the identity server. + String clientSecret; + + /// An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + String idAccessToken; + + /// The identity server to use. + String idServer; + + /// The session identifier given by the identity server. + String sid; +} + +@_NameSource('generated') +enum IdServerUnbindResult { noSupport, success } + +@_NameSource('rule override generated') +class TokenOwnerInfo { + TokenOwnerInfo({ + this.deviceId, + required this.userId, + }); + + TokenOwnerInfo.fromJson(Map json) + : deviceId = ((v) => v != null ? v as String : null)(json['device_id']), + userId = json['user_id'] as String; + Map toJson() { + final deviceId = this.deviceId; + return { + if (deviceId != null) 'device_id': deviceId, + 'user_id': userId, + }; + } + + /// Device ID associated with the access token. If no device + /// is associated with the access token (such as in the case + /// of application services) then this field can be omitted. + /// Otherwise this is required. + String? deviceId; + + /// The user ID that owns the access token. + String userId; +} + +@_NameSource('spec') +class ConnectionInfo { + ConnectionInfo({ + this.ip, + this.lastSeen, + this.userAgent, + }); + + ConnectionInfo.fromJson(Map json) + : ip = ((v) => v != null ? v as String : null)(json['ip']), + lastSeen = ((v) => v != null ? v as int : null)(json['last_seen']), + userAgent = ((v) => v != null ? v as String : null)(json['user_agent']); + Map toJson() { + final ip = this.ip; + final lastSeen = this.lastSeen; + final userAgent = this.userAgent; + return { + if (ip != null) 'ip': ip, + if (lastSeen != null) 'last_seen': lastSeen, + if (userAgent != null) 'user_agent': userAgent, + }; + } + + /// Most recently seen IP address of the session. + String? ip; + + /// Unix timestamp that the session was last active. + int? lastSeen; + + /// User agent string last seen in the session. + String? userAgent; +} + +@_NameSource('spec') +class SessionInfo { + SessionInfo({ + this.connections, + }); + + SessionInfo.fromJson(Map json) + : connections = ((v) => v != null + ? (v as List).map((v) => ConnectionInfo.fromJson(v)).toList() + : null)(json['connections']); + Map toJson() { + final connections = this.connections; + return { + if (connections != null) + 'connections': connections.map((v) => v.toJson()).toList(), + }; + } + + /// Information particular connections in the session. + List? connections; +} + +@_NameSource('spec') +class DeviceInfo { + DeviceInfo({ + this.sessions, + }); + + DeviceInfo.fromJson(Map json) + : sessions = ((v) => v != null + ? (v as List).map((v) => SessionInfo.fromJson(v)).toList() + : null)(json['sessions']); + Map toJson() { + final sessions = this.sessions; + return { + if (sessions != null) + 'sessions': sessions.map((v) => v.toJson()).toList(), + }; + } + + /// A user's sessions (i.e. what they did with an access token from one login). + List? sessions; +} + +@_NameSource('rule override generated') +class WhoIsInfo { + WhoIsInfo({ + this.devices, + this.userId, + }); + + WhoIsInfo.fromJson(Map json) + : devices = ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, DeviceInfo.fromJson(v))) + : null)(json['devices']), + userId = ((v) => v != null ? v as String : null)(json['user_id']); + Map toJson() { + final devices = this.devices; + final userId = this.userId; + return { + if (devices != null) + 'devices': devices.map((k, v) => MapEntry(k, v.toJson())), + if (userId != null) 'user_id': userId, + }; + } + + /// Each key is an identifier for one of the user's devices. + Map? devices; + + /// The Matrix user ID of the user. + String? userId; +} + +@_NameSource('spec') +class ChangePasswordCapability { + ChangePasswordCapability({ + required this.enabled, + }); + + ChangePasswordCapability.fromJson(Map json) + : enabled = json['enabled'] as bool; + Map toJson() => { + 'enabled': enabled, + }; + + /// True if the user can change their password, false otherwise. + bool enabled; +} + +/// The stability of the room version. +@_NameSource('rule override generated') +enum RoomVersionAvailable { stable, unstable } + +@_NameSource('spec') +class RoomVersionsCapability { + RoomVersionsCapability({ + required this.available, + required this.default$, + }); + + RoomVersionsCapability.fromJson(Map json) + : available = (json['available'] as Map).map((k, v) => + MapEntry( + k, + { + 'stable': RoomVersionAvailable.stable, + 'unstable': RoomVersionAvailable.unstable + }[v]!)), + default$ = json['default'] as String; + Map toJson() => { + 'available': available.map((k, v) => MapEntry( + k, + { + RoomVersionAvailable.stable: 'stable', + RoomVersionAvailable.unstable: 'unstable' + }[v]!)), + 'default': default$, + }; + + /// A detailed description of the room versions the server supports. + Map available; + + /// The default room version the server is using for new rooms. + String default$; +} + +@_NameSource('spec') +class Capabilities { + Capabilities({ + this.mChangePassword, + this.mRoomVersions, + this.additionalProperties = const {}, + }); + + Capabilities.fromJson(Map json) + : mChangePassword = ((v) => v != null + ? ChangePasswordCapability.fromJson(v) + : null)(json['m.change_password']), + mRoomVersions = ((v) => v != null + ? RoomVersionsCapability.fromJson(v) + : null)(json['m.room_versions']), + additionalProperties = Map.fromEntries(json.entries + .where((e) => + !['m.change_password', 'm.room_versions'].contains(e.key)) + .map((e) => MapEntry(e.key, e.value as Map))); + Map toJson() { + final mChangePassword = this.mChangePassword; + final mRoomVersions = this.mRoomVersions; + return { + ...additionalProperties, + if (mChangePassword != null) + 'm.change_password': mChangePassword.toJson(), + if (mRoomVersions != null) 'm.room_versions': mRoomVersions.toJson(), + }; + } + + /// Capability to indicate if the user can change their password. + ChangePasswordCapability? mChangePassword; + + /// The room versions the server supports. + RoomVersionsCapability? mRoomVersions; + + Map> additionalProperties; +} + +@_NameSource('spec') +class StateEvent { + StateEvent({ + required this.content, + this.stateKey, + required this.type, + }); + + StateEvent.fromJson(Map json) + : content = json['content'] as Map, + stateKey = ((v) => v != null ? v as String : null)(json['state_key']), + type = json['type'] as String; + Map toJson() { + final stateKey = this.stateKey; + return { + 'content': content, + if (stateKey != null) 'state_key': stateKey, + 'type': type, + }; + } + + /// The content of the event. + Map content; + + /// The state_key of the state event. Defaults to an empty string. + String? stateKey; + + /// The type of event to send. + String type; +} + +@_NameSource('spec') +class Invite3pid { + Invite3pid({ + required this.address, + required this.idAccessToken, + required this.idServer, + required this.medium, + }); + + Invite3pid.fromJson(Map json) + : address = json['address'] as String, + idAccessToken = json['id_access_token'] as String, + idServer = json['id_server'] as String, + medium = json['medium'] as String; + Map toJson() => { + 'address': address, + 'id_access_token': idAccessToken, + 'id_server': idServer, + 'medium': medium, + }; + + /// The invitee's third party identifier. + String address; + + /// An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + String idAccessToken; + + /// The hostname+port of the identity server which should be used for third party identifier lookups. + String idServer; + + /// The kind of address being passed in the address field, for example `email`. + String medium; +} + +@_NameSource('rule override generated') +enum CreateRoomPreset { privateChat, publicChat, trustedPrivateChat } + +@_NameSource('generated') +enum Visibility { private, public } + +/// A client device +@_NameSource('spec') +class Device { + Device({ + required this.deviceId, + this.displayName, + this.lastSeenIp, + this.lastSeenTs, + }); + + Device.fromJson(Map json) + : deviceId = json['device_id'] as String, + displayName = + ((v) => v != null ? v as String : null)(json['display_name']), + lastSeenIp = + ((v) => v != null ? v as String : null)(json['last_seen_ip']), + lastSeenTs = ((v) => v != null ? v as int : null)(json['last_seen_ts']); + Map toJson() { + final displayName = this.displayName; + final lastSeenIp = this.lastSeenIp; + final lastSeenTs = this.lastSeenTs; + return { + 'device_id': deviceId, + if (displayName != null) 'display_name': displayName, + if (lastSeenIp != null) 'last_seen_ip': lastSeenIp, + if (lastSeenTs != null) 'last_seen_ts': lastSeenTs, + }; + } + + /// Identifier of this device. + String deviceId; + + /// Display name set by the user for this device. Absent if no name has been + /// set. + String? displayName; + + /// The IP address where this device was last seen. (May be a few minutes out + /// of date, for efficiency reasons). + String? lastSeenIp; + + /// The timestamp (in milliseconds since the unix epoch) when this devices + /// was last seen. (May be a few minutes out of date, for efficiency + /// reasons). + int? lastSeenTs; +} + +@_NameSource('generated') +class GetRoomIdByAliasResponse { + GetRoomIdByAliasResponse({ + this.roomId, + this.servers, + }); + + GetRoomIdByAliasResponse.fromJson(Map json) + : roomId = ((v) => v != null ? v as String : null)(json['room_id']), + servers = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['servers']); + Map toJson() { + final roomId = this.roomId; + final servers = this.servers; + return { + if (roomId != null) 'room_id': roomId, + if (servers != null) 'servers': servers.map((v) => v).toList(), + }; + } + + /// The room ID for this room alias. + String? roomId; + + /// A list of servers that are aware of this room alias. + List? servers; +} + +/// 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. +@_NameSource('spec') +class ThirdPartySigned { + ThirdPartySigned({ + required this.mxid, + required this.sender, + required this.signatures, + required this.token, + }); + + ThirdPartySigned.fromJson(Map json) + : mxid = json['mxid'] as String, + sender = json['sender'] as String, + signatures = (json['signatures'] as Map).map((k, v) => + MapEntry( + k, + (v as Map) + .map((k, v) => MapEntry(k, v as String)))), + token = json['token'] as String; + Map toJson() => { + 'mxid': mxid, + 'sender': sender, + 'signatures': signatures + .map((k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v)))), + 'token': token, + }; + + /// The Matrix ID of the invitee. + String mxid; + + /// The Matrix ID of the user who issued the invite. + String sender; + + /// A signatures object containing a signature of the entire signed object. + Map> signatures; + + /// The state key of the m.third_party_invite event. + String token; +} + +@_NameSource('generated') +class GetKeysChangesResponse { + GetKeysChangesResponse({ + this.changed, + this.left, + }); + + GetKeysChangesResponse.fromJson(Map json) + : changed = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['changed']), + left = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['left']); + Map toJson() { + final changed = this.changed; + final left = this.left; + return { + if (changed != null) 'changed': changed.map((v) => v).toList(), + if (left != null) 'left': left.map((v) => v).toList(), + }; + } + + /// The Matrix User IDs of all users who updated their device + /// identity keys. + List? changed; + + /// The Matrix User IDs of all users who may have left all + /// the end-to-end encrypted rooms they previously shared + /// with the user. + List? left; +} + +@_NameSource('generated') +class ClaimKeysResponse { + ClaimKeysResponse({ + this.failures, + required this.oneTimeKeys, + }); + + ClaimKeysResponse.fromJson(Map json) + : failures = ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, v as Map)) + : null)(json['failures']), + oneTimeKeys = (json['one_time_keys'] as Map).map( + (k, v) => MapEntry( + k, + (v as Map) + .map((k, v) => MapEntry(k, v as dynamic)))); + Map toJson() { + final failures = this.failures; + return { + if (failures != null) 'failures': failures.map((k, v) => MapEntry(k, v)), + 'one_time_keys': oneTimeKeys + .map((k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v)))), + }; + } + + /// If any remote homeservers could not be reached, they are + /// recorded here. The names of the properties are the names of + /// the unreachable servers. + /// + /// If the homeserver could be reached, but the user or device + /// was unknown, no failure is recorded. Instead, the corresponding + /// user or device is missing from the `one_time_keys` result. + Map>? failures; + + /// One-time keys for the queried devices. A map from user ID, to a + /// map from devices to a map from `:` to the key object. + /// + /// See the [key algorithms](https://spec.matrix.org/unstable/client-server-api/#key-algorithms) section for information + /// on the Key Object format. + Map> oneTimeKeys; +} + +@_NameSource('generated') +class QueryKeysResponse { + QueryKeysResponse({ + this.deviceKeys, + this.failures, + this.masterKeys, + this.selfSigningKeys, + this.userSigningKeys, + }); + + QueryKeysResponse.fromJson(Map json) + : deviceKeys = ((v) => v != null + ? (v as Map).map((k, v) => MapEntry( + k, + (v as Map) + .map((k, v) => MapEntry(k, MatrixDeviceKeys.fromJson(v))))) + : null)(json['device_keys']), + failures = ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, v as Map)) + : null)(json['failures']), + masterKeys = ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, MatrixCrossSigningKey.fromJson(v))) + : null)(json['master_keys']), + selfSigningKeys = ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, MatrixCrossSigningKey.fromJson(v))) + : null)(json['self_signing_keys']), + userSigningKeys = ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, MatrixCrossSigningKey.fromJson(v))) + : null)(json['user_signing_keys']); + Map toJson() { + final deviceKeys = this.deviceKeys; + final failures = this.failures; + final masterKeys = this.masterKeys; + final selfSigningKeys = this.selfSigningKeys; + final userSigningKeys = this.userSigningKeys; + return { + if (deviceKeys != null) + 'device_keys': deviceKeys.map( + (k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v.toJson())))), + if (failures != null) 'failures': failures.map((k, v) => MapEntry(k, v)), + if (masterKeys != null) + 'master_keys': masterKeys.map((k, v) => MapEntry(k, v.toJson())), + if (selfSigningKeys != null) + 'self_signing_keys': + selfSigningKeys.map((k, v) => MapEntry(k, v.toJson())), + if (userSigningKeys != null) + 'user_signing_keys': + userSigningKeys.map((k, v) => MapEntry(k, v.toJson())), + }; + } + + /// Information on the queried devices. A map from user ID, to a + /// map from device ID to device information. For each device, + /// the information returned will be the same as uploaded via + /// `/keys/upload`, with the addition of an `unsigned` + /// property. + Map>? deviceKeys; + + /// If any remote homeservers could not be reached, they are + /// recorded here. The names of the properties are the names of + /// the unreachable servers. + /// + /// If the homeserver could be reached, but the user or device + /// was unknown, no failure is recorded. Instead, the corresponding + /// user or device is missing from the `device_keys` result. + Map>? failures; + + /// Information on the master cross-signing keys of the queried users. + /// A map from user ID, to master key information. For each key, the + /// information returned will be the same as uploaded via + /// `/keys/device_signing/upload`, along with the signatures + /// uploaded via `/keys/signatures/upload` that the requesting user + /// is allowed to see. + Map? masterKeys; + + /// Information on the self-signing keys of the queried users. A map + /// from user ID, to self-signing key information. For each key, the + /// information returned will be the same as uploaded via + /// `/keys/device_signing/upload`. + Map? selfSigningKeys; + + /// Information on the user-signing key of the user making the + /// request, if they queried their own device information. A map + /// from user ID, to user-signing key information. The + /// information returned will be the same as uploaded via + /// `/keys/device_signing/upload`. + Map? userSigningKeys; +} + +@_NameSource('spec') +class LoginFlow { + LoginFlow({ + this.type, + }); + + LoginFlow.fromJson(Map json) + : type = ((v) => v != null ? v as String : null)(json['type']); + Map toJson() { + final type = this.type; + return { + if (type != null) 'type': type, + }; + } + + /// The login type. This is supplied as the `type` when + /// logging in. + String? type; +} + +@_NameSource('rule override generated') +enum LoginType { mLoginPassword, mLoginToken } + +@_NameSource('generated') +class LoginResponse { + LoginResponse({ + this.accessToken, + this.deviceId, + this.homeServer, + this.userId, + this.wellKnown, + }); + + LoginResponse.fromJson(Map json) + : accessToken = + ((v) => v != null ? v as String : null)(json['access_token']), + deviceId = ((v) => v != null ? v as String : null)(json['device_id']), + homeServer = + ((v) => v != null ? v as String : null)(json['home_server']), + userId = ((v) => v != null ? v as String : null)(json['user_id']), + wellKnown = ((v) => v != null + ? DiscoveryInformation.fromJson(v) + : null)(json['well_known']); + Map toJson() { + final accessToken = this.accessToken; + final deviceId = this.deviceId; + final homeServer = this.homeServer; + final userId = this.userId; + final wellKnown = this.wellKnown; + return { + if (accessToken != null) 'access_token': accessToken, + if (deviceId != null) 'device_id': deviceId, + if (homeServer != null) 'home_server': homeServer, + if (userId != null) 'user_id': userId, + if (wellKnown != null) 'well_known': wellKnown.toJson(), + }; + } + + /// An access token for the account. + /// This access token can then be used to authorize other requests. + String? accessToken; + + /// ID of the logged-in device. Will be the same as the + /// corresponding parameter in the request, if one was specified. + String? deviceId; + + /// The server_name of the homeserver on which the account has + /// been registered. + /// + /// **Deprecated**. Clients should extract the server_name from + /// `user_id` (by splitting at the first colon) if they require + /// it. Note also that `homeserver` is not spelt this way. + String? homeServer; + + /// The fully-qualified Matrix ID for the account. + String? userId; + + /// Optional client configuration provided by the server. If present, + /// clients SHOULD use the provided object to reconfigure themselves, + /// optionally validating the URLs within. This object takes the same + /// form as the one returned from .well-known autodiscovery. + DiscoveryInformation? wellKnown; +} + +@_NameSource('spec') +class Notification { + Notification({ + required this.actions, + required this.event, + this.profileTag, + required this.read, + required this.roomId, + required this.ts, + }); + + Notification.fromJson(Map json) + : actions = (json['actions'] as List).map((v) => v as dynamic).toList(), + event = MatrixEvent.fromJson(json['event']), + profileTag = + ((v) => v != null ? v as String : null)(json['profile_tag']), + read = json['read'] as bool, + roomId = json['room_id'] as String, + ts = json['ts'] as int; + Map toJson() { + final profileTag = this.profileTag; + return { + 'actions': actions.map((v) => v).toList(), + 'event': event.toJson(), + if (profileTag != null) 'profile_tag': profileTag, + 'read': read, + 'room_id': roomId, + 'ts': ts, + }; + } + + /// The action(s) to perform when the conditions for this rule are met. + /// See [Push Rules: API](https://spec.matrix.org/unstable/client-server-api/#push-rules-api). + List actions; + + /// The Event object for the event that triggered the notification. + MatrixEvent event; + + /// The profile tag of the rule that matched this event. + String? profileTag; + + /// Indicates whether the user has sent a read receipt indicating + /// that they have read this message. + bool read; + + /// The ID of the room in which the event was posted. + String roomId; + + /// The unix timestamp at which the event notification was sent, + /// in milliseconds. + int ts; +} + +@_NameSource('generated') +class GetNotificationsResponse { + GetNotificationsResponse({ + this.nextToken, + required this.notifications, + }); + + GetNotificationsResponse.fromJson(Map json) + : nextToken = ((v) => v != null ? v as String : null)(json['next_token']), + notifications = (json['notifications'] as List) + .map((v) => Notification.fromJson(v)) + .toList(); + Map toJson() { + final nextToken = this.nextToken; + return { + if (nextToken != null) 'next_token': nextToken, + 'notifications': notifications.map((v) => v.toJson()).toList(), + }; + } + + /// The token to supply in the `from` param of the next + /// `/notifications` request in order to request more + /// events. If this is absent, there are no more results. + String? nextToken; + + /// The list of events that triggered notifications. + List notifications; +} + +@_NameSource('rule override generated') +enum PresenceType { offline, online, unavailable } + +@_NameSource('generated') +class GetPresenceResponse { + GetPresenceResponse({ + this.currentlyActive, + this.lastActiveAgo, + required this.presence, + this.statusMsg, + }); + + GetPresenceResponse.fromJson(Map json) + : currentlyActive = + ((v) => v != null ? v as bool : null)(json['currently_active']), + lastActiveAgo = + ((v) => v != null ? v as int : null)(json['last_active_ago']), + presence = { + 'online': PresenceType.online, + 'offline': PresenceType.offline, + 'unavailable': PresenceType.unavailable + }[json['presence']]!, + statusMsg = ((v) => v != null ? v as String : null)(json['status_msg']); + Map toJson() { + final currentlyActive = this.currentlyActive; + final lastActiveAgo = this.lastActiveAgo; + final statusMsg = this.statusMsg; + return { + if (currentlyActive != null) 'currently_active': currentlyActive, + if (lastActiveAgo != null) 'last_active_ago': lastActiveAgo, + 'presence': { + PresenceType.online: 'online', + PresenceType.offline: 'offline', + PresenceType.unavailable: 'unavailable' + }[presence]!, + if (statusMsg != null) 'status_msg': statusMsg, + }; + } + + /// Whether the user is currently active + bool? currentlyActive; + + /// The length of time in milliseconds since an action was performed + /// by this user. + int? lastActiveAgo; + + /// This user's presence. + PresenceType presence; + + /// The state message for this user if one was set. + String? statusMsg; +} + +@_NameSource('rule override generated') +class ProfileInformation { + ProfileInformation({ + this.avatarUrl, + this.displayname, + }); + + ProfileInformation.fromJson(Map json) + : avatarUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + displayname = + ((v) => v != null ? v as String : null)(json['displayname']); + Map toJson() { + final avatarUrl = this.avatarUrl; + final displayname = this.displayname; + return { + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + if (displayname != null) 'displayname': displayname, + }; + } + + /// The user's avatar URL if they have set one, otherwise not present. + Uri? avatarUrl; + + /// The user's display name if they have set one, otherwise not present. + String? displayname; +} + +@_NameSource('spec') +class PublicRoomsChunk { + PublicRoomsChunk({ + this.aliases, + this.avatarUrl, + this.canonicalAlias, + required this.guestCanJoin, + this.joinRule, + this.name, + required this.numJoinedMembers, + required this.roomId, + this.topic, + required this.worldReadable, + }); + + PublicRoomsChunk.fromJson(Map json) + : aliases = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['aliases']), + avatarUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + canonicalAlias = + ((v) => v != null ? v as String : null)(json['canonical_alias']), + guestCanJoin = json['guest_can_join'] as bool, + joinRule = ((v) => v != null ? v as String : null)(json['join_rule']), + name = ((v) => v != null ? v as String : null)(json['name']), + numJoinedMembers = json['num_joined_members'] as int, + roomId = json['room_id'] as String, + topic = ((v) => v != null ? v as String : null)(json['topic']), + worldReadable = json['world_readable'] as bool; + Map toJson() { + final aliases = this.aliases; + final avatarUrl = this.avatarUrl; + final canonicalAlias = this.canonicalAlias; + final joinRule = this.joinRule; + final name = this.name; + final topic = this.topic; + return { + if (aliases != null) 'aliases': aliases.map((v) => v).toList(), + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + if (canonicalAlias != null) 'canonical_alias': canonicalAlias, + 'guest_can_join': guestCanJoin, + if (joinRule != null) 'join_rule': joinRule, + if (name != null) 'name': name, + 'num_joined_members': numJoinedMembers, + 'room_id': roomId, + if (topic != null) 'topic': topic, + 'world_readable': worldReadable, + }; + } + + /// Aliases of the room. May be empty. + List? aliases; + + /// The URL for the room's avatar, if one is set. + Uri? avatarUrl; + + /// The canonical alias of the room, if any. + String? canonicalAlias; + + /// 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. + bool guestCanJoin; + + /// The room's join rule. When not present, the room is assumed to + /// be `public`. Note that rooms with `invite` join rules are not + /// expected here, but rooms with `knock` rules are given their + /// near-public nature. + String? joinRule; + + /// The name of the room, if any. + String? name; + + /// The number of members joined to the room. + int numJoinedMembers; + + /// The ID of the room. + String roomId; + + /// The topic of the room, if any. + String? topic; + + /// Whether the room may be viewed by guest users without joining. + bool worldReadable; +} + +/// A list of the rooms on the server. +@_NameSource('generated') +class GetPublicRoomsResponse { + GetPublicRoomsResponse({ + required this.chunk, + this.nextBatch, + this.prevBatch, + this.totalRoomCountEstimate, + }); + + GetPublicRoomsResponse.fromJson(Map json) + : chunk = (json['chunk'] as List) + .map((v) => PublicRoomsChunk.fromJson(v)) + .toList(), + nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), + prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']), + totalRoomCountEstimate = ((v) => + v != null ? v as int : null)(json['total_room_count_estimate']); + Map toJson() { + final nextBatch = this.nextBatch; + final prevBatch = this.prevBatch; + final totalRoomCountEstimate = this.totalRoomCountEstimate; + return { + 'chunk': chunk.map((v) => v.toJson()).toList(), + if (nextBatch != null) 'next_batch': nextBatch, + if (prevBatch != null) 'prev_batch': prevBatch, + if (totalRoomCountEstimate != null) + 'total_room_count_estimate': totalRoomCountEstimate, + }; + } + + /// A paginated chunk of public rooms. + List chunk; + + /// A pagination token for the response. The absence of this token + /// means there are no more results to fetch and the client should + /// stop paginating. + String? nextBatch; + + /// A pagination token that allows fetching previous results. The + /// absence of this token means there are no results before this + /// batch, i.e. this is the first batch. + String? prevBatch; + + /// An estimate on the total number of public rooms, if the + /// server has an estimate. + int? totalRoomCountEstimate; +} + +@_NameSource('rule override spec') +class PublicRoomQueryFilter { + PublicRoomQueryFilter({ + this.genericSearchTerm, + }); + + PublicRoomQueryFilter.fromJson(Map json) + : genericSearchTerm = ((v) => + v != null ? v as String : null)(json['generic_search_term']); + Map toJson() { + final genericSearchTerm = this.genericSearchTerm; + return { + if (genericSearchTerm != null) 'generic_search_term': genericSearchTerm, + }; + } + + /// A string to search for in the room metadata, e.g. name, + /// topic, canonical alias etc. (Optional). + String? genericSearchTerm; +} + +/// A list of the rooms on the server. +@_NameSource('generated') +class QueryPublicRoomsResponse { + QueryPublicRoomsResponse({ + required this.chunk, + this.nextBatch, + this.prevBatch, + this.totalRoomCountEstimate, + }); + + QueryPublicRoomsResponse.fromJson(Map json) + : chunk = (json['chunk'] as List) + .map((v) => PublicRoomsChunk.fromJson(v)) + .toList(), + nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), + prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']), + totalRoomCountEstimate = ((v) => + v != null ? v as int : null)(json['total_room_count_estimate']); + Map toJson() { + final nextBatch = this.nextBatch; + final prevBatch = this.prevBatch; + final totalRoomCountEstimate = this.totalRoomCountEstimate; + return { + 'chunk': chunk.map((v) => v.toJson()).toList(), + if (nextBatch != null) 'next_batch': nextBatch, + if (prevBatch != null) 'prev_batch': prevBatch, + if (totalRoomCountEstimate != null) + 'total_room_count_estimate': totalRoomCountEstimate, + }; + } + + /// A paginated chunk of public rooms. + List chunk; + + /// A pagination token for the response. The absence of this token + /// means there are no more results to fetch and the client should + /// stop paginating. + String? nextBatch; + + /// A pagination token that allows fetching previous results. The + /// absence of this token means there are no results before this + /// batch, i.e. this is the first batch. + String? prevBatch; + + /// An estimate on the total number of public rooms, if the + /// server has an estimate. + int? totalRoomCountEstimate; +} + +@_NameSource('spec') +class PusherData { + PusherData({ + this.format, + this.url, + }); + + PusherData.fromJson(Map json) + : format = ((v) => v != null ? v as String : null)(json['format']), + url = ((v) => v != null ? Uri.parse(v) : null)(json['url']); + Map toJson() { + final format = this.format; + final url = this.url; + return { + if (format != null) 'format': format, + if (url != null) 'url': url.toString(), + }; + } + + /// The format to use when sending notifications to the Push + /// Gateway. + String? format; + + /// Required if `kind` is `http`. The URL to use to send + /// notifications to. + Uri? url; +} + +@_NameSource('spec') +class Pusher { + Pusher({ + required this.appDisplayName, + required this.appId, + required this.data, + required this.deviceDisplayName, + required this.kind, + required this.lang, + this.profileTag, + required this.pushkey, + }); + + Pusher.fromJson(Map json) + : appDisplayName = json['app_display_name'] as String, + appId = json['app_id'] as String, + data = PusherData.fromJson(json['data']), + deviceDisplayName = json['device_display_name'] as String, + kind = json['kind'] as String, + lang = json['lang'] as String, + profileTag = + ((v) => v != null ? v as String : null)(json['profile_tag']), + pushkey = json['pushkey'] as String; + Map toJson() { + final profileTag = this.profileTag; + return { + 'app_display_name': appDisplayName, + 'app_id': appId, + 'data': data.toJson(), + 'device_display_name': deviceDisplayName, + 'kind': kind, + 'lang': lang, + if (profileTag != null) 'profile_tag': profileTag, + 'pushkey': pushkey, + }; + } + + /// A string that will allow the user to identify what application + /// owns this pusher. + String appDisplayName; + + /// This is a reverse-DNS style identifier for the application. + /// Max length, 64 chars. + String appId; + + /// A dictionary of information for the pusher implementation + /// itself. + PusherData data; + + /// A string that will allow the user to identify what device owns + /// this pusher. + String deviceDisplayName; + + /// The kind of pusher. `"http"` is a pusher that + /// sends HTTP pokes. + String kind; + + /// The preferred language for receiving notifications (e.g. 'en' + /// or 'en-US') + String lang; + + /// This string determines which set of device specific rules this + /// pusher executes. + String? profileTag; + + /// This is a unique identifier for this pusher. See `/set` for + /// more detail. + /// Max length, 512 bytes. + String pushkey; +} + +@_NameSource('spec') +class PushCondition { + PushCondition({ + this.is$, + this.key, + required this.kind, + this.pattern, + }); + + PushCondition.fromJson(Map json) + : is$ = ((v) => v != null ? v as String : null)(json['is']), + key = ((v) => v != null ? v as String : null)(json['key']), + kind = json['kind'] as String, + pattern = ((v) => v != null ? v as String : null)(json['pattern']); + Map toJson() { + final is$ = this.is$; + final key = this.key; + final pattern = this.pattern; + return { + if (is$ != null) 'is': is$, + if (key != null) 'key': key, + 'kind': kind, + if (pattern != null) 'pattern': pattern, + }; + } + + /// Required for `room_member_count` conditions. A decimal integer + /// optionally prefixed by one of, ==, <, >, >= or <=. A prefix of < matches + /// rooms where the member count is strictly less than the given number and + /// so forth. If no prefix is present, this parameter defaults to ==. + String? is$; + + /// Required for `event_match` conditions. The dot-separated field of the + /// event to match. + /// + /// Required for `sender_notification_permission` conditions. The field in + /// the power level event the user needs a minimum power level for. Fields + /// must be specified under the `notifications` property in the power level + /// event's `content`. + String? key; + + /// The kind of condition to apply. See [conditions](https://spec.matrix.org/unstable/client-server-api/#conditions) for + /// more information on the allowed kinds and how they work. + String kind; + + /// Required for `event_match` conditions. The glob-style pattern to + /// match against. Patterns with no special glob characters should be + /// treated as having asterisks prepended and appended when testing the + /// condition. + String? pattern; +} + +@_NameSource('spec') +class PushRule { + PushRule({ + required this.actions, + this.conditions, + required this.default$, + required this.enabled, + this.pattern, + required this.ruleId, + }); + + PushRule.fromJson(Map json) + : actions = (json['actions'] as List).map((v) => v as dynamic).toList(), + conditions = ((v) => v != null + ? (v as List).map((v) => PushCondition.fromJson(v)).toList() + : null)(json['conditions']), + default$ = json['default'] as bool, + enabled = json['enabled'] as bool, + pattern = ((v) => v != null ? v as String : null)(json['pattern']), + ruleId = json['rule_id'] as String; + Map toJson() { + final conditions = this.conditions; + final pattern = this.pattern; + return { + 'actions': actions.map((v) => v).toList(), + if (conditions != null) + 'conditions': conditions.map((v) => v.toJson()).toList(), + 'default': default$, + 'enabled': enabled, + if (pattern != null) 'pattern': pattern, + 'rule_id': ruleId, + }; + } + + /// The actions to perform when this rule is matched. + List actions; + + /// 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. + List? conditions; + + /// Whether this is a default rule, or has been set explicitly. + bool default$; + + /// Whether the push rule is enabled or not. + bool enabled; + + /// The glob-style pattern to match against. Only applicable to `content` + /// rules. + String? pattern; + + /// The ID of this rule. + String ruleId; +} + +@_NameSource('rule override generated') +class PushRuleSet { + PushRuleSet({ + this.content, + this.override, + this.room, + this.sender, + this.underride, + }); + + PushRuleSet.fromJson(Map json) + : content = ((v) => v != null + ? (v as List).map((v) => PushRule.fromJson(v)).toList() + : null)(json['content']), + override = ((v) => v != null + ? (v as List).map((v) => PushRule.fromJson(v)).toList() + : null)(json['override']), + room = ((v) => v != null + ? (v as List).map((v) => PushRule.fromJson(v)).toList() + : null)(json['room']), + sender = ((v) => v != null + ? (v as List).map((v) => PushRule.fromJson(v)).toList() + : null)(json['sender']), + underride = ((v) => v != null + ? (v as List).map((v) => PushRule.fromJson(v)).toList() + : null)(json['underride']); + Map toJson() { + final content = this.content; + final override = this.override; + final room = this.room; + final sender = this.sender; + final underride = this.underride; + return { + if (content != null) 'content': content.map((v) => v.toJson()).toList(), + if (override != null) + 'override': override.map((v) => v.toJson()).toList(), + if (room != null) 'room': room.map((v) => v.toJson()).toList(), + if (sender != null) 'sender': sender.map((v) => v.toJson()).toList(), + if (underride != null) + 'underride': underride.map((v) => v.toJson()).toList(), + }; + } + + List? content; + + List? override; + + List? room; + + List? sender; + + List? underride; +} + +@_NameSource('rule override generated') +enum PushRuleKind { content, override, room, sender, underride } + +@_NameSource('rule override generated') +enum AccountKind { guest, user } + +@_NameSource('generated') +class RegisterResponse { + RegisterResponse({ + this.accessToken, + this.deviceId, + this.homeServer, + required this.userId, + }); + + RegisterResponse.fromJson(Map json) + : accessToken = + ((v) => v != null ? v as String : null)(json['access_token']), + deviceId = ((v) => v != null ? v as String : null)(json['device_id']), + homeServer = + ((v) => v != null ? v as String : null)(json['home_server']), + userId = json['user_id'] as String; + Map toJson() { + final accessToken = this.accessToken; + final deviceId = this.deviceId; + final homeServer = this.homeServer; + return { + if (accessToken != null) 'access_token': accessToken, + if (deviceId != null) 'device_id': deviceId, + if (homeServer != null) 'home_server': homeServer, + 'user_id': userId, + }; + } + + /// An access token for the account. + /// This access token can then be used to authorize other requests. + /// Required if the `inhibit_login` option is false. + String? accessToken; + + /// ID of the registered device. Will be the same as the + /// corresponding parameter in the request, if one was specified. + /// Required if the `inhibit_login` option is false. + String? deviceId; + + /// The server_name of the homeserver on which the account has + /// been registered. + /// + /// **Deprecated**. Clients should extract the server_name from + /// `user_id` (by splitting at the first colon) if they require + /// it. Note also that `homeserver` is not spelt this way. + String? homeServer; + + /// The fully-qualified Matrix user ID (MXID) that has been registered. + /// + /// Any user ID returned by this API must conform to the grammar given in the + /// [Matrix specification](https://spec.matrix.org/unstable/appendices/#user-identifiers). + String userId; +} + +/// The key data +@_NameSource('spec') +class KeyBackupData { + KeyBackupData({ + required this.firstMessageIndex, + required this.forwardedCount, + required this.isVerified, + required this.sessionData, + }); + + KeyBackupData.fromJson(Map json) + : firstMessageIndex = json['first_message_index'] as int, + forwardedCount = json['forwarded_count'] as int, + isVerified = json['is_verified'] as bool, + sessionData = json['session_data'] as Map; + Map toJson() => { + 'first_message_index': firstMessageIndex, + 'forwarded_count': forwardedCount, + 'is_verified': isVerified, + 'session_data': sessionData, + }; + + /// The index of the first message in the session that the key can decrypt. + int firstMessageIndex; + + /// The number of times this key has been forwarded via key-sharing between devices. + int forwardedCount; + + /// Whether the device backing up the key verified the device that the key + /// is from. + bool isVerified; + + /// Algorithm-dependent data. See the documentation for the backup + /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the + /// expected format of the data. + Map sessionData; +} + +/// The backed up keys for a room. +@_NameSource('spec') +class RoomKeyBackup { + RoomKeyBackup({ + required this.sessions, + }); + + RoomKeyBackup.fromJson(Map json) + : sessions = (json['sessions'] as Map) + .map((k, v) => MapEntry(k, KeyBackupData.fromJson(v))); + Map toJson() => { + 'sessions': sessions.map((k, v) => MapEntry(k, v.toJson())), + }; + + /// A map of session IDs to key data. + Map sessions; +} + +@_NameSource('rule override generated') +class RoomKeys { + RoomKeys({ + required this.rooms, + }); + + RoomKeys.fromJson(Map json) + : rooms = (json['rooms'] as Map) + .map((k, v) => MapEntry(k, RoomKeyBackup.fromJson(v))); + Map toJson() => { + 'rooms': rooms.map((k, v) => MapEntry(k, v.toJson())), + }; + + /// A map of room IDs to room key backup data. + Map rooms; +} + +@_NameSource('generated') +class PostRoomKeysKeyResponse { + PostRoomKeysKeyResponse({ + required this.count, + required this.etag, + }); + + PostRoomKeysKeyResponse.fromJson(Map json) + : count = json['count'] as int, + etag = json['etag'] as String; + Map toJson() => { + 'count': count, + 'etag': etag, + }; + + /// The number of keys stored in the backup + int count; + + /// The new etag value representing stored keys in the backup. + /// See `GET /room_keys/version/{version}` for more details. + String etag; +} + +@_NameSource('generated') +class PostRoomKeysKeyRoomIdResponse { + PostRoomKeysKeyRoomIdResponse({ + required this.count, + required this.etag, + }); + + PostRoomKeysKeyRoomIdResponse.fromJson(Map json) + : count = json['count'] as int, + etag = json['etag'] as String; + Map toJson() => { + 'count': count, + 'etag': etag, + }; + + /// The number of keys stored in the backup + int count; + + /// The new etag value representing stored keys in the backup. + /// See `GET /room_keys/version/{version}` for more details. + String etag; +} + +@_NameSource('generated') +class PostRoomKeysKeyRoomIdSessionIdResponse { + PostRoomKeysKeyRoomIdSessionIdResponse({ + required this.count, + required this.etag, + }); + + PostRoomKeysKeyRoomIdSessionIdResponse.fromJson(Map json) + : count = json['count'] as int, + etag = json['etag'] as String; + Map toJson() => { + 'count': count, + 'etag': etag, + }; + + /// The number of keys stored in the backup + int count; + + /// The new etag value representing stored keys in the backup. + /// See `GET /room_keys/version/{version}` for more details. + String etag; +} + +@_NameSource('rule override generated') +enum BackupAlgorithm { mMegolmBackupV1Curve25519AesSha2 } + +@_NameSource('generated') +class GetRoomKeysVersionCurrentResponse { + GetRoomKeysVersionCurrentResponse({ + required this.algorithm, + required this.authData, + required this.count, + required this.etag, + required this.version, + }); + + GetRoomKeysVersionCurrentResponse.fromJson(Map json) + : algorithm = { + 'm.megolm_backup.v1.curve25519-aes-sha2': + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 + }[json['algorithm']]!, + authData = json['auth_data'] as Map, + count = json['count'] as int, + etag = json['etag'] as String, + version = json['version'] as String; + Map toJson() => { + 'algorithm': { + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: + 'm.megolm_backup.v1.curve25519-aes-sha2' + }[algorithm]!, + 'auth_data': authData, + 'count': count, + 'etag': etag, + 'version': version, + }; + + /// The algorithm used for storing backups. + BackupAlgorithm algorithm; + + /// Algorithm-dependent data. See the documentation for the backup + /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the + /// expected format of the data. + Map authData; + + /// The number of keys stored in the backup. + int count; + + /// An opaque string representing stored keys in the backup. + /// Clients can compare it with the `etag` value they received + /// in the request of their last key storage request. If not + /// equal, another client has modified the backup. + String etag; + + /// The backup version. + String version; +} + +@_NameSource('generated') +class GetRoomKeysVersionResponse { + GetRoomKeysVersionResponse({ + required this.algorithm, + required this.authData, + required this.count, + required this.etag, + required this.version, + }); + + GetRoomKeysVersionResponse.fromJson(Map json) + : algorithm = { + 'm.megolm_backup.v1.curve25519-aes-sha2': + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 + }[json['algorithm']]!, + authData = json['auth_data'] as Map, + count = json['count'] as int, + etag = json['etag'] as String, + version = json['version'] as String; + Map toJson() => { + 'algorithm': { + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: + 'm.megolm_backup.v1.curve25519-aes-sha2' + }[algorithm]!, + 'auth_data': authData, + 'count': count, + 'etag': etag, + 'version': version, + }; + + /// The algorithm used for storing backups. + BackupAlgorithm algorithm; + + /// Algorithm-dependent data. See the documentation for the backup + /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the + /// expected format of the data. + Map authData; + + /// The number of keys stored in the backup. + int count; + + /// An opaque string representing stored keys in the backup. + /// Clients can compare it with the `etag` value they received + /// in the request of their last key storage request. If not + /// equal, another client has modified the backup. + String etag; + + /// The backup version. + String version; +} + +/// The events and state surrounding the requested event. +@_NameSource('rule override generated') +class EventContext { + EventContext({ + this.end, + this.event, + this.eventsAfter, + this.eventsBefore, + this.start, + this.state, + }); + + EventContext.fromJson(Map json) + : end = ((v) => v != null ? v as String : null)(json['end']), + event = + ((v) => v != null ? MatrixEvent.fromJson(v) : null)(json['event']), + eventsAfter = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['events_after']), + eventsBefore = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['events_before']), + start = ((v) => v != null ? v as String : null)(json['start']), + state = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['state']); + Map toJson() { + final end = this.end; + final event = this.event; + final eventsAfter = this.eventsAfter; + final eventsBefore = this.eventsBefore; + final start = this.start; + final state = this.state; + return { + if (end != null) 'end': end, + if (event != null) 'event': event.toJson(), + if (eventsAfter != null) + 'events_after': eventsAfter.map((v) => v.toJson()).toList(), + if (eventsBefore != null) + 'events_before': eventsBefore.map((v) => v.toJson()).toList(), + if (start != null) 'start': start, + if (state != null) 'state': state.map((v) => v.toJson()).toList(), + }; + } + + /// A token that can be used to paginate forwards with. + String? end; + + /// Details of the requested event. + MatrixEvent? event; + + /// A list of room events that happened just after the + /// requested event, in chronological order. + List? eventsAfter; + + /// A list of room events that happened just before the + /// requested event, in reverse-chronological order. + List? eventsBefore; + + /// A token that can be used to paginate backwards with. + String? start; + + /// The state of the room at the last event returned. + List? state; +} + +@_NameSource('spec') +class RoomMember { + RoomMember({ + this.avatarUrl, + this.displayName, + }); + + RoomMember.fromJson(Map json) + : avatarUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + displayName = + ((v) => v != null ? v as String : null)(json['display_name']); + Map toJson() { + final avatarUrl = this.avatarUrl; + final displayName = this.displayName; + return { + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + if (displayName != null) 'display_name': displayName, + }; + } + + /// The mxc avatar url of the user this object is representing. + Uri? avatarUrl; + + /// The display name of the user this object is representing. + String? displayName; +} + +@_NameSource('(generated, rule override generated)') +enum Membership { ban, invite, join, leave } + +@_NameSource('rule override generated') +enum Direction { b, f } + +/// A list of messages with a new token to request more. +@_NameSource('generated') +class GetRoomEventsResponse { + GetRoomEventsResponse({ + this.chunk, + this.end, + this.start, + this.state, + }); + + GetRoomEventsResponse.fromJson(Map json) + : chunk = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['chunk']), + end = ((v) => v != null ? v as String : null)(json['end']), + start = ((v) => v != null ? v as String : null)(json['start']), + state = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['state']); + Map toJson() { + final chunk = this.chunk; + final end = this.end; + final start = this.start; + final state = this.state; + return { + if (chunk != null) 'chunk': chunk.map((v) => v.toJson()).toList(), + if (end != null) 'end': end, + if (start != null) 'start': start, + if (state != null) 'state': state.map((v) => v.toJson()).toList(), + }; + } + + /// A list of room events. The order depends on the `dir` parameter. + /// For `dir=b` events will be in reverse-chronological order, + /// for `dir=f` in chronological order, so that events start + /// at the `from` point. + List? chunk; + + /// The token the pagination ends at. If `dir=b` this token should + /// be used again to request even earlier events. + String? end; + + /// The token the pagination starts from. If `dir=b` this will be + /// the token supplied in `from`. + String? start; + + /// A list of state events relevant to showing the `chunk`. For example, if + /// `lazy_load_members` is enabled in the filter then this may contain + /// the membership events for the senders of events in the `chunk`. + /// + /// Unless `include_redundant_members` is `true`, the server + /// may remove membership events which would have already been + /// sent to the client in prior calls to this endpoint, assuming + /// the membership of those members has not changed. + List? state; +} + +@_NameSource('generated') +enum ReceiptType { mRead } + +@_NameSource('spec') +class IncludeEventContext { + IncludeEventContext({ + this.afterLimit, + this.beforeLimit, + this.includeProfile, + }); + + IncludeEventContext.fromJson(Map json) + : afterLimit = ((v) => v != null ? v as int : null)(json['after_limit']), + beforeLimit = + ((v) => v != null ? v as int : null)(json['before_limit']), + includeProfile = + ((v) => v != null ? v as bool : null)(json['include_profile']); + Map toJson() { + final afterLimit = this.afterLimit; + final beforeLimit = this.beforeLimit; + final includeProfile = this.includeProfile; + return { + if (afterLimit != null) 'after_limit': afterLimit, + if (beforeLimit != null) 'before_limit': beforeLimit, + if (includeProfile != null) 'include_profile': includeProfile, + }; + } + + /// How many events after the result are + /// returned. By default, this is `5`. + int? afterLimit; + + /// How many events before the result are + /// returned. By default, this is `5`. + int? beforeLimit; + + /// Requests that the server returns the + /// historic profile information for the users + /// that sent the events that were returned. + /// By default, this is `false`. + bool? includeProfile; +} + +@_NameSource('spec') +class EventFilter { + EventFilter({ + this.limit, + this.notSenders, + this.notTypes, + this.senders, + this.types, + }); + + EventFilter.fromJson(Map json) + : limit = ((v) => v != null ? v as int : null)(json['limit']), + notSenders = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_senders']), + notTypes = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_types']), + senders = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['senders']), + types = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['types']); + Map toJson() { + final limit = this.limit; + final notSenders = this.notSenders; + final notTypes = this.notTypes; + final senders = this.senders; + final types = this.types; + return { + if (limit != null) 'limit': limit, + if (notSenders != null) 'not_senders': notSenders.map((v) => v).toList(), + if (notTypes != null) 'not_types': notTypes.map((v) => v).toList(), + if (senders != null) 'senders': senders.map((v) => v).toList(), + if (types != null) 'types': types.map((v) => v).toList(), + }; + } + + /// The maximum number of events to return. + int? limit; + + /// 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. + List? notSenders; + + /// 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. + List? notTypes; + + /// A list of senders IDs to include. If this list is absent then all senders are included. + List? senders; + + /// 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. + List? types; +} + +@_NameSource('spec') +class RoomEventFilter { + RoomEventFilter({ + this.containsUrl, + this.includeRedundantMembers, + this.lazyLoadMembers, + this.notRooms, + this.rooms, + }); + + RoomEventFilter.fromJson(Map json) + : containsUrl = + ((v) => v != null ? v as bool : null)(json['contains_url']), + includeRedundantMembers = ((v) => + v != null ? v as bool : null)(json['include_redundant_members']), + lazyLoadMembers = + ((v) => v != null ? v as bool : null)(json['lazy_load_members']), + notRooms = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_rooms']), + rooms = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['rooms']); + Map toJson() { + final containsUrl = this.containsUrl; + final includeRedundantMembers = this.includeRedundantMembers; + final lazyLoadMembers = this.lazyLoadMembers; + final notRooms = this.notRooms; + final rooms = this.rooms; + return { + if (containsUrl != null) 'contains_url': containsUrl, + if (includeRedundantMembers != null) + 'include_redundant_members': includeRedundantMembers, + if (lazyLoadMembers != null) 'lazy_load_members': lazyLoadMembers, + if (notRooms != null) 'not_rooms': notRooms.map((v) => v).toList(), + if (rooms != null) 'rooms': rooms.map((v) => v).toList(), + }; + } + + /// If `true`, includes only events with a `url` key in their content. If `false`, excludes those events. If omitted, `url` key is not considered for filtering. + bool? containsUrl; + + /// If `true`, sends all membership events for all events, even if they have already + /// been sent to the client. Does not + /// apply unless `lazy_load_members` is `true`. See + /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) + /// for more information. Defaults to `false`. + bool? includeRedundantMembers; + + /// If `true`, enables lazy-loading of membership events. See + /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) + /// for more information. Defaults to `false`. + bool? lazyLoadMembers; + + /// 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. + List? notRooms; + + /// A list of room IDs to include. If this list is absent then all rooms are included. + List? rooms; +} + +@_NameSource('rule override generated') +class SearchFilter implements EventFilter, RoomEventFilter { + SearchFilter({ + this.limit, + this.notSenders, + this.notTypes, + this.senders, + this.types, + this.containsUrl, + this.includeRedundantMembers, + this.lazyLoadMembers, + this.notRooms, + this.rooms, + }); + + SearchFilter.fromJson(Map json) + : limit = ((v) => v != null ? v as int : null)(json['limit']), + notSenders = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_senders']), + notTypes = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_types']), + senders = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['senders']), + types = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['types']), + containsUrl = + ((v) => v != null ? v as bool : null)(json['contains_url']), + includeRedundantMembers = ((v) => + v != null ? v as bool : null)(json['include_redundant_members']), + lazyLoadMembers = + ((v) => v != null ? v as bool : null)(json['lazy_load_members']), + notRooms = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_rooms']), + rooms = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['rooms']); + Map toJson() { + final limit = this.limit; + final notSenders = this.notSenders; + final notTypes = this.notTypes; + final senders = this.senders; + final types = this.types; + final containsUrl = this.containsUrl; + final includeRedundantMembers = this.includeRedundantMembers; + final lazyLoadMembers = this.lazyLoadMembers; + final notRooms = this.notRooms; + final rooms = this.rooms; + return { + if (limit != null) 'limit': limit, + if (notSenders != null) 'not_senders': notSenders.map((v) => v).toList(), + if (notTypes != null) 'not_types': notTypes.map((v) => v).toList(), + if (senders != null) 'senders': senders.map((v) => v).toList(), + if (types != null) 'types': types.map((v) => v).toList(), + if (containsUrl != null) 'contains_url': containsUrl, + if (includeRedundantMembers != null) + 'include_redundant_members': includeRedundantMembers, + if (lazyLoadMembers != null) 'lazy_load_members': lazyLoadMembers, + if (notRooms != null) 'not_rooms': notRooms.map((v) => v).toList(), + if (rooms != null) 'rooms': rooms.map((v) => v).toList(), + }; + } + + /// The maximum number of events to return. + int? limit; + + /// 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. + List? notSenders; + + /// 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. + List? notTypes; + + /// A list of senders IDs to include. If this list is absent then all senders are included. + List? senders; + + /// 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. + List? types; + + /// If `true`, includes only events with a `url` key in their content. If `false`, excludes those events. If omitted, `url` key is not considered for filtering. + bool? containsUrl; + + /// If `true`, sends all membership events for all events, even if they have already + /// been sent to the client. Does not + /// apply unless `lazy_load_members` is `true`. See + /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) + /// for more information. Defaults to `false`. + bool? includeRedundantMembers; + + /// If `true`, enables lazy-loading of membership events. See + /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) + /// for more information. Defaults to `false`. + bool? lazyLoadMembers; + + /// 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. + List? notRooms; + + /// A list of room IDs to include. If this list is absent then all rooms are included. + List? rooms; +} + +@_NameSource('rule override generated') +enum GroupKey { roomId, sender } + +/// Configuration for group. +@_NameSource('spec') +class Group { + Group({ + this.key, + }); + + Group.fromJson(Map json) + : key = ((v) => v != null + ? {'room_id': GroupKey.roomId, 'sender': GroupKey.sender}[v]! + : null)(json['key']); + Map toJson() { + final key = this.key; + return { + if (key != null) + 'key': {GroupKey.roomId: 'room_id', GroupKey.sender: 'sender'}[key]!, + }; + } + + /// Key that defines the group. + GroupKey? key; +} + +@_NameSource('spec') +class Groupings { + Groupings({ + this.groupBy, + }); + + Groupings.fromJson(Map json) + : groupBy = ((v) => v != null + ? (v as List).map((v) => Group.fromJson(v)).toList() + : null)(json['group_by']); + Map toJson() { + final groupBy = this.groupBy; + return { + if (groupBy != null) 'group_by': groupBy.map((v) => v.toJson()).toList(), + }; + } + + /// List of groups to request. + List? groupBy; +} + +@_NameSource('rule override generated') +enum KeyKind { contentBody, contentName, contentTopic } + +@_NameSource('rule override generated') +enum SearchOrder { rank, recent } + +@_NameSource('spec') +class RoomEventsCriteria { + RoomEventsCriteria({ + this.eventContext, + this.filter, + this.groupings, + this.includeState, + this.keys, + this.orderBy, + required this.searchTerm, + }); + + RoomEventsCriteria.fromJson(Map json) + : eventContext = ((v) => v != null + ? IncludeEventContext.fromJson(v) + : null)(json['event_context']), + filter = ((v) => + v != null ? SearchFilter.fromJson(v) : null)(json['filter']), + groupings = ((v) => + v != null ? Groupings.fromJson(v) : null)(json['groupings']), + includeState = + ((v) => v != null ? v as bool : null)(json['include_state']), + keys = ((v) => v != null + ? (v as List) + .map((v) => { + 'content.body': KeyKind.contentBody, + 'content.name': KeyKind.contentName, + 'content.topic': KeyKind.contentTopic + }[v]!) + .toList() + : null)(json['keys']), + orderBy = ((v) => v != null + ? {'recent': SearchOrder.recent, 'rank': SearchOrder.rank}[v]! + : null)(json['order_by']), + searchTerm = json['search_term'] as String; + Map toJson() { + final eventContext = this.eventContext; + final filter = this.filter; + final groupings = this.groupings; + final includeState = this.includeState; + final keys = this.keys; + final orderBy = this.orderBy; + return { + if (eventContext != null) 'event_context': eventContext.toJson(), + if (filter != null) 'filter': filter.toJson(), + if (groupings != null) 'groupings': groupings.toJson(), + if (includeState != null) 'include_state': includeState, + if (keys != null) + 'keys': keys + .map((v) => { + KeyKind.contentBody: 'content.body', + KeyKind.contentName: 'content.name', + KeyKind.contentTopic: 'content.topic' + }[v]!) + .toList(), + if (orderBy != null) + 'order_by': { + SearchOrder.recent: 'recent', + SearchOrder.rank: 'rank' + }[orderBy]!, + 'search_term': searchTerm, + }; + } + + /// Configures whether any context for the events + /// returned are included in the response. + IncludeEventContext? eventContext; + + /// This takes a [filter](https://spec.matrix.org/unstable/client-server-api/#filtering). + SearchFilter? filter; + + /// Requests that the server partitions the result set + /// based on the provided list of keys. + Groupings? groupings; + + /// Requests the server return the current state for + /// each room returned. + bool? includeState; + + /// The keys to search. Defaults to all. + List? keys; + + /// The order in which to search for results. + /// By default, this is `"rank"`. + SearchOrder? orderBy; + + /// The string to search events for + String searchTerm; +} + +@_NameSource('spec') +class Categories { + Categories({ + this.roomEvents, + }); + + Categories.fromJson(Map json) + : roomEvents = ((v) => v != null ? RoomEventsCriteria.fromJson(v) : null)( + json['room_events']); + Map toJson() { + final roomEvents = this.roomEvents; + return { + if (roomEvents != null) 'room_events': roomEvents.toJson(), + }; + } + + /// Mapping of category name to search criteria. + RoomEventsCriteria? roomEvents; +} + +/// The results for a particular group value. +@_NameSource('spec') +class GroupValue { + GroupValue({ + this.nextBatch, + this.order, + this.results, + }); + + GroupValue.fromJson(Map json) + : nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), + order = ((v) => v != null ? v as int : null)(json['order']), + results = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['results']); + Map toJson() { + final nextBatch = this.nextBatch; + final order = this.order; + final results = this.results; + return { + if (nextBatch != null) 'next_batch': nextBatch, + if (order != null) 'order': order, + if (results != null) 'results': results.map((v) => v).toList(), + }; + } + + /// Token that can be used to get the next batch + /// of results in the group, by passing as the + /// `next_batch` parameter to the next call. If + /// this field is absent, there are no more + /// results in this group. + String? nextBatch; + + /// Key that can be used to order different + /// groups. + int? order; + + /// Which results are in this group. + List? results; +} + +@_NameSource('spec') +class UserProfile { + UserProfile({ + this.avatarUrl, + this.displayname, + }); + + UserProfile.fromJson(Map json) + : avatarUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + displayname = + ((v) => v != null ? v as String : null)(json['displayname']); + Map toJson() { + final avatarUrl = this.avatarUrl; + final displayname = this.displayname; + return { + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + if (displayname != null) 'displayname': displayname, + }; + } + + Uri? avatarUrl; + + String? displayname; +} + +@_NameSource('rule override spec') +class SearchResultsEventContext { + SearchResultsEventContext({ + this.end, + this.eventsAfter, + this.eventsBefore, + this.profileInfo, + this.start, + }); + + SearchResultsEventContext.fromJson(Map json) + : end = ((v) => v != null ? v as String : null)(json['end']), + eventsAfter = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['events_after']), + eventsBefore = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['events_before']), + profileInfo = ((v) => v != null + ? (v as Map) + .map((k, v) => MapEntry(k, UserProfile.fromJson(v))) + : null)(json['profile_info']), + start = ((v) => v != null ? v as String : null)(json['start']); + Map toJson() { + final end = this.end; + final eventsAfter = this.eventsAfter; + final eventsBefore = this.eventsBefore; + final profileInfo = this.profileInfo; + final start = this.start; + return { + if (end != null) 'end': end, + if (eventsAfter != null) + 'events_after': eventsAfter.map((v) => v.toJson()).toList(), + if (eventsBefore != null) + 'events_before': eventsBefore.map((v) => v.toJson()).toList(), + if (profileInfo != null) + 'profile_info': profileInfo.map((k, v) => MapEntry(k, v.toJson())), + if (start != null) 'start': start, + }; + } + + /// Pagination token for the end of the chunk + String? end; + + /// Events just after the result. + List? eventsAfter; + + /// Events just before the result. + List? eventsBefore; + + /// The historic profile information of the + /// users that sent the events returned. + /// + /// The `string` key is the user ID for which + /// the profile belongs to. + Map? profileInfo; + + /// Pagination token for the start of the chunk + String? start; +} + +/// The result object. +@_NameSource('spec') +class Result { + Result({ + this.context, + this.rank, + this.result, + }); + + Result.fromJson(Map json) + : context = ((v) => v != null + ? SearchResultsEventContext.fromJson(v) + : null)(json['context']), + rank = ((v) => v != null ? (v as num).toDouble() : null)(json['rank']), + result = + ((v) => v != null ? MatrixEvent.fromJson(v) : null)(json['result']); + Map toJson() { + final context = this.context; + final rank = this.rank; + final result = this.result; + return { + if (context != null) 'context': context.toJson(), + if (rank != null) 'rank': rank, + if (result != null) 'result': result.toJson(), + }; + } + + /// Context for result, if requested. + SearchResultsEventContext? context; + + /// A number that describes how closely this result matches the search. Higher is closer. + double? rank; + + /// The event that matched. + MatrixEvent? result; +} + +@_NameSource('spec') +class ResultRoomEvents { + ResultRoomEvents({ + this.count, + this.groups, + this.highlights, + this.nextBatch, + this.results, + this.state, + }); + + ResultRoomEvents.fromJson(Map json) + : count = ((v) => v != null ? v as int : null)(json['count']), + groups = ((v) => v != null + ? (v as Map).map((k, v) => MapEntry( + k, + (v as Map) + .map((k, v) => MapEntry(k, GroupValue.fromJson(v))))) + : null)(json['groups']), + highlights = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['highlights']), + nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), + results = ((v) => v != null + ? (v as List).map((v) => Result.fromJson(v)).toList() + : null)(json['results']), + state = ((v) => v != null + ? (v as Map).map((k, v) => MapEntry( + k, (v as List).map((v) => MatrixEvent.fromJson(v)).toList())) + : null)(json['state']); + Map toJson() { + final count = this.count; + final groups = this.groups; + final highlights = this.highlights; + final nextBatch = this.nextBatch; + final results = this.results; + final state = this.state; + return { + if (count != null) 'count': count, + if (groups != null) + 'groups': groups.map( + (k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v.toJson())))), + if (highlights != null) 'highlights': highlights.map((v) => v).toList(), + if (nextBatch != null) 'next_batch': nextBatch, + if (results != null) 'results': results.map((v) => v.toJson()).toList(), + if (state != null) + 'state': + state.map((k, v) => MapEntry(k, v.map((v) => v.toJson()).toList())), + }; + } + + /// An approximate count of the total number of results found. + int? count; + + /// Any groups that were requested. + /// + /// The outer `string` key is the group key requested (eg: `room_id` + /// or `sender`). The inner `string` key is the grouped value (eg: + /// a room's ID or a user's ID). + Map>? groups; + + /// List of words which should be highlighted, useful for stemming which may change the query terms. + List? highlights; + + /// Token that can be used to get the next batch of + /// results, by passing as the `next_batch` parameter to + /// the next call. If this field is absent, there are no + /// more results. + String? nextBatch; + + /// List of results in the requested order. + List? results; + + /// The current state for every room in the results. + /// This is included if the request had the + /// `include_state` key set with a value of `true`. + /// + /// The `string` key is the room ID for which the `State + /// Event` array belongs to. + Map>? state; +} + +@_NameSource('spec') +class ResultCategories { + ResultCategories({ + this.roomEvents, + }); + + ResultCategories.fromJson(Map json) + : roomEvents = ((v) => v != null ? ResultRoomEvents.fromJson(v) : null)( + json['room_events']); + Map toJson() { + final roomEvents = this.roomEvents; + return { + if (roomEvents != null) 'room_events': roomEvents.toJson(), + }; + } + + /// Mapping of category name to search criteria. + ResultRoomEvents? roomEvents; +} + +@_NameSource('rule override spec') +class SearchResults { + SearchResults({ + required this.searchCategories, + }); + + SearchResults.fromJson(Map json) + : searchCategories = ResultCategories.fromJson(json['search_categories']); + Map toJson() => { + 'search_categories': searchCategories.toJson(), + }; + + /// Describes which categories to search in and their criteria. + ResultCategories searchCategories; +} + +@_NameSource('generated') +enum EventFormat { client, federation } + +@_NameSource('rule override generated') +class StateFilter implements EventFilter, RoomEventFilter { + StateFilter({ + this.limit, + this.notSenders, + this.notTypes, + this.senders, + this.types, + this.containsUrl, + this.includeRedundantMembers, + this.lazyLoadMembers, + this.notRooms, + this.rooms, + }); + + StateFilter.fromJson(Map json) + : limit = ((v) => v != null ? v as int : null)(json['limit']), + notSenders = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_senders']), + notTypes = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_types']), + senders = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['senders']), + types = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['types']), + containsUrl = + ((v) => v != null ? v as bool : null)(json['contains_url']), + includeRedundantMembers = ((v) => + v != null ? v as bool : null)(json['include_redundant_members']), + lazyLoadMembers = + ((v) => v != null ? v as bool : null)(json['lazy_load_members']), + notRooms = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_rooms']), + rooms = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['rooms']); + Map toJson() { + final limit = this.limit; + final notSenders = this.notSenders; + final notTypes = this.notTypes; + final senders = this.senders; + final types = this.types; + final containsUrl = this.containsUrl; + final includeRedundantMembers = this.includeRedundantMembers; + final lazyLoadMembers = this.lazyLoadMembers; + final notRooms = this.notRooms; + final rooms = this.rooms; + return { + if (limit != null) 'limit': limit, + if (notSenders != null) 'not_senders': notSenders.map((v) => v).toList(), + if (notTypes != null) 'not_types': notTypes.map((v) => v).toList(), + if (senders != null) 'senders': senders.map((v) => v).toList(), + if (types != null) 'types': types.map((v) => v).toList(), + if (containsUrl != null) 'contains_url': containsUrl, + if (includeRedundantMembers != null) + 'include_redundant_members': includeRedundantMembers, + if (lazyLoadMembers != null) 'lazy_load_members': lazyLoadMembers, + if (notRooms != null) 'not_rooms': notRooms.map((v) => v).toList(), + if (rooms != null) 'rooms': rooms.map((v) => v).toList(), + }; + } + + /// The maximum number of events to return. + int? limit; + + /// 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. + List? notSenders; + + /// 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. + List? notTypes; + + /// A list of senders IDs to include. If this list is absent then all senders are included. + List? senders; + + /// 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. + List? types; + + /// If `true`, includes only events with a `url` key in their content. If `false`, excludes those events. If omitted, `url` key is not considered for filtering. + bool? containsUrl; + + /// If `true`, sends all membership events for all events, even if they have already + /// been sent to the client. Does not + /// apply unless `lazy_load_members` is `true`. See + /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) + /// for more information. Defaults to `false`. + bool? includeRedundantMembers; + + /// If `true`, enables lazy-loading of membership events. See + /// [Lazy-loading room members](https://spec.matrix.org/unstable/client-server-api/#lazy-loading-room-members) + /// for more information. Defaults to `false`. + bool? lazyLoadMembers; + + /// 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. + List? notRooms; + + /// A list of room IDs to include. If this list is absent then all rooms are included. + List? rooms; +} + +@_NameSource('spec') +class RoomFilter { + RoomFilter({ + this.accountData, + this.ephemeral, + this.includeLeave, + this.notRooms, + this.rooms, + this.state, + this.timeline, + }); + + RoomFilter.fromJson(Map json) + : accountData = ((v) => + v != null ? StateFilter.fromJson(v) : null)(json['account_data']), + ephemeral = ((v) => + v != null ? StateFilter.fromJson(v) : null)(json['ephemeral']), + includeLeave = + ((v) => v != null ? v as bool : null)(json['include_leave']), + notRooms = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['not_rooms']), + rooms = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['rooms']), + state = + ((v) => v != null ? StateFilter.fromJson(v) : null)(json['state']), + timeline = ((v) => + v != null ? StateFilter.fromJson(v) : null)(json['timeline']); + Map toJson() { + final accountData = this.accountData; + final ephemeral = this.ephemeral; + final includeLeave = this.includeLeave; + final notRooms = this.notRooms; + final rooms = this.rooms; + final state = this.state; + final timeline = this.timeline; + return { + if (accountData != null) 'account_data': accountData.toJson(), + if (ephemeral != null) 'ephemeral': ephemeral.toJson(), + if (includeLeave != null) 'include_leave': includeLeave, + if (notRooms != null) 'not_rooms': notRooms.map((v) => v).toList(), + if (rooms != null) 'rooms': rooms.map((v) => v).toList(), + if (state != null) 'state': state.toJson(), + if (timeline != null) 'timeline': timeline.toJson(), + }; + } + + /// The per user account data to include for rooms. + StateFilter? accountData; + + /// The events that aren't recorded in the room history, e.g. typing and receipts, to include for rooms. + StateFilter? ephemeral; + + /// Include rooms that the user has left in the sync, default false + bool? includeLeave; + + /// 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` + List? notRooms; + + /// 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` + List? rooms; + + /// The state events to include for rooms. + StateFilter? state; + + /// The message and state update events to include for rooms. + StateFilter? timeline; +} + +@_NameSource('spec') +class Filter { + Filter({ + this.accountData, + this.eventFields, + this.eventFormat, + this.presence, + this.room, + }); + + Filter.fromJson(Map json) + : accountData = ((v) => + v != null ? EventFilter.fromJson(v) : null)(json['account_data']), + eventFields = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['event_fields']), + eventFormat = ((v) => v != null + ? { + 'client': EventFormat.client, + 'federation': EventFormat.federation + }[v]! + : null)(json['event_format']), + presence = ((v) => + v != null ? EventFilter.fromJson(v) : null)(json['presence']), + room = ((v) => v != null ? RoomFilter.fromJson(v) : null)(json['room']); + Map toJson() { + final accountData = this.accountData; + final eventFields = this.eventFields; + final eventFormat = this.eventFormat; + final presence = this.presence; + final room = this.room; + return { + if (accountData != null) 'account_data': accountData.toJson(), + if (eventFields != null) + 'event_fields': eventFields.map((v) => v).toList(), + if (eventFormat != null) + 'event_format': { + EventFormat.client: 'client', + EventFormat.federation: 'federation' + }[eventFormat]!, + if (presence != null) 'presence': presence.toJson(), + if (room != null) 'room': room.toJson(), + }; + } + + /// The user account data that isn't associated with rooms to include. + EventFilter? accountData; + + /// List of event fields to include. If this list is absent then all fields are included. The entries may include '.' characters 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. + List? eventFields; + + /// 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'. + EventFormat? eventFormat; + + /// The presence updates to include. + EventFilter? presence; + + /// Filters to be applied to room data. + RoomFilter? room; +} + +@_NameSource('rule override generated') +class OpenIdCredentials { + OpenIdCredentials({ + required this.accessToken, + required this.expiresIn, + required this.matrixServerName, + required this.tokenType, + }); + + OpenIdCredentials.fromJson(Map json) + : accessToken = json['access_token'] as String, + expiresIn = json['expires_in'] as int, + matrixServerName = json['matrix_server_name'] as String, + tokenType = json['token_type'] as String; + Map toJson() => { + 'access_token': accessToken, + 'expires_in': expiresIn, + 'matrix_server_name': matrixServerName, + 'token_type': tokenType, + }; + + /// An access token the consumer may use to verify the identity of + /// the person who generated the token. This is given to the federation + /// API `GET /openid/userinfo` to verify the user's identity. + String accessToken; + + /// The number of seconds before this token expires and a new one must + /// be generated. + int expiresIn; + + /// The homeserver domain the consumer should use when attempting to + /// verify the user's identity. + String matrixServerName; + + /// The string `Bearer`. + String tokenType; +} + +@_NameSource('spec') +class Tag { + Tag({ + this.order, + this.additionalProperties = const {}, + }); + + Tag.fromJson(Map json) + : order = + ((v) => v != null ? (v as num).toDouble() : null)(json['order']), + additionalProperties = Map.fromEntries(json.entries + .where((e) => !['order'].contains(e.key)) + .map((e) => MapEntry(e.key, e.value as dynamic))); + Map toJson() { + final order = this.order; + return { + ...additionalProperties, + if (order != null) 'order': order, + }; + } + + /// A number in a range `[0,1]` describing a relative + /// position of the room under the given tag. + double? order; + + Map additionalProperties; +} + +@_NameSource('rule override spec') +class Profile { + Profile({ + this.avatarUrl, + this.displayName, + required this.userId, + }); + + Profile.fromJson(Map json) + : avatarUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + displayName = + ((v) => v != null ? v as String : null)(json['display_name']), + userId = json['user_id'] as String; + Map toJson() { + final avatarUrl = this.avatarUrl; + final displayName = this.displayName; + return { + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + if (displayName != null) 'display_name': displayName, + 'user_id': userId, + }; + } + + /// The avatar url, as an MXC, if one exists. + Uri? avatarUrl; + + /// The display name of the user, if one exists. + String? displayName; + + /// The user's matrix user ID. + String userId; +} + +@_NameSource('generated') +class SearchUserDirectoryResponse { + SearchUserDirectoryResponse({ + required this.limited, + required this.results, + }); + + SearchUserDirectoryResponse.fromJson(Map json) + : limited = json['limited'] as bool, + results = + (json['results'] as List).map((v) => Profile.fromJson(v)).toList(); + Map toJson() => { + 'limited': limited, + 'results': results.map((v) => v.toJson()).toList(), + }; + + /// Indicates if the result list has been truncated by the limit. + bool limited; + + /// Ordered by rank and then whether or not profile info is available. + List results; +} + +@_NameSource('rule override generated') +class TurnServerCredentials { + TurnServerCredentials({ + required this.password, + required this.ttl, + required this.uris, + required this.username, + }); + + TurnServerCredentials.fromJson(Map json) + : password = json['password'] as String, + ttl = json['ttl'] as int, + uris = (json['uris'] as List).map((v) => v as String).toList(), + username = json['username'] as String; + Map toJson() => { + 'password': password, + 'ttl': ttl, + 'uris': uris.map((v) => v).toList(), + 'username': username, + }; + + /// The password to use. + String password; + + /// The time-to-live in seconds + int ttl; + + /// A list of TURN URIs + List uris; + + /// The username to use. + String username; +} + +@_NameSource('generated') +class GetVersionsResponse { + GetVersionsResponse({ + this.unstableFeatures, + required this.versions, + }); + + GetVersionsResponse.fromJson(Map json) + : unstableFeatures = ((v) => v != null + ? (v as Map).map((k, v) => MapEntry(k, v as bool)) + : null)(json['unstable_features']), + versions = (json['versions'] as List).map((v) => v as String).toList(); + Map toJson() { + final unstableFeatures = this.unstableFeatures; + return { + if (unstableFeatures != null) + 'unstable_features': unstableFeatures.map((k, v) => MapEntry(k, v)), + 'versions': versions.map((v) => v).toList(), + }; + } + + /// Experimental features the server supports. Features not listed here, + /// or the lack of this property all together, indicate that a feature is + /// not supported. + Map? unstableFeatures; + + /// The supported versions. + List versions; +} + +@_NameSource('rule override generated') +class ServerConfig { + ServerConfig({ + this.mUploadSize, + }); + + ServerConfig.fromJson(Map json) + : mUploadSize = + ((v) => v != null ? v as int : null)(json['m.upload.size']); + Map toJson() { + final mUploadSize = this.mUploadSize; + return { + if (mUploadSize != null) 'm.upload.size': mUploadSize, + }; + } + + /// The maximum size an upload can be in bytes. + /// Clients SHOULD use this as a guide when uploading content. + /// If not listed or null, the size limit should be treated as unknown. + int? mUploadSize; +} + +@_NameSource('generated') +class GetUrlPreviewResponse { + GetUrlPreviewResponse({ + this.matrixImageSize, + this.ogImage, + }); + + GetUrlPreviewResponse.fromJson(Map json) + : matrixImageSize = + ((v) => v != null ? v as int : null)(json['matrix:image:size']), + ogImage = ((v) => v != null ? Uri.parse(v) : null)(json['og:image']); + Map toJson() { + final matrixImageSize = this.matrixImageSize; + final ogImage = this.ogImage; + return { + if (matrixImageSize != null) 'matrix:image:size': matrixImageSize, + if (ogImage != null) 'og:image': ogImage.toString(), + }; + } + + /// The byte-size of the image. Omitted if there is no image attached. + int? matrixImageSize; + + /// An [MXC URI](https://spec.matrix.org/unstable/client-server-api/#matrix-content-mxc-uris) to the image. Omitted if there is no image. + Uri? ogImage; +} + +@_NameSource('generated') +enum Method { crop, scale } diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 9e601ef7..2e2bb31c 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -26,57 +27,23 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:http/http.dart' as http; -import 'package:mime/mime.dart'; import '../matrix_api_lite.dart'; import 'model/auth/authentication_data.dart'; -import 'model/auth/authentication_types.dart'; -import 'model/device.dart'; -import 'model/event_context.dart'; import 'model/events_sync_update.dart'; -import 'model/filter.dart'; -import 'model/keys_query_response.dart'; -import 'model/login_response.dart'; -import 'model/login_types.dart'; import 'model/matrix_connection_exception.dart'; -import 'model/matrix_event.dart'; import 'model/matrix_exception.dart'; import 'model/matrix_keys.dart'; -import 'model/notifications_query_response.dart'; -import 'model/one_time_keys_claim_response.dart'; -import 'model/open_graph_data.dart'; -import 'model/open_id_credentials.dart'; -import 'model/presence_content.dart'; -import 'model/profile.dart'; -import 'model/public_rooms_response.dart'; -import 'model/push_rule_set.dart'; -import 'model/pusher.dart'; import 'model/request_token_response.dart'; -import 'model/room_alias_information.dart'; -import 'model/room_keys_info.dart'; import 'model/room_keys_keys.dart'; -import 'model/server_capabilities.dart'; import 'model/supported_protocol.dart'; -import 'model/supported_versions.dart'; -import 'model/sync_update.dart'; -import 'model/tag.dart'; -import 'model/third_party_identifier.dart'; import 'model/third_party_location.dart'; import 'model/third_party_user.dart'; -import 'model/timeline_history_response.dart'; -import 'model/turn_server_credentials.dart'; import 'model/upload_key_signatures_response.dart'; -import 'model/user_search_result.dart'; -import 'model/well_known_information.dart'; -import 'model/who_is_info.dart'; + +import 'generated/api.dart'; enum RequestType { GET, POST, PUT, DELETE } -enum IdServerUnbindResult { success, no_support } -enum ThirdPartyIdentifierMedium { email, msisdn } -enum Membership { join, invite, leave, ban } -enum Direction { b, f } -enum Visibility { public, private } -enum CreateRoomPreset { private_chat, public_chat, trusted_private_chat } String describeEnum(Object enumEntry) { final description = enumEntry.toString(); @@ -85,35 +52,39 @@ String describeEnum(Object enumEntry) { return description.substring(indexOfDot + 1); } -class MatrixApi { +class MatrixApi extends Api { /// The homeserver this client is communicating with. - Uri homeserver; + Uri get homeserver => baseUri; + set homeserver(Uri uri) => baseUri = uri; /// This is the access token for the matrix client. When it is undefined, then /// the user needs to sign in first. - String accessToken; + String get accessToken => bearerToken; + set accessToken(String token) => bearerToken = token; + + @override + Null unexpectedResponse(http.BaseResponse response, Uint8List responseBody) { + if (response.statusCode >= 400 && response.statusCode < 500) { + throw MatrixException.fromJson(json.decode(utf8.decode(responseBody))); + } + super.unexpectedResponse(response, responseBody); + } /// Matrix synchronisation is done with https long polling. This needs a /// timeout which is usually 30 seconds. int syncTimeoutSec; - http.Client httpClient = http.Client(); - - bool get _testMode => - homeserver.toString() == 'https://fakeserver.notexisting'; - int _timeoutFactor = 1; MatrixApi({ - this.homeserver, - this.accessToken, + Uri homeserver, + String accessToken, http.Client httpClient, this.syncTimeoutSec = 30, - }) { - if (httpClient != null) { - this.httpClient = httpClient; - } - } + }) : super( + httpClient: httpClient, + baseUri: homeserver, + bearerToken: accessToken); /// Used for all Matrix json requests using the [c2s API](https://matrix.org/docs/spec/client_server/r0.6.0.html). /// @@ -217,128 +188,6 @@ class MatrixApi { return jsonResp; } - /// Gets the versions of the specification supported by the server. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-versions - Future getVersions() async { - final response = await request( - RequestType.GET, - '/client/versions', - ); - return SupportedVersions.fromJson(response); - } - - /// Gets discovery information about the domain. The file may include additional keys. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-well-known-matrix-client - Future getWellknown() async { - final response = - await httpClient.get(homeserver.resolve('.well-known/matrix/client')); - final rawJson = json.decode(response.body); - return WellKnownInformation.fromJson(rawJson); - } - - Future getLoginFlows() async { - final response = await request( - RequestType.GET, - '/client/r0/login', - ); - return LoginTypes.fromJson(response); - } - - /// Authenticates the user, and issues an access token they can use to authorize themself in subsequent requests. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-login - /// To just login with the username 'alice' you set [identifier] to: - /// `AuthenticationUserIdentifier(user: 'alice')` - /// Maybe you want to set [user] to the same String to stay compatible with - /// older server versions. - Future login({ - String type = AuthenticationTypes.password, - AuthenticationIdentifier identifier, - String password, - String token, - String deviceId, - String initialDeviceDisplayName, - AuthenticationData auth, - @Deprecated('Deprecated in favour of identifier.') String user, - @Deprecated('Deprecated in favour of identifier.') String medium, - @Deprecated('Deprecated in favour of identifier.') String address, - }) async { - final response = await request(RequestType.POST, '/client/r0/login', data: { - 'type': type, - if (identifier != null) 'identifier': identifier.toJson(), - if (user != null) 'user': user, - if (medium != null) 'medium': medium, - if (address != null) 'address': address, - if (password != null) 'password': password, - if (token != null) 'token': token, - if (deviceId != null) 'device_id': deviceId, - if (initialDeviceDisplayName != null) - 'initial_device_display_name': initialDeviceDisplayName, - if (auth != null) 'auth': auth.toJson(), - }); - return LoginResponse.fromJson(response); - } - - /// Invalidates an existing access token, so that it can no longer be used for authorization. - /// The device associated with the access token is also deleted. Device keys for the device - /// are deleted alongside the device. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-logout - Future logout() async { - await request( - RequestType.POST, - '/client/r0/logout', - ); - return; - } - - /// Invalidates all access tokens for a user, so that they can no longer be used - /// for authorization. This includes the access token that made this request. All - /// devices for the user are also deleted. Device keys for the device are - /// deleted alongside the device. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-logout-all - Future logoutAll() async { - await request( - RequestType.POST, - '/client/r0/logout/all', - ); - return; - } - - /// Register for an account on this homeserver. - /// - /// There are two kinds of user account: - /// - /// user accounts. These accounts may use the full API described in this - /// specification. - /// guest accounts. These accounts may have limited permissions and may not - /// be supported by all servers. - /// - /// If registration is successful, this endpoint will issue an access token - /// the client can use to authorize itself in subsequent requests. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register - Future register({ - String username, - String password, - String deviceId, - String initialDeviceDisplayName, - bool inhibitLogin, - AuthenticationData auth, - String kind, - }) async { - final response = - await request(RequestType.POST, '/client/r0/register', query: { - if (kind != null) 'kind': kind, - }, data: { - if (username != null) 'username': username, - if (password != null) 'password': password, - if (deviceId != null) 'device_id': deviceId, - if (initialDeviceDisplayName != null) - 'initial_device_display_name': initialDeviceDisplayName, - if (inhibitLogin != null) 'inhibit_login': inhibitLogin, - if (auth != null) 'auth': auth.toJson(), - }); - return LoginResponse.fromJson(response); - } - /// The homeserver must check that the given email address is not already associated /// with an account on this homeserver. The homeserver should validate the email /// itself, either by sending a validation email itself or by using a service it @@ -392,19 +241,6 @@ class MatrixApi { return RequestTokenResponse.fromJson(response); } - /// Changes the password for an account on this homeserver. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password - Future changePassword( - String newPassword, { - AuthenticationData auth, - }) async { - await request(RequestType.POST, '/client/r0/account/password', data: { - 'new_password': newPassword, - if (auth != null) 'auth': auth.toJson(), - }); - return; - } - /// The homeserver must check that the given email address is associated with /// an account on this homeserver. This API should be used to request /// validation tokens when authenticating for the /account/password endpoint. @@ -457,118 +293,6 @@ class MatrixApi { return RequestTokenResponse.fromJson(response); } - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-account-deactivate - Future deactivateAccount({ - String idServer, - AuthenticationData auth, - }) async { - final response = - await request(RequestType.POST, '/client/r0/account/deactivate', data: { - if (idServer != null) 'id_server': idServer, - if (auth != null) 'auth': auth.toJson(), - }); - - return IdServerUnbindResult.values.firstWhere( - (i) => describeEnum(i) == response['id_server_unbind_result'], - ); - } - - Future checkUsernameAvailability(String username) async { - final response = await request( - RequestType.GET, - '/client/r0/register/available', - query: { - 'username': username, - }, - ); - return response['available']; - } - - /// Gets a list of the third party identifiers that the homeserver has - /// associated with the user's account. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-register-available - Future> getAccount3PIDs() async { - final response = await request( - RequestType.GET, - '/client/r0/account/3pid', - ); - return (response['threepids'] as List) - .map((item) => ThirdPartyIdentifier.fromJson(item)) - .toList(); - } - - /// Adds contact information to the user's account. Homeservers - /// should use 3PIDs added through this endpoint for password resets - /// instead of relying on the identity server. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-add - Future add3PID( - String clientSecret, - String sid, { - AuthenticationData auth, - }) async { - await request(RequestType.POST, '/client/r0/account/3pid/add', data: { - 'sid': sid, - 'client_secret': clientSecret, - if (auth != null) 'auth': auth.toJson(), - }); - return; - } - - /// Binds a 3PID to the user's account through the specified identity server. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-bind - Future bind3PID( - String clientSecret, - String sid, - String idServer, - String idAccessToken, - ) async { - await request(RequestType.POST, '/client/r0/account/3pid/bind', data: { - 'sid': sid, - 'client_secret': clientSecret, - 'id_server': idServer, - 'id_access_token': idAccessToken, - }); - return; - } - - /// Removes a third party identifier from the user's account. This might not cause an unbind of the identifier from the identity server. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-delete - Future delete3pidFromAccount( - String address, - ThirdPartyIdentifierMedium medium, { - String idServer, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/3pid/delete', - data: { - 'address': address, - 'medium': describeEnum(medium), - if (idServer != null) 'id_server': idServer, - }); - return IdServerUnbindResult.values.firstWhere( - (i) => describeEnum(i) == response['id_server_unbind_result'], - ); - } - - /// Removes a user's third party identifier from the provided identity server without removing it from the homeserver. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-unbind - Future unbind3pidFromAccount( - String address, - ThirdPartyIdentifierMedium medium, - String idServer, - ) async { - final response = await request( - RequestType.POST, '/client/r0/account/3pid/unbind', - data: { - 'address': address, - 'medium': describeEnum(medium), - 'id_server': idServer, - }); - return IdServerUnbindResult.values.firstWhere( - (i) => describeEnum(i) == response['id_server_unbind_result'], - ); - } - /// This API should be used to request validation tokens when adding an email address to an account. /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-email-requesttoken Future requestEmailValidationToken( @@ -617,87 +341,6 @@ class MatrixApi { return RequestTokenResponse.fromJson(response); } - /// Gets information about the owner of a given access token. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-account-whoami - Future getTokenOwner() async { - final response = await request( - RequestType.GET, - '/client/r0/account/whoami', - ); - return response['user_id']; - } - - /// Gets information about the server's supported feature set and other relevant capabilities. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-capabilities - Future getCapabilities() async { - final response = await request( - RequestType.GET, - '/client/r0/capabilities', - ); - return ServerCapabilities.fromJson(response['capabilities']); - } - - /// Uploads a new filter definition to the homeserver. Returns a filter ID that may be used - /// in future requests to restrict which events are returned to the client. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-filter - Future defineFilter( - String userId, - Filter filter, - ) async { - final response = await request( - RequestType.POST, - '/client/r0/user/${Uri.encodeComponent(userId)}/filter', - data: filter.toJson(), - ); - return response['filter_id']; - } - - /// Download a filter - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-filter - Future getFilter(String userId, String filterId) async { - final response = await request( - RequestType.GET, - '/client/r0/user/${Uri.encodeComponent(userId)}/filter/${Uri.encodeComponent(filterId)}', - ); - return Filter.fromJson(response); - } - - /// Synchronise the client's state with the latest state on the server. Clients use this API when - /// they first log in to get an initial snapshot of the state on the server, and then continue to - /// call this API to get incremental deltas to the state, and to receive new messages. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-sync - Future sync({ - String filter, - String since, - bool fullState, - PresenceType setPresence, - int timeout, - }) async { - final response = await request( - RequestType.GET, - '/client/r0/sync', - query: { - if (filter != null) 'filter': filter, - if (since != null) 'since': since, - if (fullState != null) 'full_state': fullState.toString(), - if (setPresence != null) 'set_presence': describeEnum(setPresence), - if (timeout != null) 'timeout': timeout.toString(), - }, - ); - return SyncUpdate.fromJson(response); - } - - /// Get a single event based on roomId/eventId. You must have permission to - /// retrieve this event e.g. by being a member in the room for this event. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-event-eventid - Future getOneRoomEvent(String roomId, String eventId) async { - final response = await request( - RequestType.GET, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/event/${Uri.encodeComponent(eventId)}', - ); - return MatrixEvent.fromJson(response); - } - /// Looks up the contents of a state event in a room. If the user is joined to the room then the /// state is taken from the current state of the room. If the user has left the room then the /// state is taken from the state of the room when they left. @@ -717,329 +360,6 @@ class MatrixApi { return response; } - /// Get the state events for the current state of a room. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-state - Future> getRoomState(String roomId) async { - final response = await request( - RequestType.GET, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state', - ); - return (response['chunk'] as List) - .map((i) => MatrixEvent.fromJson(i)) - .toList(); - } - - /// Get the list of members for this room. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-members - Future> getMembersByRoom( - String roomId, { - String at, - Membership membership, - Membership notMembership, - }) async { - final response = await request( - RequestType.GET, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/members', - query: { - if (at != null) 'at': at, - if (membership != null) 'membership': describeEnum(membership), - if (notMembership != null) - 'not_membership': describeEnum(notMembership), - }, - ); - return (response['chunk'] as List) - .map((i) => MatrixEvent.fromJson(i)) - .toList(); - } - - /// This API returns a map of MXIDs to member info objects for members of the room. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-joined-members - Future> getJoinedMembersByRoom(String roomId) async { - final response = await request( - RequestType.GET, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/joined_members', - ); - return (response['joined'] as Map).map( - (k, v) => MapEntry(k, Profile.fromJson(v)), - ); - } - - /// This API returns a list of message and state events for a room. It uses pagination query - /// parameters to paginate history in the room. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-messages - Future getRoomEvents( - String roomId, - String from, - Direction dir, { - String to, - int limit, - String filter, - }) async { - final response = await request(RequestType.GET, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/messages', - query: { - 'from': from, - 'dir': describeEnum(dir), - if (to != null) 'to': to, - if (limit != null) 'limit': limit.toString(), - if (filter != null) 'filter': filter, - }); - return TimelineHistoryResponse.fromJson(response); - } - - /// State events can be sent using this endpoint. - /// https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey - Future setRoomStateWithKey( - String roomId, - String eventType, - Map content, [ - String stateKey = '', - ]) async { - final response = await request(RequestType.PUT, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}', - data: content); - return response['event_id']; - } - - /// This endpoint is used to send a message event to a room. - /// Message events allow access to historical events and pagination, - /// making them suited for "once-off" activity in a room. - /// https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid - Future sendMessage( - String roomId, - String eventType, - String txnId, - Map content, - ) async { - final response = await request(RequestType.PUT, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/send/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}', - data: content); - return response['event_id']; - } - - /// Strips all information out of an event which isn't critical to the integrity of - /// the server-side representation of the room. - /// https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid - Future redactEvent( - String roomId, - String eventId, - String txnId, { - String reason, - }) async { - final response = await request(RequestType.PUT, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/redact/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(txnId)}', - data: { - if (reason != null) 'reason': reason, - }); - return response['event_id']; - } - - Future createRoom({ - Visibility visibility, - String roomAliasName, - String name, - String topic, - List invite, - List> invite3pid, - String roomVersion, - Map creationContent, - List> initialState, - CreateRoomPreset preset, - bool isDirect, - Map powerLevelContentOverride, - }) async { - final response = - await request(RequestType.POST, '/client/r0/createRoom', data: { - if (visibility != null) 'visibility': describeEnum(visibility), - if (roomAliasName != null) 'room_alias_name': roomAliasName, - if (name != null) 'name': name, - if (topic != null) 'topic': topic, - if (invite != null) 'invite': invite, - if (invite3pid != null) 'invite_3pid': invite3pid, - if (roomVersion != null) 'room_version': roomVersion, - if (creationContent != null) 'creation_content': creationContent, - if (initialState != null) 'initial_state': initialState, - if (preset != null) 'preset': describeEnum(preset), - if (isDirect != null) 'is_direct': isDirect, - if (powerLevelContentOverride != null) - 'power_level_content_override': powerLevelContentOverride, - }); - return response['room_id']; - } - - /// Create a new mapping from room alias to room ID. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-directory-room-roomalias - Future setRoomAlias(String alias, String roomId) async { - await request( - RequestType.PUT, - '/client/r0/directory/room/${Uri.encodeComponent(alias)}', - data: {'room_id': roomId}, - ); - return; - } - - /// Requests that the server resolve a room alias to a room ID. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-room-roomalias - Future getRoomIdByAlias(String alias) async { - final response = await request( - RequestType.GET, - '/client/r0/directory/room/${Uri.encodeComponent(alias)}', - ); - return RoomAliasInformation.fromJson(response); - } - - /// Remove a mapping of room alias to room ID. - /// https://matrix.org/docs/spec/client_server/r0.6.1#delete-matrix-client-r0-directory-room-roomalias - Future deleteRoomAlias(String alias) async { - await request( - RequestType.DELETE, - '/client/r0/directory/room/${Uri.encodeComponent(alias)}', - ); - return; - } - - /// Get a list of aliases maintained by the local server for the given room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-aliases - Future> getLocalAliases(String roomId) async { - final response = await request( - RequestType.GET, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/aliases', - ); - return List.from(response['aliases']); - } - - /// This API returns a list of the user's current rooms. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-joined-rooms - Future> getJoinedRooms() async { - final response = await request( - RequestType.GET, - '/client/r0/joined_rooms', - ); - return List.from(response['joined_rooms']); - } - - /// This API invites a user to participate in a particular room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-invite - Future inviteToRoom(String roomId, String userId) async { - await request( - RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/invite', - data: { - 'user_id': userId, - }, - ); - return; - } - - /// This API starts a user participating in a particular room, if that user is allowed to participate in that room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-invite - Future joinRoomById( - String roomId, { - String thirdPidSignedSender, - String thirdPidSignedmxid, - String thirdPidSignedToken, - Map thirdPidSignedSiganture, - }) async { - final response = await request( - RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/join', - data: { - if (thirdPidSignedSiganture != null) - 'third_party_signed': { - 'sender': thirdPidSignedSender, - 'mxid': thirdPidSignedmxid, - 'token': thirdPidSignedToken, - 'signatures': thirdPidSignedSiganture, - } - }, - ); - return response['room_id']; - } - - /// This API starts a user participating in a particular room, if that user is allowed to participate in that room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-join-roomidoralias - Future joinRoom( - String roomIdOrAlias, { - List servers, - String thirdPidSignedSender, - String thirdPidSignedmxid, - String thirdPidSignedToken, - Map thirdPidSignedSiganture, - }) async { - final response = await request( - RequestType.POST, - '/client/r0/join/${Uri.encodeComponent(roomIdOrAlias)}', - query: {'server_name': servers ?? []}, - data: { - if (thirdPidSignedSiganture != null) - 'third_party_signed': { - 'sender': thirdPidSignedSender, - 'mxid': thirdPidSignedmxid, - 'token': thirdPidSignedToken, - 'signatures': thirdPidSignedSiganture, - } - }, - ); - return response['room_id']; - } - - /// This API stops a user participating in a particular room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-leave - Future leaveRoom(String roomId) async { - await request( - RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/leave', - ); - return; - } - - /// This API stops a user remembering about a particular room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-forget - Future forgetRoom(String roomId) async { - await request( - RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/forget', - ); - return; - } - - /// Kick a user from the room. - /// The caller must have the required power level in order to perform this operation. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-kick - Future kick(String roomId, String userId, {String reason}) async { - await request(RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/kick', - data: { - 'user_id': userId, - if (reason != null) 'reason': reason, - }); - return; - } - - /// Ban a user in the room. If the user is currently in the room, also kick them. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-ban - Future ban(String roomId, String userId, {String reason}) async { - await request( - RequestType.POST, '/client/r0/rooms/${Uri.encodeComponent(roomId)}/ban', - data: { - 'user_id': userId, - if (reason != null) 'reason': reason, - }); - return; - } - - /// Unban a user from the room. This allows them to be invited to the room, and join if they - /// would otherwise be allowed to join according to its join rules. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-unban - Future unban(String roomId, String userId) async { - await request(RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/unban', - data: { - 'user_id': userId, - }); - return; - } - /// Gets the visibility of a given room on the server's public room directory. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-list-room-roomid Future getRoomVisibilityOnDirectory(String roomId) async { @@ -1065,356 +385,6 @@ class MatrixApi { return; } - /// Lists the public rooms on the server. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-publicrooms - Future getPublicRooms({ - int limit, - String since, - String server, - }) async { - final response = await request( - RequestType.GET, - '/client/r0/publicRooms', - query: { - if (limit != null) 'limit': limit.toString(), - if (since != null) 'since': since, - if (server != null) 'server': server, - }, - ); - return PublicRoomsResponse.fromJson(response); - } - - /// Lists the public rooms on the server, with optional filter. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-publicrooms - Future queryPublicRooms({ - String genericSearchTerm, - int limit, - String since, - String server, - bool includeAllNetworks, - String thirdPartyInstanceId, - }) async { - final response = await request( - RequestType.POST, - '/client/r0/publicRooms', - query: { - if (server != null) 'server': server, - }, - data: { - if (limit != null) 'limit': limit, - if (since != null) 'since': since, - if (includeAllNetworks != null) - 'include_all_networks': includeAllNetworks, - if (thirdPartyInstanceId != null) - 'third_party_instance_id': thirdPartyInstanceId, - if (genericSearchTerm != null) - 'filter': { - 'generic_search_term': genericSearchTerm, - }, - }, - ); - return PublicRoomsResponse.fromJson(response); - } - - /// Performs a search for users. The homeserver may determine which subset of users are searched, - /// however the homeserver MUST at a minimum consider the users the requesting user shares a - /// room with and those who reside in public rooms (known to the homeserver). The search MUST - /// consider local users to the homeserver, and SHOULD query remote users as part of the search. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-user-directory-search - Future searchUserDirectory( - String searchTerm, { - int limit, - }) async { - final response = await request( - RequestType.POST, - '/client/r0/user_directory/search', - data: { - 'search_term': searchTerm, - if (limit != null) 'limit': limit, - }, - ); - return UserSearchResult.fromJson(response); - } - - /// This API sets the given user's display name. You must have permission to - /// set this user's display name, e.g. you need to have their access_token. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-profile-userid-displayname - Future setDisplayName(String userId, String displayname) async { - await request( - RequestType.PUT, - '/client/r0/profile/${Uri.encodeComponent(userId)}/displayname', - data: { - 'displayname': displayname, - }, - ); - return; - } - - /// Get the user's display name. This API may be used to fetch the user's own - /// displayname or to query the name of other users; either locally or on remote homeservers. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-displayname - Future getDisplayName(String userId) async { - final response = await request( - RequestType.GET, - '/client/r0/profile/${Uri.encodeComponent(userId)}/displayname', - ); - return response['displayname']; - } - - /// This API sets the given user's avatar URL. You must have permission to set - /// this user's avatar URL, e.g. you need to have their access_token. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-profile-userid-avatar-url - Future setAvatarUrl(String userId, Uri avatarUrl) async { - await request( - RequestType.PUT, - '/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url', - data: { - 'avatar_url': avatarUrl.toString(), - }, - ); - return; - } - - /// Get the user's avatar URL. This API may be used to fetch the user's own avatar URL or to - /// query the URL of other users; either locally or on remote homeservers. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-avatar-url - Future getAvatarUrl(String userId) async { - final response = await request( - RequestType.GET, - '/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url', - ); - return Uri.parse(response['avatar_url']); - } - - /// Get the combined profile information for this user. This API may be used to fetch the user's - /// own profile information or other users; either locally or on remote homeservers. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-profile-userid-avatar-url - Future getUserProfile(String userId) async { - final response = await request( - RequestType.GET, - '/client/r0/profile/${Uri.encodeComponent(userId)}', - ); - return Profile.fromJson(response); - } - - /// This API provides credentials for the client to use when initiating calls. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-voip-turnserver - Future getTurnServer() async { - final response = await request( - RequestType.GET, - '/client/r0/voip/turnServer', - ); - return TurnServerCredentials.fromJson(response); - } - - /// This tells the server that the user is typing for the next N milliseconds - /// where N is the value specified in the timeout key. Alternatively, if typing is false, - /// it tells the server that the user has stopped typing. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-typing-userid - Future setTyping( - String userId, - String roomId, - bool typing, { - int timeout, - }) async { - await request(RequestType.PUT, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/typing/${Uri.encodeComponent(userId)}', - data: { - 'typing': typing, - if (timeout != null) 'timeout': timeout, - }); - return; - } - - /// This API updates the marker for the given receipt type to the event ID specified. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-receipt-receipttype-eventid - /// - Future postReceipt(String roomId, String eventId) async { - await request( - RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/receipt/m.read/${Uri.encodeComponent(eventId)}', - ); - return; - } - - /// Sets the position of the read marker for a given room, and optionally the read receipt's location. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-read-markers - Future setReadMarker(String roomId, String eventId, - {String readReceiptLocationEventId}) async { - await request( - RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/read_markers', - data: { - 'm.fully_read': eventId, - if (readReceiptLocationEventId != null) - 'm.read': readReceiptLocationEventId, - }, - ); - return; - } - - /// This API sets the given user's presence state. When setting the status, - /// the activity time is updated to reflect that activity; the client does not need - /// to specify the last_active_ago field. You cannot set the presence state of another user. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-presence-userid-status - Future setPresence( - String userId, - PresenceType presenceType, { - String statusMsg, - }) async { - await request( - RequestType.PUT, - '/client/r0/presence/${Uri.encodeComponent(userId)}/status', - data: { - 'presence': describeEnum(presenceType), - if (statusMsg != null) 'status_msg': statusMsg, - }, - ); - return; - } - - /// Get the given user's presence state. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-presence-userid-status - Future getPresence(String userId) async { - final response = await request( - RequestType.GET, - '/client/r0/presence/${Uri.encodeComponent(userId)}/status', - ); - return PresenceContent.fromJson(response); - } - - /// Uploads a file with the name [fileName] as base64 encoded to the server - /// and returns the mxc url as a string. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-media-r0-upload - Future uploadContent(Uint8List file, String fileName, - {String contentType}) async { - fileName = fileName.split('/').last; - final length = file.length; - final headers = {}; - headers['Authorization'] = 'Bearer $accessToken'; - headers['Content-Type'] = - contentType ?? lookupMimeType(fileName, headerBytes: file); - headers['Content-Length'] = length.toString(); - fileName = Uri.encodeQueryComponent(fileName); - final url = homeserver.resolveUri(Uri( - path: '_matrix/media/r0/upload', - queryParameters: {'filename': fileName}, - )); - final streamedRequest = http.StreamedRequest('POST', url) - ..headers.addAll(headers); - streamedRequest.contentLength = length; - streamedRequest.sink.add(file); - streamedRequest.sink.close(); - final streamedResponse = _testMode ? null : await streamedRequest.send(); - final Map jsonResponse = json.decode( - String.fromCharCodes(_testMode - ? ((fileName == 'file.jpeg') - ? '{"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"}' - : '{"errcode":"M_FORBIDDEN","error":"Cannot upload this content"}') - .codeUnits - : await streamedResponse.stream.first), - ); - if (!(jsonResponse['content_uri'] is String)) { - throw MatrixException.fromJson(jsonResponse); - } - return jsonResponse['content_uri']; - } - - /// Get information about a URL for the client. Typically this is called when a client sees a - /// URL in a message and wants to render a preview for the user. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-preview-url - Future getUrlPreview(Uri url, {int ts}) async { - final action = homeserver - .resolveUri(Uri(path: '_matrix/media/r0/preview_url', queryParameters: { - 'url': url.toString(), - if (ts != null) 'ts': ts.toString(), - })); - final response = await httpClient.get(action); - final rawJson = json.decode(response.body.isEmpty ? '{}' : response.body); - return OpenGraphData.fromJson(rawJson); - } - - /// This endpoint allows clients to retrieve the configuration of the content repository, such as upload limitations. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-media-r0-config - Future getConfig() async { - final action = homeserver.resolve('_matrix/media/r0/config'); - final response = await httpClient.get(action); - final rawJson = json.decode(response.body.isEmpty ? '{}' : response.body); - return rawJson['m.upload.size']; - } - - /// This endpoint is used to send send-to-device events to a set of client devices. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-sendtodevice-eventtype-txnid - Future sendToDevice( - String eventType, - String txnId, - Map>> messages, - ) async { - await request( - RequestType.PUT, - '/client/r0/sendToDevice/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}', - data: { - 'messages': messages, - }, - ); - return; - } - - /// Gets information about all devices for the current user. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-devices - Future> getDevices() async { - final response = await request( - RequestType.GET, - '/client/r0/devices', - ); - return (response['devices'] as List) - .map((i) => Device.fromJson(i)) - .toList(); - } - - /// Gets information on a single device, by device id. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-devices-deviceid - Future getDevice(String deviceId) async { - final response = await request( - RequestType.GET, - '/client/r0/devices/${Uri.encodeComponent(deviceId)}', - ); - return Device.fromJson(response); - } - - /// Updates the metadata on the given device. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-devices-deviceid - Future updateDevice(String deviceId, {String displayName}) async { - await request( - RequestType.PUT, '/client/r0/devices/${Uri.encodeComponent(deviceId)}', - data: { - if (displayName != null) 'display_name': displayName, - }); - return; - } - - /// Deletes the given device, and invalidates any access token associated with it. - /// https://matrix.org/docs/spec/client_server/r0.6.1#delete-matrix-client-r0-devices-deviceid - Future deleteDevice(String deviceId, {AuthenticationData auth}) async { - await request(RequestType.DELETE, - '/client/r0/devices/${Uri.encodeComponent(deviceId)}', - data: { - if (auth != null) 'auth': auth.toJson(), - }); - return; - } - - /// Deletes the given devices, and invalidates any access token associated with them. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-delete-devices - Future deleteDevices(List deviceIds, - {AuthenticationData auth}) async { - await request(RequestType.POST, '/client/r0/delete_devices', data: { - 'devices': deviceIds, - if (auth != null) 'auth': auth.toJson(), - }); - return; - } - /// Publishes end-to-end encryption keys for the device. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query Future> uploadKeys( @@ -1436,53 +406,6 @@ class MatrixApi { return Map.from(response['one_time_key_counts']); } - /// Returns the current devices and identity keys for the given users. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query - Future queryKeys( - Map deviceKeys, { - int timeout, - String token, - }) async { - final response = await request( - RequestType.POST, - '/client/r0/keys/query', - data: { - 'device_keys': deviceKeys, - if (timeout != null) 'timeout': timeout, - if (token != null) 'token': token, - }, - ); - return KeysQueryResponse.fromJson(response); - } - - /// Claims one-time keys for use in pre-key messages. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-claim - Future claimKeys( - Map> oneTimeKeys, { - int timeout, - }) async { - final response = await request( - RequestType.POST, - '/client/r0/keys/claim', - data: { - 'one_time_keys': oneTimeKeys, - if (timeout != null) 'timeout': timeout, - }, - ); - return OneTimeKeysClaimResponse.fromJson(response); - } - - /// Gets a list of users who have updated their device identity keys since a previous sync token. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-upload - Future getKeysChanges(String from, String to) async { - final response = - await request(RequestType.GET, '/client/r0/keys/changes', query: { - 'from': from, - 'to': to, - }); - return DeviceListsUpdate.fromJson(response); - } - /// Uploads your own cross-signing keys. /// https://github.com/matrix-org/matrix-doc/pull/2536 Future uploadDeviceSigningKeys({ @@ -1534,18 +457,6 @@ class MatrixApi { return UploadKeySignaturesResponse.fromJson(response); } - /// Gets all currently active pushers for the authenticated user. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushers - Future> getPushers() async { - final response = await request( - RequestType.GET, - '/client/r0/pushers', - ); - return (response['pushers'] as List) - .map((i) => Pusher.fromJson(i)) - .toList(); - } - /// This endpoint allows the creation, modification and deletion of pushers /// for this user ID. The behaviour of this endpoint varies depending on the /// values in the JSON body. @@ -1563,169 +474,6 @@ class MatrixApi { return; } - /// This API is used to paginate through the list of events that the user has - /// been, or would have been notified about. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-notifications - Future getNotifications({ - String from, - int limit, - String only, - }) async { - final response = await request( - RequestType.GET, - '/client/r0/notifications', - query: { - if (from != null) 'from': from, - if (limit != null) 'limit': limit.toString(), - if (only != null) 'only': only, - }, - ); - return NotificationsQueryResponse.fromJson(response); - } - - /// Retrieve all push rulesets for this user. Clients can "drill-down" - /// on the rulesets by suffixing a scope to this path e.g. /pushrules/global/. - /// This will return a subset of this data under the specified key e.g. the global key. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules - Future getPushRules() async { - final response = await request( - RequestType.GET, - '/client/r0/pushrules', - ); - return PushRuleSet.fromJson(response['global']); - } - - /// Retrieve a single specified push rule. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid - Future getPushRule( - String scope, - PushRuleKind kind, - String ruleId, - ) async { - final response = await request( - RequestType.GET, - '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}', - ); - return PushRule.fromJson(response); - } - - /// This endpoint removes the push rule defined in the path. - /// https://matrix.org/docs/spec/client_server/r0.6.1#delete-matrix-client-r0-pushrules-scope-kind-ruleid - Future deletePushRule( - String scope, - PushRuleKind kind, - String ruleId, - ) async { - await request( - RequestType.DELETE, - '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}', - ); - return; - } - - /// This endpoint allows the creation, modification and deletion of pushers for this user ID. - /// The behaviour of this endpoint varies depending on the values in the JSON body. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-pushrules-scope-kind-ruleid - Future setPushRule( - String scope, - PushRuleKind kind, - String ruleId, - List actions, { - String before, - String after, - List conditions, - String pattern, - }) async { - await request(RequestType.PUT, - '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}', - query: { - if (before != null) 'before': before, - if (after != null) 'after': after, - }, - data: { - 'actions': actions.map(describeEnum).toList(), - if (conditions != null) - 'conditions': conditions.map((c) => c.toJson()).toList(), - if (pattern != null) 'pattern': pattern, - }); - return; - } - - /// This endpoint gets whether the specified push rule is enabled. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid-enabled - Future isPushRuleEnabled( - String scope, - PushRuleKind kind, - String ruleId, - ) async { - final response = await request( - RequestType.GET, - '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}/enabled', - ); - return response['enabled']; - } - - /// This endpoint allows clients to enable or disable the specified push rule. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-pushrules-scope-kind-ruleid-enabled - Future setPushRuleEnabled( - String scope, - PushRuleKind kind, - String ruleId, - bool enabled, - ) async { - await request( - RequestType.PUT, - '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}/enabled', - data: {'enabled': enabled}, - ); - return; - } - - /// This endpoint get the actions for the specified push rule. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-pushrules-scope-kind-ruleid-actions - Future> getPushRuleActions( - String scope, - PushRuleKind kind, - String ruleId, - ) async { - final response = await request( - RequestType.GET, - '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}/actions', - ); - return (response['actions'] as List) - .map((i) => - PushRuleAction.values.firstWhere((a) => describeEnum(a) == i)) - .toList(); - } - - /// This endpoint allows clients to change the actions of a push rule. This can be used to change the actions of builtin rules. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-pushrules-scope-kind-ruleid-actions - Future setPushRuleActions( - String scope, - PushRuleKind kind, - String ruleId, - List actions, - ) async { - await request( - RequestType.PUT, - '/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(describeEnum(kind))}/${Uri.encodeComponent(ruleId)}/actions', - data: {'actions': actions.map((a) => describeEnum(a)).toList()}, - ); - return; - } - - /// Performs a full text search across different categories. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-search - /// Please note: The specification is not 100% clear what it is expecting and sending here. - /// So we stick with pure json until we have more information. - Future> search(Map query) async { - return await request( - RequestType.POST, - '/client/r0/search', - data: query, - ); - } - /// This will listen for new events related to a particular room and return them to the /// caller. This will block until an event is received, or until the timeout is reached. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-events @@ -1743,147 +491,6 @@ class MatrixApi { return EventsSyncUpdate.fromJson(response); } - /// List the tags set by a user on a room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-rooms-roomid-tags - Future> getRoomTags(String userId, String roomId) async { - final response = await request( - RequestType.GET, - '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags', - ); - return (response['tags'] as Map).map( - (k, v) => MapEntry(k, Tag.fromJson(v)), - ); - } - - /// Add a tag to the room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-tags-tag - Future setRoomTag( - String userId, - String roomId, - String tag, { - double order, - }) async { - await request(RequestType.PUT, - '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}', - data: { - if (order != null) 'order': order, - }); - return; - } - - /// Remove a tag from the room. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-tags-tag - Future deleteRoomTag(String userId, String roomId, String tag) async { - await request( - RequestType.DELETE, - '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}', - ); - return; - } - - /// Set some account_data for the client. This config is only visible to the user that set the account_data. - /// The config will be synced to clients in the top-level account_data. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-account-data-type - Future setAccountData( - String userId, - String type, - Map content, - ) async { - await request( - RequestType.PUT, - '/client/r0/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}', - data: content, - ); - return; - } - - /// Get some account_data for the client. This config is only visible to the user that set the account_data. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-account-data-type - Future> getAccountData( - String userId, - String type, - ) async { - return await request( - RequestType.GET, - '/client/r0/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}', - ); - } - - /// Set some account_data for the client on a given room. This config is only visible to the user that set - /// the account_data. The config will be synced to clients in the per-room account_data. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-user-userid-rooms-roomid-account-data-type - Future setAccountDataPerRoom( - String userId, - String roomId, - String type, - Map content, - ) async { - await request( - RequestType.PUT, - '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}', - data: content, - ); - return; - } - - /// Get some account_data for the client on a given room. This config is only visible to the user that set the account_data. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-user-userid-rooms-roomid-account-data-type - Future> getAccountDataPerRoom( - String userId, - String roomId, - String type, - ) async { - return await request( - RequestType.GET, - '/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}', - ); - } - - /// Gets information about a particular user. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-admin-whois-userid - Future getWhoIs(String userId) async { - final response = await request( - RequestType.GET, - '/client/r0/admin/whois/${Uri.encodeComponent(userId)}', - ); - return WhoIsInfo.fromJson(response); - } - - /// This API returns a number of events that happened just before and after the specified event. - /// This allows clients to get the context surrounding an event. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-context-eventid - Future getEventContext( - String roomId, - String eventId, { - int limit, - String filter, - }) async { - final response = await request(RequestType.GET, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/context/${Uri.encodeComponent(eventId)}', - query: { - if (filter != null) 'filter': filter, - if (limit != null) 'limit': limit.toString(), - }); - return EventContext.fromJson(response); - } - - /// Reports an event as inappropriate to the server, which may then notify the appropriate people. - /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-rooms-roomid-report-eventid - Future reportContent( - String roomId, - String eventId, - String reason, - int score, - ) async { - await request(RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/report/${Uri.encodeComponent(eventId)}', - data: { - 'reason': reason, - 'score': score, - }); - return; - } - /// Fetches the overall metadata about protocols supported by the homeserver. Includes /// both the available protocols and all fields required for queries against each protocol. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-protocols @@ -1959,68 +566,6 @@ class MatrixApi { .toList(); } - Future requestOpenIdToken(String userId) async { - final response = await request( - RequestType.POST, - '/client/r0/user/${Uri.encodeComponent(userId)}/openid/request_token', - data: {}, - ); - return OpenIdCredentials.fromJson(response); - } - - Future upgradeRoom(String roomId, String version) async { - await request( - RequestType.POST, - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/upgrade', - data: {'new_version': version}, - ); - return; - } - - /// Create room keys backup - /// https://matrix.org/docs/spec/client_server/unstable#post-matrix-client-r0-room-keys-version - Future createRoomKeysBackup( - RoomKeysAlgorithmType algorithm, Map authData) async { - final ret = await request( - RequestType.POST, - '/client/unstable/room_keys/version', - data: { - 'algorithm': algorithm.algorithmString, - 'auth_data': authData, - }, - ); - return ret['version']; - } - - /// Gets a room key backup - /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-version - Future getRoomKeysBackup([String version]) async { - var url = '/client/unstable/room_keys/version'; - if (version != null) { - url += '/${Uri.encodeComponent(version)}'; - } - final ret = await request( - RequestType.GET, - url, - ); - return RoomKeysVersionResponse.fromJson(ret); - } - - /// Updates a room key backup - /// https://matrix.org/docs/spec/client_server/unstable#put-matrix-client-r0-room-keys-version-version - Future updateRoomKeysBackup(String version, - RoomKeysAlgorithmType algorithm, Map authData) async { - await request( - RequestType.PUT, - '/client/unstable/room_keys/version/${Uri.encodeComponent(version)}', - data: { - 'algorithm': algorithm.algorithmString, - 'auth_data': authData, - 'version': version, - }, - ); - } - /// Deletes a room key backup /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-version-version Future deleteRoomKeysBackup(String version) async { @@ -2030,19 +575,6 @@ class MatrixApi { ); } - /// Stores a single room key - /// https://matrix.org/docs/spec/client_server/unstable#put-matrix-client-r0-room-keys-keys-roomid-sessionid - Future storeRoomKeysSingleKey(String roomId, - String sessionId, String version, RoomKeysSingleKey session) async { - final ret = await request( - RequestType.PUT, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', - query: {'version': version}, - data: session.toJson(), - ); - return RoomKeysUpdateResponse.fromJson(ret); - } - /// Gets a single room key /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys-roomid-sessionid Future getRoomKeysSingleKey( @@ -2067,19 +599,6 @@ class MatrixApi { return RoomKeysUpdateResponse.fromJson(ret); } - /// Stores room keys for a room - /// https://matrix.org/docs/spec/client_server/unstable#put-matrix-client-r0-room-keys-keys-roomid - Future storeRoomKeysRoom( - String roomId, String version, RoomKeysRoom keys) async { - final ret = await request( - RequestType.PUT, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', - query: {'version': version}, - data: keys.toJson(), - ); - return RoomKeysUpdateResponse.fromJson(ret); - } - /// Gets room keys for a room /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys-roomid Future getRoomKeysRoom(String roomId, String version) async { @@ -2103,19 +622,6 @@ class MatrixApi { return RoomKeysUpdateResponse.fromJson(ret); } - /// Store multiple room keys - /// https://matrix.org/docs/spec/client_server/unstable#put-matrix-client-r0-room-keys-keys - Future storeRoomKeys( - String version, RoomKeys keys) async { - final ret = await request( - RequestType.PUT, - '/client/unstable/room_keys/keys', - query: {'version': version}, - data: keys.toJson(), - ); - return RoomKeysUpdateResponse.fromJson(ret); - } - /// get all room keys /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys Future getRoomKeys(String version) async { diff --git a/lib/src/model/algorithm_types.dart b/lib/src/model/algorithm_types.dart index e4f8548b..207ccd96 100644 --- a/lib/src/model/algorithm_types.dart +++ b/lib/src/model/algorithm_types.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 2d8e0632..68441c43 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index 29242a83..14047d42 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index f727c6c0..99d2c26d 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index d45a3eab..7ae42bf6 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index a98ec159..256f1931 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index e8dabf3b..3cb44fe3 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 41c04d6c..faaef644 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index d8e96301..32d42dd3 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_types.dart b/lib/src/model/auth/authentication_types.dart index ea181e40..2a667ee6 100644 --- a/lib/src/model/auth/authentication_types.dart +++ b/lib/src/model/auth/authentication_types.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index 7531bdd8..0e1a98dc 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index cd708d48..0be5741f 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index 8a99781c..78a7979b 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index 3a3dbb86..4e9a0cf5 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/device.dart b/lib/src/model/device.dart deleted file mode 100644 index 825c828d..00000000 --- a/lib/src/model/device.dart +++ /dev/null @@ -1,51 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class Device { - String deviceId; - String displayName; - String lastSeenIp; - DateTime lastSeenTs; - - Device.fromJson(Map json) - : deviceId = json['device_id'], - displayName = json['display_name'], - lastSeenIp = json['last_seen_ip'], - lastSeenTs = - DateTime.fromMillisecondsSinceEpoch(json['last_seen_ts'] ?? 0); - - Map toJson() { - final data = {}; - data['device_id'] = deviceId; - if (displayName != null) { - data['display_name'] = displayName; - } - if (lastSeenIp != null) { - data['last_seen_ip'] = lastSeenIp; - } - if (lastSeenTs != null) { - data['last_seen_ts'] = lastSeenTs.millisecondsSinceEpoch; - } - return data; - } -} diff --git a/lib/src/model/event_context.dart b/lib/src/model/event_context.dart deleted file mode 100644 index 90620915..00000000 --- a/lib/src/model/event_context.dart +++ /dev/null @@ -1,75 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'matrix_event.dart'; - -class EventContext { - String end; - List eventsAfter; - MatrixEvent event; - List eventsBefore; - String start; - List state; - - EventContext.fromJson(Map json) - : end = json['end'], - eventsAfter = (json['events_after'] != null) - ? (json['events_after'] as List) - .map((v) => MatrixEvent.fromJson(v)) - .toList() - : null, - event = - json['event'] != null ? MatrixEvent.fromJson(json['event']) : null, - eventsBefore = (json['events_before'] != null) - ? (json['events_before'] as List) - .map((v) => MatrixEvent.fromJson(v)) - .toList() - : null, - start = json['start'], - state = (json['state'] != null) - ? (json['state'] as List) - .map((v) => MatrixEvent.fromJson(v)) - .toList() - : null; - - Map toJson() { - final data = {}; - if (end != null) { - data['end'] = end; - } - if (eventsAfter != null) { - data['events_after'] = eventsAfter.map((v) => v.toJson()).toList(); - } - if (event != null) { - data['event'] = event.toJson(); - } - if (eventsBefore != null) { - data['events_before'] = eventsBefore.map((v) => v.toJson()).toList(); - } - data['start'] = start; - if (state != null) { - data['state'] = state.map((v) => v.toJson()).toList(); - } - return data; - } -} diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index 69251296..50840346 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/forwarded_room_key_content.dart b/lib/src/model/events/forwarded_room_key_content.dart index 73eac32e..a9b238fc 100644 --- a/lib/src/model/events/forwarded_room_key_content.dart +++ b/lib/src/model/events/forwarded_room_key_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/olm_plaintext_payload.dart b/lib/src/model/events/olm_plaintext_payload.dart index c4a918d5..55f377f3 100644 --- a/lib/src/model/events/olm_plaintext_payload.dart +++ b/lib/src/model/events/olm_plaintext_payload.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index def336dc..0b132541 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/src/model/events/room_encryption_content.dart index 15ea46f0..33afcda2 100644 --- a/lib/src/model/events/room_encryption_content.dart +++ b/lib/src/model/events/room_encryption_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/room_key_content.dart b/lib/src/model/events/room_key_content.dart index 4a78e36f..8686db21 100644 --- a/lib/src/model/events/room_key_content.dart +++ b/lib/src/model/events/room_key_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index c48a1fba..ca690e52 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/src/model/events/secret_storage_default_key_content.dart index f5067a34..a8630813 100644 --- a/lib/src/model/events/secret_storage_default_key_content.dart +++ b/lib/src/model/events/secret_storage_default_key_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index 899fead4..de7e3618 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/tombstone_content.dart b/lib/src/model/events/tombstone_content.dart index dfc8beef..9e939223 100644 --- a/lib/src/model/events/tombstone_content.dart +++ b/lib/src/model/events/tombstone_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart index 1e53d9ee..1a215473 100644 --- a/lib/src/model/events_sync_update.dart +++ b/lib/src/model/events_sync_update.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/filter.dart b/lib/src/model/filter.dart deleted file mode 100644 index 68146542..00000000 --- a/lib/src/model/filter.dart +++ /dev/null @@ -1,219 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -enum EventFormat { client, federation } - -class Filter { - RoomFilter room; - EventFilter presence; - EventFilter accountData; - EventFormat eventFormat; - List eventFields; - - Filter({ - this.room, - this.presence, - this.accountData, - this.eventFormat, - this.eventFields, - }); - - Filter.fromJson(Map json) - : room = json['room'] != null ? RoomFilter.fromJson(json['room']) : null, - presence = json['presence'] != null - ? EventFilter.fromJson(json['presence']) - : null, - accountData = json['account_data'] != null - ? EventFilter.fromJson(json['account_data']) - : null, - eventFormat = json['event_format'] != null - ? EventFormat.values.firstWhere( - (e) => e.toString().split('.').last == json['event_format']) - : null, - eventFields = json['event_fields'] != null - ? json['event_fields'].cast() - : null; - - Map toJson() { - final data = {}; - if (room != null) { - data['room'] = room.toJson(); - } - if (presence != null) { - data['presence'] = presence.toJson(); - } - if (eventFormat != null) { - data['event_format'] = eventFormat.toString().split('.').last; - } - if (eventFields != null) { - data['event_fields'] = eventFields; - } - if (accountData != null) { - data['account_data'] = accountData.toJson(); - } - return data; - } -} - -class RoomFilter { - List notRooms; - List rooms; - StateFilter ephemeral; - bool includeLeave; - StateFilter state; - StateFilter timeline; - StateFilter accountData; - - RoomFilter({ - this.notRooms, - this.rooms, - this.ephemeral, - this.includeLeave, - this.state, - this.timeline, - this.accountData, - }); - - RoomFilter.fromJson(Map json) { - notRooms = json['not_rooms']?.cast(); - rooms = json['rooms']?.cast(); - state = json['state'] != null ? StateFilter.fromJson(json['state']) : null; - includeLeave = json['include_leave']; - timeline = json['timeline'] != null - ? StateFilter.fromJson(json['timeline']) - : null; - ephemeral = json['ephemeral'] != null - ? StateFilter.fromJson(json['ephemeral']) - : null; - accountData = json['account_data'] != null - ? StateFilter.fromJson(json['account_data']) - : null; - } - - Map toJson() { - final data = {}; - if (notRooms != null) { - data['not_rooms'] = notRooms; - } - if (rooms != null) { - data['rooms'] = rooms; - } - if (ephemeral != null) { - data['ephemeral'] = ephemeral.toJson(); - } - if (includeLeave != null) { - data['include_leave'] = includeLeave; - } - if (state != null) { - data['state'] = state.toJson(); - } - if (timeline != null) { - data['timeline'] = timeline.toJson(); - } - if (accountData != null) { - data['account_data'] = accountData.toJson(); - } - return data; - } -} - -class EventFilter { - int limit; - List senders; - List types; - List notRooms; - List notSenders; - - EventFilter( - {this.limit, this.senders, this.types, this.notRooms, this.notSenders}); - - EventFilter.fromJson(Map json) { - limit = json['limit']; - types = json['senders']?.cast(); - types = json['types']?.cast(); - notRooms = json['not_rooms']?.cast(); - notSenders = json['not_senders']?.cast(); - } - - Map toJson() { - final data = {}; - if (limit != null) data['limit'] = limit; - if (types != null) data['types'] = types; - if (notRooms != null) data['not_rooms'] = notRooms; - if (notSenders != null) data['not_senders'] = notSenders; - return data; - } -} - -class StateFilter extends EventFilter { - List notTypes; - bool lazyLoadMembers; - bool includeRedundantMembers; - bool containsUrl; - - StateFilter({ - this.notTypes, - this.lazyLoadMembers, - this.includeRedundantMembers, - this.containsUrl, - int limit, - List senders, - List types, - List notRooms, - List notSenders, - }) : super( - limit: limit, - senders: senders, - types: types, - notRooms: notRooms, - notSenders: notSenders, - ); - - StateFilter.fromJson(Map json) : super.fromJson(json) { - notTypes = json['not_types']?.cast(); - lazyLoadMembers = json['lazy_load_members']; - includeRedundantMembers = json['include_redundant_members']; - containsUrl = json['contains_url']; - } - - @override - Map toJson() { - final data = super.toJson(); - if (limit != null) { - data['limit'] = limit; - } - if (notTypes != null) { - data['not_types'] = notTypes; - } - if (lazyLoadMembers != null) { - data['lazy_load_members'] = lazyLoadMembers; - } - if (includeRedundantMembers != null) { - data['include_redundant_members'] = includeRedundantMembers; - } - if (containsUrl != null) { - data['contains_url'] = containsUrl; - } - return data; - } -} diff --git a/lib/src/model/keys_query_response.dart b/lib/src/model/keys_query_response.dart deleted file mode 100644 index ccbc80ff..00000000 --- a/lib/src/model/keys_query_response.dart +++ /dev/null @@ -1,118 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'matrix_keys.dart'; -import '../utils/map_copy_extension.dart'; - -class KeysQueryResponse { - Map failures; - Map> deviceKeys; - Map masterKeys; - Map selfSigningKeys; - Map userSigningKeys; - - KeysQueryResponse.fromJson(Map json) - : failures = (json['failures'] as Map)?.copy(), - deviceKeys = json['device_keys'] != null - ? (json['device_keys'] as Map).map( - (k, v) => MapEntry( - k, - (v as Map).map( - (k, v) => MapEntry( - k, - MatrixDeviceKeys.fromJson(v), - ), - ), - ), - ) - : null, - masterKeys = json['master_keys'] != null - ? (json['master_keys'] as Map).map( - (k, v) => MapEntry( - k, - MatrixCrossSigningKey.fromJson(v), - ), - ) - : null, - selfSigningKeys = json['self_signing_keys'] != null - ? (json['self_signing_keys'] as Map).map( - (k, v) => MapEntry( - k, - MatrixCrossSigningKey.fromJson(v), - ), - ) - : null, - userSigningKeys = json['user_signing_keys'] != null - ? (json['user_signing_keys'] as Map).map( - (k, v) => MapEntry( - k, - MatrixCrossSigningKey.fromJson(v), - ), - ) - : null; - - Map toJson() { - final data = {}; - if (failures != null) { - data['failures'] = failures; - } - if (deviceKeys != null) { - data['device_keys'] = deviceKeys.map( - (k, v) => MapEntry( - k, - v.map( - (k, v) => MapEntry( - k, - v.toJson(), - ), - ), - ), - ); - } - if (masterKeys != null) { - data['master_keys'] = masterKeys.map( - (k, v) => MapEntry( - k, - v.toJson(), - ), - ); - } - if (selfSigningKeys != null) { - data['self_signing_keys'] = selfSigningKeys.map( - (k, v) => MapEntry( - k, - v.toJson(), - ), - ); - } - if (userSigningKeys != null) { - data['user_signing_keys'] = userSigningKeys.map( - (k, v) => MapEntry( - k, - v.toJson(), - ), - ); - } - return data; - } -} diff --git a/lib/src/model/login_response.dart b/lib/src/model/login_response.dart deleted file mode 100644 index 625739e7..00000000 --- a/lib/src/model/login_response.dart +++ /dev/null @@ -1,50 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'well_known_information.dart'; - -class LoginResponse { - String userId; - String accessToken; - String deviceId; - WellKnownInformation wellKnownInformation; - - LoginResponse.fromJson(Map json) - : userId = json['user_id'], - accessToken = json['access_token'], - deviceId = json['device_id'], - wellKnownInformation = (json['well_known'] is Map) - ? WellKnownInformation.fromJson(json['well_known']) - : null; - - Map toJson() { - final data = {}; - if (userId != null) data['user_id'] = userId; - if (accessToken != null) data['access_token'] = accessToken; - if (deviceId != null) data['device_id'] = deviceId; - if (wellKnownInformation != null) { - data['well_known'] = wellKnownInformation.toJson(); - } - return data; - } -} diff --git a/lib/src/model/login_types.dart b/lib/src/model/login_types.dart deleted file mode 100644 index de8dca7f..00000000 --- a/lib/src/model/login_types.dart +++ /dev/null @@ -1,54 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class LoginTypes { - List flows; - - LoginTypes.fromJson(Map json) { - if (json['flows'] != null) { - flows = (json['flows'] as List).map((v) => Flows.fromJson(v)).toList(); - } - } - - Map toJson() { - final data = {}; - if (flows != null) { - data['flows'] = flows.map((v) => v.toJson()).toList(); - } - return data; - } -} - -class Flows { - String type; - - Flows.fromJson(Map json) { - type = json['type']; - } - - Map toJson() { - final data = {}; - data['type'] = type; - return data; - } -} diff --git a/lib/src/model/matrix_connection_exception.dart b/lib/src/model/matrix_connection_exception.dart index a7046525..d9cfb113 100644 --- a/lib/src/model/matrix_connection_exception.dart +++ b/lib/src/model/matrix_connection_exception.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index c45e2615..a2aba791 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 1e1b3bf4..4365d4ef 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index 44ebbc8e..9f179480 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/message_types.dart b/lib/src/model/message_types.dart index d6745350..0a9b240c 100644 --- a/lib/src/model/message_types.dart +++ b/lib/src/model/message_types.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/notifications_query_response.dart b/lib/src/model/notifications_query_response.dart deleted file mode 100644 index 83e0d767..00000000 --- a/lib/src/model/notifications_query_response.dart +++ /dev/null @@ -1,75 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'matrix_event.dart'; - -class NotificationsQueryResponse { - String nextToken; - List notifications; - - NotificationsQueryResponse.fromJson(Map json) - : nextToken = json['next_token'], - notifications = (json['notifications'] as List) - .map((v) => Notification.fromJson(v)) - .toList(); - - Map toJson() { - final data = {}; - if (nextToken != null) { - data['next_token'] = nextToken; - } - data['notifications'] = notifications.map((v) => v.toJson()).toList(); - return data; - } -} - -class Notification { - List actions; - String profileTag; - bool read; - String roomId; - int ts; - MatrixEvent event; - - Notification.fromJson(Map json) { - actions = json['actions'].cast(); - profileTag = json['profile_tag']; - read = json['read']; - roomId = json['room_id']; - ts = json['ts']; - event = MatrixEvent.fromJson(json['event']); - } - - Map toJson() { - final data = {}; - data['actions'] = actions; - if (profileTag != null) { - data['profile_tag'] = profileTag; - } - data['read'] = read; - data['room_id'] = roomId; - data['ts'] = ts; - data['event'] = event.toJson(); - return data; - } -} diff --git a/lib/src/model/one_time_keys_claim_response.dart b/lib/src/model/one_time_keys_claim_response.dart deleted file mode 100644 index 525d2c9c..00000000 --- a/lib/src/model/one_time_keys_claim_response.dart +++ /dev/null @@ -1,46 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import '../utils/map_copy_extension.dart'; - -class OneTimeKeysClaimResponse { - Map failures; - Map> oneTimeKeys; - - OneTimeKeysClaimResponse.fromJson(Map json) - : failures = (json['failures'] as Map)?.copy() ?? {}, - // We still need a Map<...>.from(...) to ensure all second-level entries are also maps - oneTimeKeys = Map>.from( - (json['one_time_keys'] as Map).copy()); - - Map toJson() { - final data = {}; - if (failures != null) { - data['failures'] = failures; - } - if (oneTimeKeys != null) { - data['one_time_keys'] = oneTimeKeys; - } - return data; - } -} diff --git a/lib/src/model/open_graph_data.dart b/lib/src/model/open_graph_data.dart deleted file mode 100644 index 48a8b1f4..00000000 --- a/lib/src/model/open_graph_data.dart +++ /dev/null @@ -1,67 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class OpenGraphData { - String ogTitle; - String ogDescription; - String ogImage; - String ogImageType; - int ogImageHeight; - int ogImageWidth; - int matrixImageSize; - - OpenGraphData.fromJson(Map json) - : ogTitle = json['og:title'], - ogDescription = json['og:description'], - ogImage = json['og:image'], - ogImageType = json['og:image:type'], - ogImageHeight = json['og:image:height'], - ogImageWidth = json['og:image:width'], - matrixImageSize = json['matrix:image:size']; - - Map toJson() { - final data = {}; - if (ogTitle != null) { - data['og:title'] = ogTitle; - } - if (ogDescription != null) { - data['og:description'] = ogDescription; - } - if (ogImage != null) { - data['og:image'] = ogImage; - } - if (ogImageType != null) { - data['og:image:type'] = ogImageType; - } - if (ogImageHeight != null) { - data['og:image:height'] = ogImageHeight; - } - if (ogImageWidth != null) { - data['og:image:width'] = ogImageWidth; - } - if (matrixImageSize != null) { - data['matrix:image:size'] = matrixImageSize; - } - return data; - } -} diff --git a/lib/src/model/open_id_credentials.dart b/lib/src/model/open_id_credentials.dart deleted file mode 100644 index e398ffa3..00000000 --- a/lib/src/model/open_id_credentials.dart +++ /dev/null @@ -1,44 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class OpenIdCredentials { - String accessToken; - String tokenType; - String matrixServerName; - double expiresIn; - - OpenIdCredentials.fromJson(Map json) - : accessToken = json['access_token'], - tokenType = json['token_type'], - matrixServerName = json['matrix_server_name'], - expiresIn = json['expires_in']; - - Map toJson() { - final data = {}; - data['access_token'] = accessToken; - data['token_type'] = tokenType; - data['matrix_server_name'] = matrixServerName; - data['expires_in'] = expiresIn; - return data; - } -} diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index 73848c2e..c5091d5c 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index 597082f3..b7bab947 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -21,7 +22,7 @@ * SOFTWARE. */ -enum PresenceType { online, offline, unavailable } +import '../generated/model.dart'; class PresenceContent { PresenceType presence; diff --git a/lib/src/model/profile.dart b/lib/src/model/profile.dart deleted file mode 100644 index 79c6a38e..00000000 --- a/lib/src/model/profile.dart +++ /dev/null @@ -1,49 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class Profile { - /// The user's avatar URL if they have set one, otherwise null. - Uri avatarUrl; - - /// The user's display name if they have set one, otherwise null. - String displayname; - - /// The matrix ID of this user. May be omitted. - String userId; - - Map additionalContent; - - Profile(this.displayname, this.avatarUrl, - {this.additionalContent = const {}}); - - Profile.fromJson(Map json) - : avatarUrl = - json['avatar_url'] != null ? Uri.parse(json['avatar_url']) : null, - displayname = json['display_name'] ?? json['displayname'], - userId = json['user_id'], - additionalContent = json; - - Map toJson() { - return additionalContent; - } -} diff --git a/lib/src/model/public_rooms_response.dart b/lib/src/model/public_rooms_response.dart deleted file mode 100644 index 7fdfabdd..00000000 --- a/lib/src/model/public_rooms_response.dart +++ /dev/null @@ -1,98 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class PublicRoomsResponse { - List chunk; - String nextBatch; - String prevBatch; - int totalRoomCountEstimate; - - PublicRoomsResponse.fromJson(Map json) - : chunk = - (json['chunk'] as List).map((v) => PublicRoom.fromJson(v)).toList(), - nextBatch = json['next_batch'], - prevBatch = json['prev_batch'], - totalRoomCountEstimate = json['total_room_count_estimate']; - - Map toJson() { - final data = {}; - data['chunk'] = chunk.map((v) => v.toJson()).toList(); - if (nextBatch != null) { - data['next_batch'] = nextBatch; - } - if (prevBatch != null) { - data['prev_batch'] = prevBatch; - } - if (totalRoomCountEstimate != null) { - data['total_room_count_estimate'] = totalRoomCountEstimate; - } - return data; - } -} - -class PublicRoom { - List aliases; - String avatarUrl; - bool guestCanJoin; - String name; - int numJoinedMembers; - String roomId; - String topic; - bool worldReadable; - String canonicalAlias; - - PublicRoom.fromJson(Map json) - : aliases = json['aliases']?.cast(), - avatarUrl = json['avatar_url'], - guestCanJoin = json['guest_can_join'], - canonicalAlias = json['canonical_alias'], - name = json['name'], - numJoinedMembers = json['num_joined_members'], - roomId = json['room_id'], - topic = json['topic'], - worldReadable = json['world_readable']; - - Map toJson() { - final data = {}; - if (aliases != null) { - data['aliases'] = aliases; - } - if (canonicalAlias != null) { - data['canonical_alias'] = canonicalAlias; - } - if (avatarUrl != null) { - data['avatar_url'] = avatarUrl; - } - data['guest_can_join'] = guestCanJoin; - if (name != null) { - data['name'] = name; - } - data['num_joined_members'] = numJoinedMembers; - data['room_id'] = roomId; - if (topic != null) { - data['topic'] = topic; - } - data['world_readable'] = worldReadable; - return data; - } -} diff --git a/lib/src/model/push_rule_set.dart b/lib/src/model/push_rule_set.dart deleted file mode 100644 index 0055e5ad..00000000 --- a/lib/src/model/push_rule_set.dart +++ /dev/null @@ -1,148 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -enum PushRuleKind { content, override, room, sender, underride } -enum PushRuleAction { notify, dont_notify, coalesce, set_tweak } - -class PushRuleSet { - List content; - List override; - List room; - List sender; - List underride; - - PushRuleSet.fromJson(Map json) { - if (json['content'] != null) { - content = - (json['content'] as List).map((i) => PushRule.fromJson(i)).toList(); - } - if (json['override'] != null) { - override = - (json['override'] as List).map((i) => PushRule.fromJson(i)).toList(); - } - if (json['room'] != null) { - room = (json['room'] as List).map((i) => PushRule.fromJson(i)).toList(); - } - if (json['sender'] != null) { - sender = - (json['sender'] as List).map((i) => PushRule.fromJson(i)).toList(); - } - if (json['underride'] != null) { - underride = - (json['underride'] as List).map((i) => PushRule.fromJson(i)).toList(); - } - } - - Map toJson() { - final data = {}; - if (content != null) { - data['content'] = content.map((v) => v.toJson()).toList(); - } - if (override != null) { - data['override'] = override.map((v) => v.toJson()).toList(); - } - if (room != null) { - data['room'] = room.map((v) => v.toJson()).toList(); - } - if (sender != null) { - data['sender'] = sender.map((v) => v.toJson()).toList(); - } - if (underride != null) { - data['underride'] = underride.map((v) => v.toJson()).toList(); - } - return data; - } -} - -class PushRule { - List actions; - List conditions; - bool isDefault; - bool enabled; - String pattern; - String ruleId; - - PushRule.fromJson(Map json) { - actions = json['actions']; - isDefault = json['default']; - enabled = json['enabled']; - pattern = json['pattern']; - ruleId = json['rule_id']; - conditions = json['conditions'] != null - ? (json['conditions'] as List) - .map((i) => PushConditions.fromJson(i)) - .toList() - : null; - } - - Map toJson() { - final data = {}; - data['actions'] = actions; - data['default'] = isDefault; - data['enabled'] = enabled; - if (pattern != null) { - data['pattern'] = pattern; - } - if (conditions != null) { - data['conditions'] = conditions.map((i) => i.toJson()).toList(); - } - data['rule_id'] = ruleId; - return data; - } -} - -class PushConditions { - String key; - String kind; - String pattern; - String isOperator; - - PushConditions( - this.kind, { - this.key, - this.pattern, - this.isOperator, - }); - - PushConditions.fromJson(Map json) { - key = json['key']; - kind = json['kind']; - pattern = json['pattern']; - isOperator = json['is']; - } - - Map toJson() { - final data = {}; - if (key != null) { - data['key'] = key; - } - data['kind'] = kind; - if (pattern != null) { - data['pattern'] = pattern; - } - if (isOperator != null) { - data['is'] = isOperator; - } - return data; - } -} diff --git a/lib/src/model/pusher.dart b/lib/src/model/pusher.dart deleted file mode 100644 index 08d36577..00000000 --- a/lib/src/model/pusher.dart +++ /dev/null @@ -1,94 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class Pusher { - String pushkey; - String kind; - String appId; - String appDisplayName; - String deviceDisplayName; - String profileTag; - String lang; - PusherData data; - - Pusher( - this.pushkey, - this.appId, - this.appDisplayName, - this.deviceDisplayName, - this.lang, - this.data, { - this.profileTag, - this.kind, - }); - - Pusher.fromJson(Map json) - : pushkey = json['pushkey'], - kind = json['kind'], - appId = json['app_id'], - appDisplayName = json['app_display_name'], - deviceDisplayName = json['device_display_name'], - profileTag = json['profile_tag'], - lang = json['lang'], - data = PusherData.fromJson(json['data']); - - Map toJson() { - final data = {}; - data['pushkey'] = pushkey; - data['kind'] = kind; - data['app_id'] = appId; - data['app_display_name'] = appDisplayName; - data['device_display_name'] = deviceDisplayName; - if (profileTag != null) { - data['profile_tag'] = profileTag; - } - data['lang'] = lang; - data['data'] = this.data.toJson(); - return data; - } -} - -class PusherData { - Uri url; - String format; - - PusherData({ - this.url, - this.format, - }); - - PusherData.fromJson(Map json) - : format = json['format'], - url = json.containsKey('url') ? Uri.parse(json['url']) : null; - - Map toJson() { - final data = {}; - if (url != null) { - data['url'] = url.toString(); - } - if (format != null) { - data['format'] = format; - } - return data; - } -} diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart index e2001826..00dd1e68 100644 --- a/lib/src/model/request_token_response.dart +++ b/lib/src/model/request_token_response.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/room_alias_information.dart b/lib/src/model/room_alias_information.dart deleted file mode 100644 index 050b6b2c..00000000 --- a/lib/src/model/room_alias_information.dart +++ /dev/null @@ -1,38 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class RoomAliasInformation { - String roomId; - List servers; - - RoomAliasInformation.fromJson(Map json) - : roomId = json['room_id'], - servers = json['servers'].cast(); - - Map toJson() { - final data = {}; - data['room_id'] = roomId; - data['servers'] = servers; - return data; - } -} diff --git a/lib/src/model/room_creation_types.dart b/lib/src/model/room_creation_types.dart index 703f0ce1..fb41cb6c 100644 --- a/lib/src/model/room_creation_types.dart +++ b/lib/src/model/room_creation_types.dart @@ -1,3 +1,4 @@ +// @dart=2.9 abstract class RoomCreationTypes { static const String mSpace = 'm.space'; } diff --git a/lib/src/model/room_keys_info.dart b/lib/src/model/room_keys_info.dart deleted file mode 100644 index c300b298..00000000 --- a/lib/src/model/room_keys_info.dart +++ /dev/null @@ -1,73 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import '../../matrix_api_lite.dart'; - -enum RoomKeysAlgorithmType { v1Curve25519AesSha2 } - -extension RoomKeysAlgorithmTypeExtension on RoomKeysAlgorithmType { - String get algorithmString { - switch (this) { - case RoomKeysAlgorithmType.v1Curve25519AesSha2: - return AlgorithmTypes.megolmBackupV1Curve25519AesSha2; - default: - return null; - } - } - - static RoomKeysAlgorithmType fromAlgorithmString(String s) { - switch (s) { - case AlgorithmTypes.megolmBackupV1Curve25519AesSha2: - return RoomKeysAlgorithmType.v1Curve25519AesSha2; - default: - return null; - } - } -} - -class RoomKeysVersionResponse { - RoomKeysAlgorithmType algorithm; - Map authData; - int count; - String etag; - String version; - - RoomKeysVersionResponse.fromJson(Map json) - : algorithm = RoomKeysAlgorithmTypeExtension.fromAlgorithmString( - json['algorithm']), - authData = json['auth_data'], - count = json['count'], - etag = json['etag'] - .toString(), // synapse replies an int but docs say string? - version = json['version']; - - Map toJson() { - final data = {}; - data['algorithm'] = algorithm?.algorithmString; - data['auth_data'] = authData; - data['count'] = count; - data['etag'] = etag; - data['version'] = version; - return data; - } -} diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart index 54c2f102..0e8122ba 100644 --- a/lib/src/model/room_keys_keys.dart +++ b/lib/src/model/room_keys_keys.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -67,24 +68,6 @@ class RoomKeysRoom { } } -class RoomKeys { - Map rooms; - - RoomKeys({this.rooms}) { - rooms ??= {}; - } - - RoomKeys.fromJson(Map json) - : rooms = (json['rooms'] as Map) - .map((k, v) => MapEntry(k, RoomKeysRoom.fromJson(v))); - - Map toJson() { - final data = {}; - data['rooms'] = rooms.map((k, v) => MapEntry(k, v.toJson())); - return data; - } -} - class RoomKeysUpdateResponse { String etag; int count; diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index 664cd229..24a9d444 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/room_types.dart b/lib/src/model/room_types.dart index ba551ae9..6a84114f 100644 --- a/lib/src/model/room_types.dart +++ b/lib/src/model/room_types.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/server_capabilities.dart b/lib/src/model/server_capabilities.dart deleted file mode 100644 index b7053f84..00000000 --- a/lib/src/model/server_capabilities.dart +++ /dev/null @@ -1,95 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import '../utils/map_copy_extension.dart'; - -enum RoomVersionStability { stable, unstable } - -class ServerCapabilities { - MChangePassword mChangePassword; - MRoomVersions mRoomVersions; - Map customCapabilities; - - ServerCapabilities.fromJson(Map json) - : mChangePassword = json['m.change_password'] != null - ? MChangePassword.fromJson(json['m.change_password']) - : null, - mRoomVersions = json['m.room_versions'] != null - ? MRoomVersions.fromJson(json['m.room_versions']) - : null, - customCapabilities = json.copy() - ..remove('m.change_password') - ..remove('m.room_versions'); - - Map toJson() { - final data = {}; - if (mChangePassword != null) { - data['m.change_password'] = mChangePassword.toJson(); - } - if (mRoomVersions != null) { - data['m.room_versions'] = mRoomVersions.toJson(); - } - for (final entry in customCapabilities.entries) { - data[entry.key] = entry.value; - } - return data; - } -} - -class MChangePassword { - bool enabled; - - MChangePassword.fromJson(Map json) { - enabled = json['enabled']; - } - - Map toJson() { - final data = {}; - data['enabled'] = enabled; - return data; - } -} - -class MRoomVersions { - String defaultVersion; - Map available; - - MRoomVersions.fromJson(Map json) { - defaultVersion = json['default']; - available = (json['available'] as Map).map( - (k, v) => MapEntry( - k, - RoomVersionStability.values - .firstWhere((r) => r.toString().split('.').last == v), - ), - ); - } - - Map toJson() { - final data = {}; - data['default'] = defaultVersion; - data['available'] = available.map( - (k, v) => MapEntry(k, v.toString().split('.').last)); - return data; - } -} diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index bb8ad374..cf222869 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart index b9e4ad35..5a168f06 100644 --- a/lib/src/model/supported_protocol.dart +++ b/lib/src/model/supported_protocol.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/supported_versions.dart b/lib/src/model/supported_versions.dart deleted file mode 100644 index 42b8bc6b..00000000 --- a/lib/src/model/supported_versions.dart +++ /dev/null @@ -1,41 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class SupportedVersions { - List versions; - Map unstableFeatures; - - SupportedVersions.fromJson(Map json) - : versions = json['versions'].cast(), - unstableFeatures = - Map.from(json['unstable_features'] ?? {}); - - Map toJson() { - final data = {}; - data['versions'] = versions; - if (unstableFeatures != null) { - data['unstable_features'] = unstableFeatures; - } - return data; - } -} diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index a847eed5..c4d158a5 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/tag.dart b/lib/src/model/tag.dart deleted file mode 100644 index 3329b551..00000000 --- a/lib/src/model/tag.dart +++ /dev/null @@ -1,46 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class Tag { - double order; - - Tag.fromJson(Map json) - : order = double.tryParse(json['order'].toString()); - - Map toJson() { - final data = {}; - if (order != null) { - data['order'] = order; - } - return data; - } -} - -abstract class TagType { - static const String Favourite = 'm.favourite'; - static const String LowPriority = 'm.lowpriority'; - static const String ServerNotice = 'm.server_notice'; - static bool isValid(String tag) => tag.startsWith('m.') - ? [Favourite, LowPriority, ServerNotice].contains(tag) - : true; -} diff --git a/lib/src/model/third_party_identifier.dart b/lib/src/model/third_party_identifier.dart deleted file mode 100644 index b6ab7b90..00000000 --- a/lib/src/model/third_party_identifier.dart +++ /dev/null @@ -1,47 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import '../matrix_api.dart'; - -class ThirdPartyIdentifier { - ThirdPartyIdentifierMedium medium; - String address; - int validatedAt; - int addedAt; - - ThirdPartyIdentifier.fromJson(Map json) - : medium = ThirdPartyIdentifierMedium.values - .firstWhere((medium) => describeEnum(medium) == json['medium']), - address = json['address'], - validatedAt = json['validated_at'], - addedAt = json['added_at']; - - Map toJson() { - final data = {}; - data['medium'] = describeEnum(medium); - data['address'] = address; - data['validated_at'] = validatedAt; - data['added_at'] = addedAt; - return data; - } -} diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index a2271f9b..cfcad4d4 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index a4289b2a..65a23dc5 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/timeline_history_response.dart b/lib/src/model/timeline_history_response.dart deleted file mode 100644 index e9806b89..00000000 --- a/lib/src/model/timeline_history_response.dart +++ /dev/null @@ -1,54 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'matrix_event.dart'; - -class TimelineHistoryResponse { - String start; - String end; - List chunk; - List state; - - TimelineHistoryResponse.fromJson(Map json) - : start = json['start'], - end = json['end'], - chunk = json['chunk'] != null - ? (json['chunk'] as List) - .map((i) => MatrixEvent.fromJson(i)) - .toList() - : null, - state = json['state'] != null - ? (json['state'] as List) - .map((i) => MatrixEvent.fromJson(i)) - .toList() - : null; - - Map toJson() { - final data = {}; - if (start != null) data['start'] = start; - if (end != null) data['end'] = end; - if (chunk != null) data['chunk'] = chunk.map((i) => i.toJson()); - if (state != null) data['state'] = state.map((i) => i.toJson()); - return data; - } -} diff --git a/lib/src/model/turn_server_credentials.dart b/lib/src/model/turn_server_credentials.dart deleted file mode 100644 index 81b36c9e..00000000 --- a/lib/src/model/turn_server_credentials.dart +++ /dev/null @@ -1,44 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class TurnServerCredentials { - String username; - String password; - List uris; - num ttl; - - TurnServerCredentials.fromJson(Map json) - : username = json['username'], - password = json['password'], - uris = json['uris'].cast(), - ttl = json['ttl']; - - Map toJson() { - final data = {}; - data['username'] = username; - data['password'] = password; - data['uris'] = uris; - data['ttl'] = ttl; - return data; - } -} diff --git a/lib/src/model/upload_key_signatures_response.dart b/lib/src/model/upload_key_signatures_response.dart index b53e01a2..f5b46015 100644 --- a/lib/src/model/upload_key_signatures_response.dart +++ b/lib/src/model/upload_key_signatures_response.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/user_search_result.dart b/lib/src/model/user_search_result.dart deleted file mode 100644 index 8da4b82a..00000000 --- a/lib/src/model/user_search_result.dart +++ /dev/null @@ -1,42 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'profile.dart'; - -class UserSearchResult { - List results; - bool limited; - - UserSearchResult.fromJson(Map json) - : results = - (json['results'] as List).map((v) => Profile.fromJson(v)).toList(), - limited = json['limited']; - - Map toJson() { - final data = {}; - data['results'] = results.map((v) => v.toJson()).toList(); - - data['limited'] = limited; - return data; - } -} diff --git a/lib/src/model/well_known_information.dart b/lib/src/model/well_known_information.dart deleted file mode 100644 index dbeb1a84..00000000 --- a/lib/src/model/well_known_information.dart +++ /dev/null @@ -1,73 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import '../utils/try_get_map_extension.dart'; - -class WellKnownInformation { - MHomeserver mHomeserver; - MHomeserver mIdentityServer; - Map content; - - factory WellKnownInformation.fromJson(Map json) => - WellKnownInformation._fromJson( - json, - json.tryGetMap('m.homeserver'), - json.tryGetMap('m.identity_server')); - - WellKnownInformation._fromJson( - Map json, - Map mHomeserverMap, - Map mIdentityServerMap) - : content = json, - mHomeserver = mHomeserverMap != null - ? MHomeserver.fromJson(mHomeserverMap) - : null, - mIdentityServer = mIdentityServerMap != null - ? MHomeserver.fromJson(mIdentityServerMap) - : null; - - Map toJson() { - final data = content; - if (mHomeserver != null) { - data['m.homeserver'] = mHomeserver.toJson(); - } - if (mIdentityServer != null) { - data['m.identity_server'] = mIdentityServer.toJson(); - } - return data; - } -} - -class MHomeserver { - String baseUrl; - - MHomeserver.fromJson(Map json) { - baseUrl = json.tryGet('base_url'); - } - - Map toJson() { - final data = {}; - if (baseUrl != null) data['base_url'] = baseUrl; - return data; - } -} diff --git a/lib/src/model/who_is_info.dart b/lib/src/model/who_is_info.dart deleted file mode 100644 index 3d47930c..00000000 --- a/lib/src/model/who_is_info.dart +++ /dev/null @@ -1,108 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class WhoIsInfo { - String userId; - Map devices; - - WhoIsInfo.fromJson(Map json) - : userId = json['user_id'], - devices = json['devices'] != null - ? (json['devices'] as Map) - .map((k, v) => MapEntry(k, DeviceInfo.fromJson(v))) - : null; - - Map toJson() { - final data = {}; - data['user_id'] = userId; - if (devices != null) { - data['devices'] = devices.map((k, v) => MapEntry(k, v.toJson())); - } - return data; - } -} - -class DeviceInfo { - List sessions; - - DeviceInfo.fromJson(Map json) { - if (json['sessions'] != null) { - sessions = - (json['sessions'] as List).map((v) => Sessions.fromJson(v)).toList(); - } - } - - Map toJson() { - final data = {}; - if (sessions != null) { - data['sessions'] = sessions.map((v) => v.toJson()).toList(); - } - return data; - } -} - -class Sessions { - List connections; - - Sessions.fromJson(Map json) { - if (json['connections'] != null) { - connections = (json['connections'] as List) - .map((v) => Connections.fromJson(v)) - .toList(); - } - } - - Map toJson() { - final data = {}; - if (connections != null) { - data['connections'] = connections.map((v) => v.toJson()).toList(); - } - return data; - } -} - -class Connections { - String ip; - int lastSeen; - String userAgent; - - Connections.fromJson(Map json) { - ip = json['ip']; - lastSeen = json['last_seen']; - userAgent = json['user_agent']; - } - - Map toJson() { - final data = {}; - if (ip != null) { - data['ip'] = ip; - } - if (lastSeen != null) { - data['last_seen'] = lastSeen; - } - if (userAgent != null) { - data['user_agent'] = userAgent; - } - return data; - } -} diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index 298e1985..b9179146 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart index 2cf95989..be21bf01 100644 --- a/lib/src/utils/map_copy_extension.dart +++ b/lib/src/utils/map_copy_extension.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index 850a3a45..b9ab614c 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/values.dart b/lib/src/values.dart new file mode 100644 index 00000000..b7f1c0c5 --- /dev/null +++ b/lib/src/values.dart @@ -0,0 +1,20 @@ +// OpenAPI only supports real enums (modeled as enum in generated/model.dart). + +// In this file, possible values are defined manually, +// for cases where other values are allowed too. + +class PushRuleAction { + static final notify = 'notify'; + static final dontNotify = 'dont_notify'; + static final coalesce = 'coalesce'; + static final setTweak = 'set_tweak'; +} + +class TagType { + static final favourite = 'm.favourite'; + static final lowPriority = 'm.lowpriority'; + static final serverNotice = 'm.server_notice'; + static bool isValid(String tag) => tag.startsWith('m.') + ? [favourite, lowPriority, serverNotice].contains(tag) + : true; +} diff --git a/pubspec.yaml b/pubspec.yaml index 828a9cbf..ce5eddc1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.3.3 homepage: https://famedly.com environment: - sdk: ">=2.10.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: http: ^0.13.0 diff --git a/test/event_content_test.dart b/test/event_content_test.dart index a9969989..750f7581 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart index 329771d9..442aaa62 100644 --- a/test/map_copy_extension_test.dart +++ b/test/map_copy_extension_test.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index e58464a6..45eaf147 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -132,7 +133,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final wellKnownInformation = await matrixApi.getWellknown(); expect(wellKnownInformation.mHomeserver.baseUrl, - 'https://fakeserver.notexisting'); + Uri.parse('https://fakeserver.notexisting')); expect(wellKnownInformation.toJson(), { 'm.homeserver': {'base_url': 'https://fakeserver.notexisting'}, 'm.identity_server': { @@ -146,14 +147,15 @@ void main() { test('getLoginTypes', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final loginTypes = await matrixApi.getLoginFlows(); - expect(loginTypes.flows.first.type, 'm.login.password'); + expect(loginTypes.first.type, 'm.login.password'); expect(FakeMatrixApi.api['GET']['/client/r0/login']({}), - loginTypes.toJson()); + {'flows': loginTypes.map((x) => x.toJson()).toList()}); matrixApi.homeserver = null; }); test('login', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final loginResponse = await matrixApi.login( + LoginType.mLoginPassword, identifier: AuthenticationUserIdentifier(user: 'username'), ); expect(FakeMatrixApi.api['POST']['/client/r0/login']({}), @@ -175,7 +177,7 @@ void main() { test('register', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final registerResponse = - await matrixApi.register(kind: 'guest', username: 'test'); + await matrixApi.register(kind: AccountKind.guest, username: 'test'); expect(FakeMatrixApi.api['POST']['/client/r0/register?kind=guest']({}), registerResponse.toJson()); matrixApi.homeserver = null; @@ -319,7 +321,7 @@ void main() { final response = await matrixApi.unbind3pidFromAccount( 'alice@example.com', ThirdPartyIdentifierMedium.email, - 'https://example.com', + idServer: 'https://example.com', ); expect(response, IdServerUnbindResult.success); matrixApi.homeserver = matrixApi.accessToken = null; @@ -355,10 +357,10 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getTokenOwner(); - expect(response, 'alice@example.com'); + expect(response.userId, 'alice@example.com'); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('getServerCapabilities', () async { + test('getCapabilities', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getCapabilities(); @@ -392,7 +394,7 @@ void main() { timeline: StateFilter(), accountData: StateFilter(limit: 10, types: ['type1']), ), - presence: EventFilter( + presence: StateFilter( limit: 10, senders: ['@alice:example.com'], types: ['type1'], @@ -412,6 +414,7 @@ void main() { 'rooms': ['!1234'], 'ephemeral': { 'limit': 10, + 'senders': ['@alice:example.com'], 'types': ['type1'], 'not_rooms': ['!1234'], 'not_senders': ['@bob:example.com'], @@ -430,6 +433,7 @@ void main() { }, 'presence': { 'limit': 10, + 'senders': ['@alice:example.com'], 'types': ['type1'], 'not_rooms': ['!1234'], 'not_senders': ['@bob:example.com'] @@ -573,7 +577,7 @@ void main() { expect( FakeMatrixApi.api['GET'][ - '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&dir=b&to=1234&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']( + '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']( {}) as Map, timelineHistoryResponse.toJson()); @@ -584,7 +588,7 @@ void main() { matrixApi.accessToken = '1234'; final eventId = await matrixApi.setRoomStateWithKey( - '!localpart:server.abc', 'm.room.avatar', {'url': 'mxc://1234'}); + '!localpart:server.abc', 'm.room.avatar', '', {'url': 'mxc://1234'}); expect(eventId, 'YUwRidLecu:example.com'); @@ -634,7 +638,7 @@ void main() { roomVersion: '2', creationContent: {}, initialState: [], - preset: CreateRoomPreset.public_chat, + preset: CreateRoomPreset.publicChat, isDirect: false, powerLevelContentOverride: {}, ); @@ -695,12 +699,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('inviteToRoom', () async { + test('inviteUser', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.inviteToRoom( - '!localpart:example.com', '@bob:example.com'); + await matrixApi.inviteUser('!localpart:example.com', '@bob:example.com'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -711,12 +714,14 @@ void main() { final roomId = '!localpart:example.com'; final response = await matrixApi.joinRoomById( roomId, - thirdPidSignedSender: '@bob:example.com', - thirdPidSignedmxid: '@alice:example.com', - thirdPidSignedToken: '1234', - thirdPidSignedSiganture: { - 'example.org': {'ed25519:0': 'some9signature'} - }, + thirdPartySigned: ThirdPartySigned( + sender: '@bob:example.com', + mxid: '@alice:example.com', + token: '1234', + signatures: { + 'example.org': {'ed25519:0': 'some9signature'} + }, + ), ); expect(response, roomId); @@ -729,13 +734,15 @@ void main() { final roomId = '!localpart:example.com'; final response = await matrixApi.joinRoom( roomId, - servers: ['example.com', 'example.abc'], - thirdPidSignedSender: '@bob:example.com', - thirdPidSignedmxid: '@alice:example.com', - thirdPidSignedToken: '1234', - thirdPidSignedSiganture: { - 'example.org': {'ed25519:0': 'some9signature'} - }, + serverName: ['example.com', 'example.abc'], + thirdPartySigned: ThirdPartySigned( + sender: '@bob:example.com', + mxid: '@alice:example.com', + token: '1234', + signatures: { + 'example.org': {'ed25519:0': 'some9signature'} + }, + ), ); expect(response, roomId); @@ -836,7 +843,9 @@ void main() { limit: 10, since: '1234', server: 'example.com', - genericSearchTerm: 'test', + filter: PublicRoomQueryFilter( + genericSearchTerm: 'test', + ), includeAllNetworks: false, thirdPartyInstanceId: 'id', ); @@ -939,7 +948,9 @@ void main() { await matrixApi.postReceipt( '!localpart:example.com', + ReceiptType.mRead, '\$1234:example.com', + {}, ); matrixApi.homeserver = matrixApi.accessToken = null; @@ -951,7 +962,7 @@ void main() { await matrixApi.setReadMarker( '!localpart:example.com', '\$1234:example.com', - readReceiptLocationEventId: '\$1234:example.com', + mRead: '\$1234:example.com', ); matrixApi.homeserver = matrixApi.accessToken = null; @@ -984,12 +995,14 @@ void main() { }); test('upload', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final response = await matrixApi.uploadContent(Uint8List(0), 'file.jpeg'); + matrixApi.accessToken = '1234'; + final response = + await matrixApi.uploadContent(Uint8List(0), filename: 'file.jpeg'); expect(response, 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'); var throwsException = false; try { - await matrixApi.uploadContent(Uint8List(0), 'file.jpg'); - } on MatrixException catch (_) { + await matrixApi.uploadContent(Uint8List(0), filename: 'file.jpg'); + } catch (_) { throwsException = true; } expect(throwsException, true); @@ -1010,12 +1023,12 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestMaxUploadSize', () async { + test('getConfig', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getConfig(); - expect(response, 50000000); + expect(response.mUploadSize, 50000000); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1243,12 +1256,12 @@ void main() { await matrixApi.postPusher( Pusher( - '1234', - 'app.id', - 'appDisplayName', - 'deviceDisplayName', - 'en', - PusherData( + pushkey: '1234', + appId: 'app.id', + appDisplayName: 'appDisplayName', + deviceDisplayName: 'deviceDisplayName', + lang: 'en', + data: PusherData( format: 'event_id_only', url: Uri.parse('https://matrix.org')), profileTag: 'tag', kind: 'http', @@ -1321,11 +1334,11 @@ void main() { before: '1', after: '2', conditions: [ - PushConditions( - 'event_match', + PushCondition( + kind: 'event_match', key: 'key', pattern: 'pattern', - isOperator: '+', + is$: '+', ) ], pattern: 'pattern', @@ -1374,7 +1387,7 @@ void main() { 'global', PushRuleKind.content, 'nocake', - [PushRuleAction.dont_notify], + [PushRuleAction.dontNotify], ); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1383,7 +1396,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.search({}); + await matrixApi.search(Categories()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1509,7 +1522,7 @@ void main() { limit: 10, filter: '{}'); expect( FakeMatrixApi.api['GET'] - ['/client/r0/rooms/1234/context/1234?filter=%7B%7D&limit=10']({}), + ['/client/r0/rooms/1234/context/1234?limit=10&filter=%7B%7D']({}), response.toJson(), ); @@ -1522,8 +1535,8 @@ void main() { await matrixApi.reportContent( '1234', '1234', - 'test', - -100, + reason: 'test', + score: -100, ); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1606,7 +1619,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestOpenIdToken('1234'); + final response = await matrixApi.requestOpenIdToken('1234', {}); expect( FakeMatrixApi.api['POST'] ['/client/r0/user/1234/openid/request_token']({}), @@ -1623,39 +1636,39 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('createRoomKeysBackup', () async { + test('postRoomKeysVersion', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final algorithm = RoomKeysAlgorithmType.v1Curve25519AesSha2; + final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; final authData = { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', 'signatures': {}, }; - final ret = await matrixApi.createRoomKeysBackup(algorithm, authData); + final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); expect( FakeMatrixApi.api['POST'] ['/client/unstable/room_keys/version']({})['version'], ret); }); - test('getRoomKeysBackup', () async { + test('getRoomKeysVersionCurrent', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final ret = await matrixApi.getRoomKeysBackup(); + final ret = await matrixApi.getRoomKeysVersionCurrent(); expect(FakeMatrixApi.api['GET']['/client/unstable/room_keys/version']({}), ret.toJson()); }); - test('updateRoomKeysBackup', () async { + test('putRoomKeysVersion', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final algorithm = RoomKeysAlgorithmType.v1Curve25519AesSha2; + final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; final authData = { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', 'signatures': {}, }; - await matrixApi.updateRoomKeysBackup('5', algorithm, authData); + await matrixApi.putRoomKeysVersion('5', algorithm, authData); }); test('deleteRoomKeysBackup', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); @@ -1663,13 +1676,13 @@ void main() { await matrixApi.deleteRoomKeysBackup('5'); }); - test('storeRoomKeysSingleKey', () async { + test('postRoomKeysKeyRoomIdSessionId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final session = RoomKeysSingleKey.fromJson({ + final session = KeyBackupData.fromJson({ 'first_message_index': 0, 'forwarded_count': 0, 'is_verified': true, @@ -1680,7 +1693,7 @@ void main() { 'mac': 'QzKV/fgAs4U', }, }); - final ret = await matrixApi.storeRoomKeysSingleKey( + final ret = await matrixApi.postRoomKeysKeyRoomIdSessionId( roomId, sessionId, '5', session); expect( FakeMatrixApi.api['PUT'][ @@ -1712,13 +1725,13 @@ void main() { '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); - test('storeRoomKeysRoom', () async { + test('postRoomKeysKeyRoomId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final session = RoomKeysRoom.fromJson({ + final session = RoomKeyBackup.fromJson({ 'sessions': { sessionId: { 'first_message_index': 0, @@ -1733,7 +1746,7 @@ void main() { }, }, }); - final ret = await matrixApi.storeRoomKeysRoom(roomId, '5', session); + final ret = await matrixApi.postRoomKeysKeyRoomId(roomId, '5', session); expect( FakeMatrixApi.api['PUT'][ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), @@ -1761,7 +1774,7 @@ void main() { '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); - test('storeRoomKeys', () async { + test('postRoomKeysKey', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1786,7 +1799,7 @@ void main() { }, }, }); - final ret = await matrixApi.storeRoomKeys('5', session); + final ret = await matrixApi.postRoomKeysKey('5', session); expect( FakeMatrixApi.api['PUT'] ['/client/unstable/room_keys/keys?version=5']({}), diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index d38a1e68..dca18807 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -1,3 +1,4 @@ +// @dart=2.9 /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH From 1b84de0b447d806d896f0a95033f1e58f9446679 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Thu, 24 Jun 2021 17:37:41 +0200 Subject: [PATCH 063/174] refactor: remove timeouts in matrix_api_lite --- lib/src/matrix_api.dart | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 2e2bb31c..cf471414 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -70,17 +70,10 @@ class MatrixApi extends Api { super.unexpectedResponse(response, responseBody); } - /// Matrix synchronisation is done with https long polling. This needs a - /// timeout which is usually 30 seconds. - int syncTimeoutSec; - - int _timeoutFactor = 1; - MatrixApi({ Uri homeserver, String accessToken, http.Client httpClient, - this.syncTimeoutSec = 30, }) : super( httpClient: httpClient, baseUri: homeserver, @@ -88,7 +81,7 @@ class MatrixApi extends Api { /// Used for all Matrix json requests using the [c2s API](https://matrix.org/docs/spec/client_server/r0.6.0.html). /// - /// Throws: TimeoutException, FormatException, MatrixException + /// Throws: FormatException, MatrixException /// /// You must first set [this.homeserver] and for some endpoints also /// [this.accessToken] before you can use this! For example to send a @@ -108,14 +101,12 @@ class MatrixApi extends Api { RequestType type, String action, { dynamic data = '', - int timeout, String contentType = 'application/json', Map query, }) async { if (homeserver == null) { throw ('No homeserver specified.'); } - timeout ??= (_timeoutFactor * syncTimeoutSec) + 5; dynamic json; (!(data is String)) ? json = jsonEncode(data) : json = data; if (data is List || action.startsWith('/media/r0/upload')) json = data; @@ -136,26 +127,16 @@ class MatrixApi extends Api { try { switch (type) { case RequestType.GET: - resp = await httpClient.get(url, headers: headers).timeout( - Duration(seconds: timeout), - ); + resp = await httpClient.get(url, headers: headers); break; case RequestType.POST: - resp = - await httpClient.post(url, body: json, headers: headers).timeout( - Duration(seconds: timeout), - ); + resp = await httpClient.post(url, body: json, headers: headers); break; case RequestType.PUT: - resp = - await httpClient.put(url, body: json, headers: headers).timeout( - Duration(seconds: timeout), - ); + resp = await httpClient.put(url, body: json, headers: headers); break; case RequestType.DELETE: - resp = await httpClient.delete(url, headers: headers).timeout( - Duration(seconds: timeout), - ); + resp = await httpClient.delete(url, headers: headers); break; } var respBody = resp.body; @@ -173,11 +154,6 @@ class MatrixApi extends Api { } jsonResp = jsonDecode(jsonString) as Map; // May throw FormatException - - _timeoutFactor = 1; - } on TimeoutException catch (e, s) { - _timeoutFactor *= 2; - throw MatrixConnectionException(e, s); } catch (e, s) { throw MatrixConnectionException(e, s); } From d9c1fdb78afcc5ba096ff3d76cfc0f90ee48bd47 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Thu, 1 Jul 2021 15:11:39 +0200 Subject: [PATCH 064/174] refactor: migrate to null safety --- lib/fake_matrix_api.dart | 8 +- lib/matrix_api_lite.dart | 2 +- lib/src/matrix_api.dart | 90 +++++------ lib/src/model/algorithm_types.dart | 2 +- lib/src/model/auth/authentication_data.dart | 6 +- .../model/auth/authentication_identifier.dart | 4 +- .../model/auth/authentication_password.dart | 6 +- .../auth/authentication_phone_identifier.dart | 4 +- .../model/auth/authentication_recaptcha.dart | 4 +- ...authentication_third_party_identifier.dart | 4 +- .../auth/authentication_three_pid_creds.dart | 10 +- lib/src/model/auth/authentication_token.dart | 6 +- lib/src/model/auth/authentication_types.dart | 2 +- .../auth/authentication_user_identifier.dart | 4 +- lib/src/model/basic_event.dart | 6 +- lib/src/model/basic_event_with_sender.dart | 2 +- lib/src/model/basic_room_event.dart | 8 +- lib/src/model/event_types.dart | 2 +- .../events/forwarded_room_key_content.dart | 2 +- .../model/events/olm_plaintext_payload.dart | 14 +- .../model/events/room_encrypted_content.dart | 12 +- .../model/events/room_encryption_content.dart | 10 +- lib/src/model/events/room_key_content.dart | 2 +- .../events/room_key_request_content.dart | 6 +- .../secret_storage_default_key_content.dart | 2 +- .../events/secret_storage_key_content.dart | 20 +-- lib/src/model/events/tombstone_content.dart | 2 +- lib/src/model/events_sync_update.dart | 10 +- .../model/matrix_connection_exception.dart | 2 +- lib/src/model/matrix_event.dart | 16 +- lib/src/model/matrix_exception.dart | 16 +- lib/src/model/matrix_keys.dart | 24 +-- lib/src/model/message_types.dart | 2 +- lib/src/model/presence.dart | 2 +- lib/src/model/presence_content.dart | 8 +- lib/src/model/request_token_response.dart | 4 +- lib/src/model/room_creation_types.dart | 2 +- lib/src/model/room_keys_keys.dart | 12 +- lib/src/model/room_summary.dart | 8 +- lib/src/model/room_types.dart | 2 +- lib/src/model/stripped_state_event.dart | 4 +- lib/src/model/supported_protocol.dart | 4 +- lib/src/model/sync_update.dart | 94 ++++++------ lib/src/model/third_party_location.dart | 2 +- lib/src/model/third_party_user.dart | 2 +- .../model/upload_key_signatures_response.dart | 6 +- lib/src/utils/logs.dart | 18 +-- lib/src/utils/map_copy_extension.dart | 2 +- lib/src/utils/try_get_map_extension.dart | 2 +- test/event_content_test.dart | 30 ++-- test/map_copy_extension_test.dart | 2 +- test/matrix_api_test.dart | 140 +++++++++--------- test/try_get_map_extension_test.dart | 2 +- 53 files changed, 328 insertions(+), 328 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index f2b3f6de..b1e80ed9 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -83,9 +83,9 @@ class FakeMatrixApi extends MockClient { if (!calledEndpoints.containsKey(action)) { calledEndpoints[action] = []; } - calledEndpoints[action].add(data); - if (api.containsKey(method) && api[method].containsKey(action)) { - res = api[method][action](data); + calledEndpoints[action]!.add(data); + if (api.containsKey(method) && api[method]!.containsKey(action)) { + res = api[method]![action](data); if (res is Map && res.containsKey('errcode')) { statusCode = 405; } diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 6695187e..3a638c49 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index cf471414..31dc95be 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -54,13 +54,13 @@ String describeEnum(Object enumEntry) { class MatrixApi extends Api { /// The homeserver this client is communicating with. - Uri get homeserver => baseUri; - set homeserver(Uri uri) => baseUri = uri; + Uri? get homeserver => baseUri; + set homeserver(Uri? uri) => baseUri = uri; /// This is the access token for the matrix client. When it is undefined, then /// the user needs to sign in first. - String get accessToken => bearerToken; - set accessToken(String token) => bearerToken = token; + String? get accessToken => bearerToken; + set accessToken(String? token) => bearerToken = token; @override Null unexpectedResponse(http.BaseResponse response, Uint8List responseBody) { @@ -71,9 +71,9 @@ class MatrixApi extends Api { } MatrixApi({ - Uri homeserver, - String accessToken, - http.Client httpClient, + Uri? homeserver, + String? accessToken, + http.Client? httpClient, }) : super( httpClient: httpClient, baseUri: homeserver, @@ -102,7 +102,7 @@ class MatrixApi extends Api { String action, { dynamic data = '', String contentType = 'application/json', - Map query, + Map? query, }) async { if (homeserver == null) { throw ('No homeserver specified.'); @@ -111,7 +111,7 @@ class MatrixApi extends Api { (!(data is String)) ? json = jsonEncode(data) : json = data; if (data is List || action.startsWith('/media/r0/upload')) json = data; - final url = homeserver + final url = homeserver! .resolveUri(Uri(path: '_matrix$action', queryParameters: query)); final headers = {}; @@ -122,8 +122,8 @@ class MatrixApi extends Api { headers['Authorization'] = 'Bearer $accessToken'; } - http.Response resp; - var jsonResp = {}; + late http.Response resp; + Map? jsonResp = {}; try { switch (type) { case RequestType.GET: @@ -153,7 +153,7 @@ class MatrixApi extends Api { jsonString = '\{"chunk":$jsonString\}'; } jsonResp = jsonDecode(jsonString) - as Map; // May throw FormatException + as Map?; // May throw FormatException } catch (e, s) { throw MatrixConnectionException(e, s); } @@ -161,7 +161,7 @@ class MatrixApi extends Api { throw MatrixException(resp); } - return jsonResp; + return jsonResp!; } /// The homeserver must check that the given email address is not already associated @@ -173,9 +173,9 @@ class MatrixApi extends Api { String email, String clientSecret, int sendAttempt, { - String nextLink, - String idServer, - String idAccessToken, + String? nextLink, + String? idServer, + String? idAccessToken, }) async { final response = await request( RequestType.POST, '/client/r0/register/email/requestToken', @@ -199,9 +199,9 @@ class MatrixApi extends Api { String phoneNumber, String clientSecret, int sendAttempt, { - String nextLink, - String idServer, - String idAccessToken, + String? nextLink, + String? idServer, + String? idAccessToken, }) async { final response = await request( RequestType.POST, '/client/r0/register/msisdn/requestToken', @@ -225,9 +225,9 @@ class MatrixApi extends Api { String email, String clientSecret, int sendAttempt, { - String nextLink, - String idServer, - String idAccessToken, + String? nextLink, + String? idServer, + String? idAccessToken, }) async { final response = await request( RequestType.POST, '/client/r0/account/password/email/requestToken', @@ -251,9 +251,9 @@ class MatrixApi extends Api { String phoneNumber, String clientSecret, int sendAttempt, { - String nextLink, - String idServer, - String idAccessToken, + String? nextLink, + String? idServer, + String? idAccessToken, }) async { final response = await request( RequestType.POST, '/client/r0/account/password/msisdn/requestToken', @@ -275,9 +275,9 @@ class MatrixApi extends Api { String email, String clientSecret, int sendAttempt, { - String nextLink, - String idServer, - String idAccessToken, + String? nextLink, + String? idServer, + String? idAccessToken, }) async { final response = await request( RequestType.POST, '/client/r0/account/3pid/email/requestToken', @@ -299,9 +299,9 @@ class MatrixApi extends Api { String phoneNumber, String clientSecret, int sendAttempt, { - String nextLink, - String idServer, - String idAccessToken, + String? nextLink, + String? idServer, + String? idAccessToken, }) async { final response = await request( RequestType.POST, '/client/r0/account/3pid/msisdn/requestToken', @@ -323,7 +323,7 @@ class MatrixApi extends Api { /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey Future> requestStateContent( String roomId, String eventType, - [String stateKey]) async { + [String? stateKey]) async { var url = '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/'; if (stateKey != null) { @@ -364,9 +364,9 @@ class MatrixApi extends Api { /// Publishes end-to-end encryption keys for the device. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query Future> uploadKeys( - {MatrixDeviceKeys deviceKeys, - Map oneTimeKeys, - Map fallbackKeys}) async { + {MatrixDeviceKeys? deviceKeys, + Map? oneTimeKeys, + Map? fallbackKeys}) async { final response = await request( RequestType.POST, '/client/r0/keys/upload', @@ -385,10 +385,10 @@ class MatrixApi extends Api { /// Uploads your own cross-signing keys. /// https://github.com/matrix-org/matrix-doc/pull/2536 Future uploadDeviceSigningKeys({ - MatrixCrossSigningKey masterKey, - MatrixCrossSigningKey selfSigningKey, - MatrixCrossSigningKey userSigningKey, - AuthenticationData auth, + MatrixCrossSigningKey? masterKey, + MatrixCrossSigningKey? selfSigningKey, + MatrixCrossSigningKey? userSigningKey, + AuthenticationData? auth, }) async { await request( RequestType.POST, @@ -410,7 +410,7 @@ class MatrixApi extends Api { for (final key in keys) { if (key.identifier == null || key.signatures == null || - key.signatures.isEmpty) { + key.signatures!.isEmpty) { continue; } if (!payload.containsKey(key.userId)) { @@ -437,7 +437,7 @@ class MatrixApi extends Api { /// for this user ID. The behaviour of this endpoint varies depending on the /// values in the JSON body. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-pushers-set - Future postPusher(Pusher pusher, {bool append}) async { + Future postPusher(Pusher pusher, {bool? append}) async { final data = pusher.toJson(); if (append != null) { data['append'] = append; @@ -454,9 +454,9 @@ class MatrixApi extends Api { /// caller. This will block until an event is received, or until the timeout is reached. /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-events Future getEvents({ - String from, - int timeout, - String roomId, + String? from, + int? timeout, + String? roomId, }) async { final response = await request(RequestType.GET, '/client/r0/events', query: { diff --git a/lib/src/model/algorithm_types.dart b/lib/src/model/algorithm_types.dart index 207ccd96..59144cf3 100644 --- a/lib/src/model/algorithm_types.dart +++ b/lib/src/model/algorithm_types.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 68441c43..85d39767 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -24,9 +24,9 @@ class AuthenticationData { String type; - String session; + String?/*?*//*?*/ session; - AuthenticationData({this.type, this.session}); + AuthenticationData({required this.type, this.session}); AuthenticationData.fromJson(Map json) : type = json['type'], diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index 14047d42..572932a0 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -30,7 +30,7 @@ import 'authentication_third_party_identifier.dart'; class AuthenticationIdentifier { String type; - AuthenticationIdentifier({this.type}); + AuthenticationIdentifier({required this.type}); AuthenticationIdentifier.fromJson(Map json) : type = json['type']; diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index 99d2c26d..b1066c2f 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,7 +29,7 @@ import 'authentication_identifier.dart'; import 'authentication_types.dart'; class AuthenticationPassword extends AuthenticationData { - String user; + String? user; String password; /// You may want to cast this as [AuthenticationUserIdentifier] or other @@ -37,7 +37,7 @@ class AuthenticationPassword extends AuthenticationData { AuthenticationIdentifier identifier; AuthenticationPassword( - {String session, this.password, this.user, this.identifier}) + {String? session, required this.password, this.user, required this.identifier}) : super( type: AuthenticationTypes.password, session: session, diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index 7ae42bf6..5e3c7779 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,7 +29,7 @@ class AuthenticationPhoneIdentifier extends AuthenticationIdentifier { String country; String phone; - AuthenticationPhoneIdentifier({this.country, this.phone}) + AuthenticationPhoneIdentifier({required this.country, required this.phone}) : super(type: AuthenticationIdentifierTypes.phone); AuthenticationPhoneIdentifier.fromJson(Map json) diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index 256f1931..fdedf5b3 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -28,7 +28,7 @@ import 'authentication_types.dart'; class AuthenticationRecaptcha extends AuthenticationData { String response; - AuthenticationRecaptcha({String session, this.response}) + AuthenticationRecaptcha({required String session, required this.response}) : super( type: AuthenticationTypes.recaptcha, session: session, diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index 3cb44fe3..94b55e28 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,7 +29,7 @@ class AuthenticationThirdPartyIdentifier extends AuthenticationIdentifier { String medium; String address; - AuthenticationThirdPartyIdentifier({this.medium, this.address}) + AuthenticationThirdPartyIdentifier({required this.medium, required this.address}) : super(type: AuthenticationIdentifierTypes.thirdParty); AuthenticationThirdPartyIdentifier.fromJson(Map json) diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index faaef644..2961ac56 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,9 +29,9 @@ import 'authentication_data.dart'; /// Or phone number based identity: /// https://matrix.org/docs/spec/client_server/r0.6.1#phone-number-msisdn-based-identity-homeserver class AuthenticationThreePidCreds extends AuthenticationData { - List threepidCreds; + late List threepidCreds; - AuthenticationThreePidCreds({String session, String type, this.threepidCreds}) + AuthenticationThreePidCreds({String? session, required String type, required this.threepidCreds}) : super( type: type, session: session, @@ -65,13 +65,13 @@ class AuthenticationThreePidCreds extends AuthenticationData { } class ThreepidCreds { - String sid; + String/*!*/ sid; String clientSecret; String idServer; String idAccessToken; ThreepidCreds( - {this.sid, this.clientSecret, this.idServer, this.idAccessToken}); + {required this.sid, required this.clientSecret, required this.idServer, required this.idAccessToken}); ThreepidCreds.fromJson(Map json) : sid = json['sid'], diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index 32d42dd3..63233f4f 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -27,9 +27,9 @@ import 'authentication_types.dart'; class AuthenticationToken extends AuthenticationData { String token; - String txnId; + String? txnId; - AuthenticationToken({String session, this.token, this.txnId}) + AuthenticationToken({String? session, required this.token, this.txnId}) : super( type: AuthenticationTypes.token, session: session, diff --git a/lib/src/model/auth/authentication_types.dart b/lib/src/model/auth/authentication_types.dart index 2a667ee6..00f13793 100644 --- a/lib/src/model/auth/authentication_types.dart +++ b/lib/src/model/auth/authentication_types.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index 0e1a98dc..974f7fee 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -28,7 +28,7 @@ import 'authentication_types.dart'; class AuthenticationUserIdentifier extends AuthenticationIdentifier { String user; - AuthenticationUserIdentifier({this.user}) + AuthenticationUserIdentifier({required this.user}) : super(type: AuthenticationIdentifierTypes.userId); AuthenticationUserIdentifier.fromJson(Map json) diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 0be5741f..666fa516 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,8 +29,8 @@ class BasicEvent { Map content; BasicEvent({ - this.type, - this.content, + required this.type, + required this.content, }); BasicEvent.fromJson(Map json) diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index 78a7979b..4b6114a7 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index 4e9a0cf5..66eff7d8 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -25,12 +25,12 @@ import 'basic_event.dart'; class BasicRoomEvent extends BasicEvent { - String roomId; + String? roomId; BasicRoomEvent({ this.roomId, - Map content, - String type, + required Map content, + required String type, }) : super( content: content, type: type, diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index 50840346..19623f5d 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/forwarded_room_key_content.dart b/lib/src/model/events/forwarded_room_key_content.dart index a9b238fc..fb8ca523 100644 --- a/lib/src/model/events/forwarded_room_key_content.dart +++ b/lib/src/model/events/forwarded_room_key_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/olm_plaintext_payload.dart b/lib/src/model/events/olm_plaintext_payload.dart index 55f377f3..69a6d0e8 100644 --- a/lib/src/model/events/olm_plaintext_payload.dart +++ b/lib/src/model/events/olm_plaintext_payload.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -25,12 +25,12 @@ import '../../utils/try_get_map_extension.dart'; class OlmPlaintextPayload { - String type; - Map content; - String sender; - String recipient; - Map recipientKeys; - Map keys; + String? type; + Map? content; + String? sender; + String? recipient; + Map? recipientKeys; + Map? keys; OlmPlaintextPayload({ this.type, diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 0b132541..3608621a 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -35,10 +35,10 @@ extension RoomEncryptedContentBasicEventExtension on BasicEvent { class RoomEncryptedContent { String algorithm; String senderKey; - String deviceId; - String sessionId; - String ciphertextMegolm; - Map ciphertextOlm; + String? deviceId; + String? sessionId; + String? ciphertextMegolm; + Map? ciphertextOlm; RoomEncryptedContent.fromJson(Map json) : algorithm = json.tryGet('algorithm', ''), @@ -68,7 +68,7 @@ class RoomEncryptedContent { data['ciphertext'] = ciphertextMegolm; } if (ciphertextOlm != null) { - data['ciphertext'] = ciphertextOlm.map((k, v) => MapEntry(k, v.toJson())); + data['ciphertext'] = ciphertextOlm!.map((k, v) => MapEntry(k, v.toJson())); if (ciphertextMegolm != null) { Logs().wtf( 'ciphertextOlm and ciphertextMegolm are both set, which should never happen!'); diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/src/model/events/room_encryption_content.dart index 33afcda2..c639ba67 100644 --- a/lib/src/model/events/room_encryption_content.dart +++ b/lib/src/model/events/room_encryption_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -32,13 +32,13 @@ extension RoomEncryptionContentBasicEventExtension on BasicEvent { class RoomEncryptionContent { String algorithm; - int rotationPeriodMs; - int rotationPeriodMsgs; + int? rotationPeriodMs; + int? rotationPeriodMsgs; RoomEncryptionContent.fromJson(Map json) : algorithm = json.tryGet('algorithm', ''), - rotationPeriodMs = json.tryGet('rotation_period_ms'), - rotationPeriodMsgs = json.tryGet('rotation_period_msgs'); + rotationPeriodMs = json.tryGet('rotation_period_ms'), + rotationPeriodMsgs = json.tryGet('rotation_period_msgs'); Map toJson() { final data = {}; diff --git a/lib/src/model/events/room_key_content.dart b/lib/src/model/events/room_key_content.dart index 8686db21..4149ffad 100644 --- a/lib/src/model/events/room_key_content.dart +++ b/lib/src/model/events/room_key_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index ca690e52..1a7e6871 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -31,7 +31,7 @@ extension RoomKeyRequestContentBasicEventExtension on BasicEvent { } class RoomKeyRequestContent { - RequestedKeyInfo body; + RequestedKeyInfo? body; String action; String requestingDeviceId; String requestId; @@ -45,7 +45,7 @@ class RoomKeyRequestContent { Map toJson() { final data = {}; - if (body != null) data['body'] = body.toJson(); + if (body != null) data['body'] = body!.toJson(); data['action'] = action; data['requesting_device_id'] = requestingDeviceId; data['request_id'] = requestId; diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/src/model/events/secret_storage_default_key_content.dart index a8630813..389795d0 100644 --- a/lib/src/model/events/secret_storage_default_key_content.dart +++ b/lib/src/model/events/secret_storage_default_key_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index de7e3618..8e10a182 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -31,10 +31,10 @@ extension SecretStorageKeyContentBasicEventExtension on BasicEvent { } class SecretStorageKeyContent { - PassphraseInfo passphrase; - String iv; - String mac; - String algorithm; + PassphraseInfo? passphrase; + String? iv; + String? mac; + String? algorithm; SecretStorageKeyContent(); @@ -42,13 +42,13 @@ class SecretStorageKeyContent { : passphrase = json['passphrase'] is Map ? PassphraseInfo.fromJson(json['passphrase']) : null, - iv = json.tryGet('iv'), - mac = json.tryGet('mac'), - algorithm = json.tryGet('algorithm'); + iv = json.tryGet('iv'), + mac = json.tryGet('mac'), + algorithm = json.tryGet('algorithm'); Map toJson() { final data = {}; - if (passphrase != null) data['passphrase'] = passphrase.toJson(); + if (passphrase != null) data['passphrase'] = passphrase!.toJson(); if (iv != null) data['iv'] = iv; if (mac != null) data['mac'] = mac; if (algorithm != null) data['algorithm'] = algorithm; @@ -60,7 +60,7 @@ class PassphraseInfo { String algorithm; String salt; int iterations; - int bits; + int? bits; PassphraseInfo(); diff --git a/lib/src/model/events/tombstone_content.dart b/lib/src/model/events/tombstone_content.dart index 9e939223..93a8221f 100644 --- a/lib/src/model/events/tombstone_content.dart +++ b/lib/src/model/events/tombstone_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart index 1a215473..a93ee5b3 100644 --- a/lib/src/model/events_sync_update.dart +++ b/lib/src/model/events_sync_update.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -25,9 +25,9 @@ import 'matrix_event.dart'; class EventsSyncUpdate { - String start; - String end; - List chunk; + String? start; + String? end; + List? chunk; EventsSyncUpdate.fromJson(Map json) : start = json['start'], @@ -47,7 +47,7 @@ class EventsSyncUpdate { data['end'] = end; } if (chunk != null) { - data['chunk'] = chunk.map((i) => i.toJson()).toList(); + data['chunk'] = chunk!.map((i) => i.toJson()).toList(); } return data; } diff --git a/lib/src/model/matrix_connection_exception.dart b/lib/src/model/matrix_connection_exception.dart index d9cfb113..96d12af9 100644 --- a/lib/src/model/matrix_connection_exception.dart +++ b/lib/src/model/matrix_connection_exception.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index a2aba791..b54856db 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -27,11 +27,11 @@ import '../utils/map_copy_extension.dart'; class MatrixEvent extends StrippedStateEvent { String eventId; - String roomId; - DateTime originServerTs; - Map unsigned; - Map prevContent; - String redacts; + String? roomId; + late DateTime originServerTs; + Map? unsigned; + Map? prevContent; + String? redacts; MatrixEvent(); @@ -40,8 +40,8 @@ class MatrixEvent extends StrippedStateEvent { roomId = json['room_id'], originServerTs = DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']), - unsigned = (json['unsigned'] as Map)?.copy(), - prevContent = (json['prev_content'] as Map)?.copy(), + unsigned = (json['unsigned'] as Map?)?.copy(), + prevContent = (json['prev_content'] as Map?)?.copy(), redacts = json['redacts'], super.fromJson(json); diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 4365d4ef..f2a03e24 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -60,9 +60,9 @@ class MatrixException implements Exception { : 'Unknown error'); /// The frozen request which triggered this Error - http.Response response; + http.Response? response; - MatrixException(this.response) : raw = json.decode(response.body); + MatrixException(Response this.response) : raw = json.decode(response.body); MatrixException.fromJson(Map content) : raw = content; @override @@ -73,21 +73,21 @@ class MatrixException implements Exception { (e) => e.toString() == 'MatrixError.${(raw["errcode"] ?? "")}', orElse: () => MatrixError.M_UNKNOWN); - int get retryAfterMs => raw['retry_after_ms']; + int? get retryAfterMs => raw['retry_after_ms']; /// This is a session identifier that the client must pass back to the homeserver, if one is provided, /// in subsequent attempts to authenticate in the same API call. - String get session => raw['session']; + String? get session => raw['session']; /// Returns true if the server requires additional authentication. bool get requireAdditionalAuthentication => response != null - ? response.statusCode == 401 + ? response!.statusCode == 401 : authenticationFlows != null; /// For each endpoint, a server offers one or more 'flows' that the client can use /// to authenticate itself. Each flow comprises a series of stages. If this request /// doesn't need additional authentication, then this is null. - List get authenticationFlows { + List?/*?*/ get authenticationFlows { if (!raw.containsKey('flows') || !(raw['flows'] is List)) return null; return (raw['flows'] as List) .map((flow) => flow['stages']) @@ -99,7 +99,7 @@ class MatrixException implements Exception { /// This section contains any information that the client will need to know in order to use a given type /// of authentication. For each authentication type presented, that type may be present as a key in this /// dictionary. For example, the public part of an OAuth client ID could be given here. - Map get authenticationParams => raw['params']; + Map? get authenticationParams => raw['params']; /// Returns the list of already completed authentication flows from previous requests. List get completedAuthenticationFlows => diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index 9f179480..2ad89ed1 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -26,16 +26,16 @@ import '../utils/map_copy_extension.dart'; class MatrixSignableKey { String userId; - String identifier; + String? identifier; Map keys; - Map> signatures; - Map unsigned; + Map>? signatures; + Map? unsigned; MatrixSignableKey(this.userId, this.identifier, this.keys, this.signatures, {this.unsigned}); // This object is used for signing so we need the raw json too - Map _json; + Map? _json; MatrixSignableKey.fromJson(Map json) : _json = json, @@ -46,7 +46,7 @@ class MatrixSignableKey { ? Map>.from((json['signatures'] as Map) .map((k, v) => MapEntry(k, Map.from(v)))) : null, - unsigned = (json['unsigned'] as Map)?.copy(); + unsigned = (json['unsigned'] as Map?)?.copy(); Map toJson() { final data = _json ?? {}; @@ -65,14 +65,14 @@ class MatrixSignableKey { class MatrixCrossSigningKey extends MatrixSignableKey { List usage; - String get publicKey => identifier; + String? get publicKey => identifier; MatrixCrossSigningKey( String userId, this.usage, Map keys, Map> signatures, { - Map unsigned, + Map? unsigned, }) : super(userId, keys?.values?.first, keys, signatures, unsigned: unsigned); @override @@ -91,10 +91,10 @@ class MatrixCrossSigningKey extends MatrixSignableKey { } class MatrixDeviceKeys extends MatrixSignableKey { - String get deviceId => identifier; + String get deviceId => identifier!; List algorithms; - String get deviceDisplayName => - unsigned != null ? unsigned['device_display_name'] : null; + String? get deviceDisplayName => + unsigned != null ? unsigned!['device_display_name'] : null; MatrixDeviceKeys( String userId, @@ -102,7 +102,7 @@ class MatrixDeviceKeys extends MatrixSignableKey { this.algorithms, Map keys, Map> signatures, { - Map unsigned, + Map? unsigned, }) : super(userId, deviceId, keys, signatures, unsigned: unsigned); @override diff --git a/lib/src/model/message_types.dart b/lib/src/model/message_types.dart index 0a9b240c..e6cbc443 100644 --- a/lib/src/model/message_types.dart +++ b/lib/src/model/message_types.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index c5091d5c..4874ea54 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index b7bab947..0df3f0c2 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -26,9 +26,9 @@ import '../generated/model.dart'; class PresenceContent { PresenceType presence; - int lastActiveAgo; - String statusMsg; - bool currentlyActive; + int? lastActiveAgo; + String? statusMsg; + bool? currentlyActive; PresenceContent.fromJson(Map json) : presence = PresenceType.values.firstWhere( diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart index 00dd1e68..46f24e5c 100644 --- a/lib/src/model/request_token_response.dart +++ b/lib/src/model/request_token_response.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -24,7 +24,7 @@ class RequestTokenResponse { String sid; - String submitUrl; + String? submitUrl; RequestTokenResponse.fromJson(Map json) : sid = json['sid'], diff --git a/lib/src/model/room_creation_types.dart b/lib/src/model/room_creation_types.dart index fb41cb6c..be7b75d9 100644 --- a/lib/src/model/room_creation_types.dart +++ b/lib/src/model/room_creation_types.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + abstract class RoomCreationTypes { static const String mSpace = 'm.space'; } diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart index 0e8122ba..b285c454 100644 --- a/lib/src/model/room_keys_keys.dart +++ b/lib/src/model/room_keys_keys.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,10 +29,10 @@ class RoomKeysSingleKey { Map sessionData; RoomKeysSingleKey( - {this.firstMessageIndex, - this.forwardedCount, - this.isVerified, - this.sessionData}); + {required this.firstMessageIndex, + required this.forwardedCount, + required this.isVerified, + required this.sessionData}); RoomKeysSingleKey.fromJson(Map json) : firstMessageIndex = json['first_message_index'], @@ -53,7 +53,7 @@ class RoomKeysSingleKey { class RoomKeysRoom { Map sessions; - RoomKeysRoom({this.sessions}) { + RoomKeysRoom({required this.sessions}) { sessions ??= {}; } diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index 24a9d444..74dded00 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -23,9 +23,9 @@ */ class RoomSummary { - List mHeroes; - int mJoinedMemberCount; - int mInvitedMemberCount; + List? mHeroes; + int? mJoinedMemberCount; + int? mInvitedMemberCount; RoomSummary.fromJson(Map json) : mHeroes = json['m.heroes'] != null ? List.from(json['m.heroes']) diff --git a/lib/src/model/room_types.dart b/lib/src/model/room_types.dart index 6a84114f..7dbcf0f5 100644 --- a/lib/src/model/room_types.dart +++ b/lib/src/model/room_types.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index cf222869..cb8f914d 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -25,7 +25,7 @@ import 'basic_event_with_sender.dart'; class StrippedStateEvent extends BasicEventWithSender { - String stateKey; + String? stateKey; StrippedStateEvent(); StrippedStateEvent.fromJson(Map json) diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart index 5a168f06..32cba75c 100644 --- a/lib/src/model/supported_protocol.dart +++ b/lib/src/model/supported_protocol.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -72,7 +72,7 @@ class ProtocolFieldType { class ProtocolInstance { String networkId; String desc; - String icon; + String? icon; dynamic fields; ProtocolInstance.fromJson(Map json) { diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index c4d158a5..5b93d1ef 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -32,13 +32,13 @@ import 'stripped_state_event.dart'; class SyncUpdate { String nextBatch; - RoomsUpdate rooms; - List presence; - List accountData; - List toDevice; - DeviceListsUpdate deviceLists; - Map deviceOneTimeKeysCount; - List deviceUnusedFallbackKeyTypes; + RoomsUpdate? rooms; + List? presence; + List? accountData; + List? toDevice; + DeviceListsUpdate? deviceLists; + Map? deviceOneTimeKeysCount; + List? deviceUnusedFallbackKeyTypes; SyncUpdate(); @@ -83,25 +83,25 @@ class SyncUpdate { final data = {}; data['next_batch'] = nextBatch; if (rooms != null) { - data['rooms'] = rooms.toJson(); + data['rooms'] = rooms!.toJson(); } if (presence != null) { data['presence'] = { - 'events': presence.map((i) => i.toJson()).toList(), + 'events': presence!.map((i) => i.toJson()).toList(), }; } if (accountData != null) { data['account_data'] = { - 'events': accountData.map((i) => i.toJson()).toList(), + 'events': accountData!.map((i) => i.toJson()).toList(), }; } if (toDevice != null) { data['to_device'] = { - 'events': toDevice.map((i) => i.toJson()).toList(), + 'events': toDevice!.map((i) => i.toJson()).toList(), }; } if (deviceLists != null) { - data['device_lists'] = deviceLists.toJson(); + data['device_lists'] = deviceLists!.toJson(); } if (deviceOneTimeKeysCount != null) { data['device_one_time_keys_count'] = deviceOneTimeKeysCount; @@ -116,9 +116,9 @@ class SyncUpdate { } class RoomsUpdate { - Map join; - Map invite; - Map leave; + Map? join; + Map? invite; + Map? leave; RoomsUpdate(); @@ -139,13 +139,13 @@ class RoomsUpdate { Map toJson() { final data = {}; if (join != null) { - data['join'] = join.map((k, v) => MapEntry(k, v.toJson())); + data['join'] = join!.map((k, v) => MapEntry(k, v.toJson())); } if (invite != null) { - data['invite'] = invite.map((k, v) => MapEntry(k, v.toJson())); + data['invite'] = invite!.map((k, v) => MapEntry(k, v.toJson())); } if (leave != null) { - data['leave'] = leave.map((k, v) => MapEntry(k, v.toJson())); + data['leave'] = leave!.map((k, v) => MapEntry(k, v.toJson())); } return data; } @@ -154,12 +154,12 @@ class RoomsUpdate { abstract class SyncRoomUpdate {} class JoinedRoomUpdate extends SyncRoomUpdate { - RoomSummary summary; - List state; - TimelineUpdate timeline; - List ephemeral; - List accountData; - UnreadNotificationCounts unreadNotifications; + RoomSummary? summary; + List? state; + TimelineUpdate? timeline; + List? ephemeral; + List? accountData; + UnreadNotificationCounts? unreadNotifications; JoinedRoomUpdate(); @@ -195,35 +195,35 @@ class JoinedRoomUpdate extends SyncRoomUpdate { Map toJson() { final data = {}; if (summary != null) { - data['summary'] = summary.toJson(); + data['summary'] = summary!.toJson(); } if (state != null) { data['state'] = { - 'events': state.map((i) => i.toJson()).toList(), + 'events': state!.map((i) => i.toJson()).toList(), }; } if (timeline != null) { - data['timeline'] = timeline.toJson(); + data['timeline'] = timeline!.toJson(); } if (ephemeral != null) { data['ephemeral'] = { - 'events': ephemeral.map((i) => i.toJson()).toList(), + 'events': ephemeral!.map((i) => i.toJson()).toList(), }; } if (accountData != null) { data['account_data'] = { - 'events': accountData.map((i) => i.toJson()).toList(), + 'events': accountData!.map((i) => i.toJson()).toList(), }; } if (unreadNotifications != null) { - data['unread_notifications'] = unreadNotifications.toJson(); + data['unread_notifications'] = unreadNotifications!.toJson(); } return data; } } class InvitedRoomUpdate extends SyncRoomUpdate { - List inviteState; + List? inviteState; InvitedRoomUpdate.fromJson(Map json) { inviteState = (json['invite_state'] != null && json['invite_state']['events'] != null) @@ -236,7 +236,7 @@ class InvitedRoomUpdate extends SyncRoomUpdate { final data = {}; if (inviteState != null) { data['invite_state'] = { - 'events': inviteState.map((i) => i.toJson()).toList(), + 'events': inviteState!.map((i) => i.toJson()).toList(), }; } return data; @@ -244,9 +244,9 @@ class InvitedRoomUpdate extends SyncRoomUpdate { } class LeftRoomUpdate extends SyncRoomUpdate { - List state; - TimelineUpdate timeline; - List accountData; + List? state; + TimelineUpdate? timeline; + List? accountData; LeftRoomUpdate(); @@ -270,15 +270,15 @@ class LeftRoomUpdate extends SyncRoomUpdate { final data = {}; if (state != null) { data['state'] = { - 'events': state.map((i) => i.toJson()).toList(), + 'events': state!.map((i) => i.toJson()).toList(), }; } if (timeline != null) { - data['timeline'] = timeline.toJson(); + data['timeline'] = timeline!.toJson(); } if (accountData != null) { data['account_data'] = { - 'events': accountData.map((i) => i.toJson()).toList(), + 'events': accountData!.map((i) => i.toJson()).toList(), }; } return data; @@ -286,9 +286,9 @@ class LeftRoomUpdate extends SyncRoomUpdate { } class TimelineUpdate { - List events; - bool limited; - String prevBatch; + List? events; + bool? limited; + String? prevBatch; TimelineUpdate(); @@ -303,7 +303,7 @@ class TimelineUpdate { Map toJson() { final data = {}; if (events != null) { - data['events'] = events.map((i) => i.toJson()).toList(); + data['events'] = events!.map((i) => i.toJson()).toList(); } if (limited != null) { data['limited'] = limited; @@ -316,8 +316,8 @@ class TimelineUpdate { } class UnreadNotificationCounts { - int highlightCount; - int notificationCount; + int? highlightCount; + int? notificationCount; UnreadNotificationCounts.fromJson(Map json) { highlightCount = json['highlight_count']; notificationCount = json['notification_count']; @@ -335,8 +335,8 @@ class UnreadNotificationCounts { } class DeviceListsUpdate { - List changed; - List left; + List? changed; + List? left; DeviceListsUpdate.fromJson(Map json) { changed = List.from(json['changed'] ?? []); left = List.from(json['left'] ?? []); diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index cfcad4d4..fb834daf 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index 65a23dc5..e230e4ab 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/upload_key_signatures_response.dart b/lib/src/model/upload_key_signatures_response.dart index f5b46015..94f3255f 100644 --- a/lib/src/model/upload_key_signatures_response.dart +++ b/lib/src/model/upload_key_signatures_response.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -25,7 +25,7 @@ import 'matrix_exception.dart'; class UploadKeySignaturesResponse { - Map> failures; + Map>? failures; UploadKeySignaturesResponse.fromJson(Map json) : failures = json['failures'] != null @@ -43,7 +43,7 @@ class UploadKeySignaturesResponse { Map toJson() { final data = {}; if (failures != null) { - data['failures'] = failures.map( + data['failures'] = failures!.map( (k, v) => MapEntry( k, v.map( diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index b9179146..105319a3 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -51,7 +51,7 @@ class Logs { } } - void wtf(String title, [Object exception, StackTrace stackTrace]) => + void wtf(String title, [Object? exception, StackTrace? stackTrace]) => addLogEvent( LogEvent( title, @@ -61,7 +61,7 @@ class Logs { ), ); - void e(String title, [Object exception, StackTrace stackTrace]) => + void e(String title, [Object? exception, StackTrace? stackTrace]) => addLogEvent( LogEvent( title, @@ -71,7 +71,7 @@ class Logs { ), ); - void w(String title, [Object exception, StackTrace stackTrace]) => + void w(String title, [Object? exception, StackTrace? stackTrace]) => addLogEvent( LogEvent( title, @@ -81,7 +81,7 @@ class Logs { ), ); - void i(String title, [Object exception, StackTrace stackTrace]) => + void i(String title, [Object? exception, StackTrace? stackTrace]) => addLogEvent( LogEvent( title, @@ -91,7 +91,7 @@ class Logs { ), ); - void d(String title, [Object exception, StackTrace stackTrace]) => + void d(String title, [Object? exception, StackTrace? stackTrace]) => addLogEvent( LogEvent( title, @@ -101,7 +101,7 @@ class Logs { ), ); - void v(String title, [Object exception, StackTrace stackTrace]) => + void v(String title, [Object? exception, StackTrace? stackTrace]) => addLogEvent( LogEvent( title, @@ -115,8 +115,8 @@ class Logs { // ignore: avoid_print class LogEvent { final String title; - final Object exception; - final StackTrace stackTrace; + final Object? exception; + final StackTrace? stackTrace; final Level level; LogEvent( diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart index be21bf01..d2b89720 100644 --- a/lib/src/utils/map_copy_extension.dart +++ b/lib/src/utils/map_copy_extension.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index b9ab614c..0024aa12 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/test/event_content_test.dart b/test/event_content_test.dart index 750f7581..d7f79670 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,7 +29,7 @@ import 'dart:convert'; void main() { group('Event Content tests', () { test('Room Encryption Content', () { - var json = { + Map? json = { 'content': { 'algorithm': 'm.megolm.v1.aes-sha2', 'rotation_period_ms': 604800000, @@ -44,11 +44,11 @@ void main() { 'unsigned': {'age': 1234} }; json = jsonDecode(jsonEncode(json)); - expect(MatrixEvent.fromJson(json).parsedRoomEncryptionContent.toJson(), + expect(MatrixEvent.fromJson(json!).parsedRoomEncryptionContent.toJson(), json['content']); }); test('Room Encrypted Content', () { - var json = { + Map? json = { 'content': { 'algorithm': 'm.megolm.v1.aes-sha2', 'ciphertext': 'AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...', @@ -64,7 +64,7 @@ void main() { 'unsigned': {'age': 1234} }; json = jsonDecode(jsonEncode(json)); - expect(MatrixEvent.fromJson(json).parsedRoomEncryptedContent.toJson(), + expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), json['content']); json = { 'content': { @@ -85,11 +85,11 @@ void main() { 'unsigned': {'age': 1234} }; json = jsonDecode(jsonEncode(json)); - expect(MatrixEvent.fromJson(json).parsedRoomEncryptedContent.toJson(), + expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), json['content']); }); test('Room Key Content', () { - var json = { + Map? json = { 'content': { 'algorithm': 'm.megolm.v1.aes-sha2', 'room_id': '!Cuyf34gef24t:localhost', @@ -99,11 +99,11 @@ void main() { 'type': 'm.room_key' }; json = jsonDecode(jsonEncode(json)); - expect(BasicEvent.fromJson(json).parsedRoomKeyContent.toJson(), + expect(BasicEvent.fromJson(json!).parsedRoomKeyContent.toJson(), json['content']); }); test('Room Key Request Content', () { - var json = { + Map? json = { 'content': { 'action': 'request_cancellation', 'request_id': '1495474790150.19', @@ -112,7 +112,7 @@ void main() { 'type': 'm.room_key_request' }; json = jsonDecode(jsonEncode(json)); - expect(BasicEvent.fromJson(json).parsedRoomKeyRequestContent.toJson(), + expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), json['content']); json = { 'content': { @@ -129,11 +129,11 @@ void main() { 'type': 'm.room_key_request' }; json = jsonDecode(jsonEncode(json)); - expect(BasicEvent.fromJson(json).parsedRoomKeyRequestContent.toJson(), + expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), json['content']); }); test('Forwarded Room Key Content', () { - var json = { + Map? json = { 'content': { 'algorithm': 'm.megolm.v1.aes-sha2', 'forwarding_curve25519_key_chain': [ @@ -149,11 +149,11 @@ void main() { 'type': 'm.forwarded_room_key' }; json = jsonDecode(jsonEncode(json)); - expect(BasicEvent.fromJson(json).parsedForwardedRoomKeyContent.toJson(), + expect(BasicEvent.fromJson(json!).parsedForwardedRoomKeyContent.toJson(), json['content']); }); test('OLM Plaintext Payload', () { - var json = { + Map? json = { 'type': '', 'content': { 'msgtype': 'm.text', @@ -165,7 +165,7 @@ void main() { 'keys': {'ed25519': ''} }; json = jsonDecode(jsonEncode(json)); - expect(OlmPlaintextPayload.fromJson(json).toJson(), json); + expect(OlmPlaintextPayload.fromJson(json!).toJson(), json); }); }); } diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart index 442aaa62..f67b60fc 100644 --- a/test/map_copy_extension_test.dart +++ b/test/map_copy_extension_test.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 45eaf147..97b454e4 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -61,8 +61,8 @@ void main() { 'completed': ['example.type.foo'] }); expect( - exception.authenticationFlows.first.stages.first, 'example.type.foo'); - expect(exception.authenticationParams['example.type.baz'], + exception.authenticationFlows!.first.stages.first, 'example.type.foo'); + expect(exception.authenticationParams!['example.type.baz'], {'example_key': 'foobar'}); expect(exception.session, 'xxxxxxyz'); expect(exception.completedAuthenticationFlows, ['example.type.foo']); @@ -109,12 +109,12 @@ void main() { } catch (exception) { expect(exception is MatrixException, true); expect((exception as MatrixException).errcode, 'M_FORBIDDEN'); - expect((exception as MatrixException).error, MatrixError.M_FORBIDDEN); - expect((exception as MatrixException).errorMessage, 'Blabla'); - expect((exception as MatrixException).requireAdditionalAuthentication, + expect(exception.error, MatrixError.M_FORBIDDEN); + expect(exception.errorMessage, 'Blabla'); + expect(exception.requireAdditionalAuthentication, false); expect( - (exception as MatrixException).toString(), 'M_FORBIDDEN: Blabla'); + exception.toString(), 'M_FORBIDDEN: Blabla'); error = true; } expect(error, true); @@ -124,8 +124,8 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final supportedVersions = await matrixApi.getVersions(); expect(supportedVersions.versions.contains('r0.5.0'), true); - expect(supportedVersions.unstableFeatures['m.lazy_load_members'], true); - expect(FakeMatrixApi.api['GET']['/client/versions']({}), + expect(supportedVersions.unstableFeatures!['m.lazy_load_members'], true); + expect(FakeMatrixApi.api['GET']!['/client/versions']({}), supportedVersions.toJson()); matrixApi.homeserver = null; }); @@ -146,9 +146,9 @@ void main() { }); test('getLoginTypes', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final loginTypes = await matrixApi.getLoginFlows(); + final loginTypes = await (matrixApi.getLoginFlows() as FutureOr>); expect(loginTypes.first.type, 'm.login.password'); - expect(FakeMatrixApi.api['GET']['/client/r0/login']({}), + expect(FakeMatrixApi.api['GET']!['/client/r0/login']({}), {'flows': loginTypes.map((x) => x.toJson()).toList()}); matrixApi.homeserver = null; }); @@ -158,7 +158,7 @@ void main() { LoginType.mLoginPassword, identifier: AuthenticationUserIdentifier(user: 'username'), ); - expect(FakeMatrixApi.api['POST']['/client/r0/login']({}), + expect(FakeMatrixApi.api['POST']!['/client/r0/login']({}), loginResponse.toJson()); matrixApi.homeserver = null; }); @@ -178,7 +178,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final registerResponse = await matrixApi.register(kind: AccountKind.guest, username: 'test'); - expect(FakeMatrixApi.api['POST']['/client/r0/register?kind=guest']({}), + expect(FakeMatrixApi.api['POST']!['/client/r0/register?kind=guest']({}), registerResponse.toJson()); matrixApi.homeserver = null; }); @@ -194,7 +194,7 @@ void main() { idAccessToken: '1234', ); expect( - FakeMatrixApi.api['POST'] + FakeMatrixApi.api['POST']! ['/client/r0/register/email/requestToken']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -212,7 +212,7 @@ void main() { idAccessToken: '1234', ); expect( - FakeMatrixApi.api['POST'] + FakeMatrixApi.api['POST']! ['/client/r0/register/email/requestToken']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -281,8 +281,8 @@ void main() { test('getThirdPartyIdentifiers', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.getAccount3PIDs(); - expect(FakeMatrixApi.api['GET']['/client/r0/account/3pid']({}), + final response = await (matrixApi.getAccount3PIDs() as FutureOr>); + expect(FakeMatrixApi.api['GET']!['/client/r0/account/3pid']({}), {'threepids': response.map((t) => t.toJson()).toList()}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -364,7 +364,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getCapabilities(); - expect(FakeMatrixApi.api['GET']['/client/r0/capabilities']({}), + expect(FakeMatrixApi.api['GET']!['/client/r0/capabilities']({}), {'capabilities': response.toJson()}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -498,9 +498,9 @@ void main() { timeout: 15, ); expect( - FakeMatrixApi.api['GET'][ + FakeMatrixApi.api['GET']![ '/client/r0/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15']( - {}) as Map, + {}) as Map?, response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -537,12 +537,12 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final states = await matrixApi.getMembersByRoom( + final states = await (matrixApi.getMembersByRoom( '!localpart:server.abc', at: '1234', membership: Membership.join, notMembership: Membership.leave, - ); + ) as FutureOr>); expect(states.length, 1); matrixApi.homeserver = matrixApi.accessToken = null; @@ -551,11 +551,11 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final states = await matrixApi.getJoinedMembersByRoom( + final states = await (matrixApi.getJoinedMembersByRoom( '!localpart:server.abc', - ); + ) as FutureOr>); expect(states.length, 1); - expect(states['@bar:example.com'].toJson(), { + expect(states['@bar:example.com']!.toJson(), { 'display_name': 'Bar', 'avatar_url': 'mxc://riot.ovh/printErCATzZijQsSDWorRaK' }); @@ -576,9 +576,9 @@ void main() { ); expect( - FakeMatrixApi.api['GET'][ + FakeMatrixApi.api['GET']![ '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']( - {}) as Map, + {}) as Map?, timelineHistoryResponse.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -667,7 +667,7 @@ void main() { ); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/r0/directory/room/%23testalias%3Aexample.com']({}), roomAliasInformation.toJson()); @@ -829,7 +829,7 @@ void main() { ); expect( - FakeMatrixApi.api['GET'][ + FakeMatrixApi.api['GET']![ '/client/r0/publicRooms?limit=10&since=1234&server=example.com']({}), response.toJson()); @@ -851,7 +851,7 @@ void main() { ); expect( - FakeMatrixApi.api['POST'] + FakeMatrixApi.api['POST']! ['/client/r0/publicRooms?server=example.com']({}), response.toJson()); @@ -866,7 +866,7 @@ void main() { limit: 10, ); - expect(FakeMatrixApi.api['POST']['/client/r0/user_directory/search']({}), + expect(FakeMatrixApi.api['POST']!['/client/r0/user_directory/search']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -913,7 +913,7 @@ void main() { final response = await matrixApi.getUserProfile('@alice:example.com'); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/r0/profile/%40alice%3Aexample.com']({}), response.toJson()); @@ -924,7 +924,7 @@ void main() { matrixApi.accessToken = '1234'; final response = await matrixApi.getTurnServer(); - expect(FakeMatrixApi.api['GET']['/client/r0/voip/turnServer']({}), + expect(FakeMatrixApi.api['GET']!['/client/r0/voip/turnServer']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -987,7 +987,7 @@ void main() { '@alice:example.com', ); expect( - FakeMatrixApi.api['GET'][ + FakeMatrixApi.api['GET']![ '/client/r0/presence/${Uri.encodeComponent('@alice:example.com')}/status']({}), response.toJson()); @@ -1017,7 +1017,7 @@ void main() { ts: 10, ); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']({}), openGraphData.toJson()); @@ -1048,8 +1048,8 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final devices = await matrixApi.getDevices(); - expect(FakeMatrixApi.api['GET']['/client/r0/devices']({})['devices'], + final devices = await (matrixApi.getDevices() as FutureOr>); + expect(FakeMatrixApi.api['GET']!['/client/r0/devices']({})['devices'], devices.map((i) => i.toJson()).toList()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1118,10 +1118,10 @@ void main() { ); expect( response - .deviceKeys['@alice:example.com']['JLAFKJWSCS'].deviceDisplayName, + .deviceKeys!['@alice:example.com']!['JLAFKJWSCS']!.deviceDisplayName, 'Alices mobile phone'); expect( - FakeMatrixApi.api['POST'] + FakeMatrixApi.api['POST']! ['/client/r0/keys/query']({'device_keys': {}}), response.toJson()); @@ -1138,7 +1138,7 @@ void main() { timeout: 10, ); expect( - FakeMatrixApi.api['POST']['/client/r0/keys/claim']({ + FakeMatrixApi.api['POST']!['/client/r0/keys/claim']({ 'one_time_keys': { '@alice:example.com': {'JLAFKJWSCS': 'signed_curve25519'} } @@ -1234,7 +1234,7 @@ void main() { }); final ret = await matrixApi.uploadKeySignatures([key1, key2]); expect( - FakeMatrixApi.api['POST']['/client/r0/keys/signatures/upload']({}), + FakeMatrixApi.api['POST']!['/client/r0/keys/signatures/upload']({}), ret.toJson(), ); }); @@ -1242,9 +1242,9 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.getPushers(); + final response = await (matrixApi.getPushers() as FutureOr>); expect( - FakeMatrixApi.api['GET']['/client/r0/pushers']({}), + FakeMatrixApi.api['GET']!['/client/r0/pushers']({}), {'pushers': response.map((i) => i.toJson()).toList()}, ); @@ -1281,7 +1281,7 @@ void main() { only: '1234', ); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/r0/notifications?from=1234&limit=10&only=1234']({}), response.toJson(), ); @@ -1294,7 +1294,7 @@ void main() { final response = await matrixApi.getPushRules(); expect( - FakeMatrixApi.api['GET']['/client/r0/pushrules']({}), + FakeMatrixApi.api['GET']!['/client/r0/pushrules']({}), {'global': response.toJson()}, ); @@ -1307,7 +1307,7 @@ void main() { final response = await matrixApi.getPushRule('global', PushRuleKind.content, 'nocake'); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/r0/pushrules/global/content/nocake']({}), response.toJson(), ); @@ -1407,7 +1407,7 @@ void main() { final response = await matrixApi.getEvents(from: '1234', roomId: '!1234', timeout: 10); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/r0/events?from=1234&timeout=10&roomId=%211234']({}), response.toJson(), ); @@ -1418,10 +1418,10 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.getRoomTags( - '@alice:example.com', '!localpart:example.com'); + final response = await (matrixApi.getRoomTags( + '@alice:example.com', '!localpart:example.com') as FutureOr>); expect( - FakeMatrixApi.api['GET'][ + FakeMatrixApi.api['GET']![ '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']({}), {'tags': response.map((k, v) => MapEntry(k, v.toJson()))}, ); @@ -1507,7 +1507,7 @@ void main() { final response = await matrixApi.getWhoIs('@alice:example.com'); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/r0/admin/whois/%40alice%3Aexample.com']({}), response.toJson(), ); @@ -1521,7 +1521,7 @@ void main() { final response = await matrixApi.getEventContext('1234', '1234', limit: 10, filter: '{}'); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/r0/rooms/1234/context/1234?limit=10&filter=%7B%7D']({}), response.toJson(), ); @@ -1547,7 +1547,7 @@ void main() { final response = await matrixApi.requestSupportedProtocols(); expect( - FakeMatrixApi.api['GET']['/client/r0/thirdparty/protocols']({}), + FakeMatrixApi.api['GET']!['/client/r0/thirdparty/protocols']({}), response.map((k, v) => MapEntry(k, v.toJson())), ); @@ -1559,7 +1559,7 @@ void main() { final response = await matrixApi.requestSupportedProtocol('irc'); expect( - FakeMatrixApi.api['GET']['/client/r0/thirdparty/protocol/irc']({}), + FakeMatrixApi.api['GET']!['/client/r0/thirdparty/protocol/irc']({}), response.toJson(), ); @@ -1571,7 +1571,7 @@ void main() { final response = await matrixApi.requestThirdPartyLocations('irc'); expect( - FakeMatrixApi.api['GET']['/client/r0/thirdparty/location/irc']({}), + FakeMatrixApi.api['GET']!['/client/r0/thirdparty/location/irc']({}), response.map((i) => i.toJson()).toList(), ); @@ -1583,7 +1583,7 @@ void main() { final response = await matrixApi.requestThirdPartyUsers('irc'); expect( - FakeMatrixApi.api['GET']['/client/r0/thirdparty/user/irc']({}), + FakeMatrixApi.api['GET']!['/client/r0/thirdparty/user/irc']({}), response.map((i) => i.toJson()).toList(), ); @@ -1596,7 +1596,7 @@ void main() { final response = await matrixApi.requestThirdPartyLocationsByAlias('1234'); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/r0/thirdparty/location?alias=1234']({}), response.map((i) => i.toJson()).toList(), ); @@ -1609,7 +1609,7 @@ void main() { final response = await matrixApi.requestThirdPartyUsersByUserId('1234'); expect( - FakeMatrixApi.api['GET']['/client/r0/thirdparty/user?userid=1234']({}), + FakeMatrixApi.api['GET']!['/client/r0/thirdparty/user?userid=1234']({}), response.map((i) => i.toJson()).toList(), ); @@ -1621,7 +1621,7 @@ void main() { final response = await matrixApi.requestOpenIdToken('1234', {}); expect( - FakeMatrixApi.api['POST'] + FakeMatrixApi.api['POST']! ['/client/r0/user/1234/openid/request_token']({}), response.toJson(), ); @@ -1647,7 +1647,7 @@ void main() { }; final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); expect( - FakeMatrixApi.api['POST'] + FakeMatrixApi.api['POST']! ['/client/unstable/room_keys/version']({})['version'], ret); }); @@ -1656,7 +1656,7 @@ void main() { matrixApi.accessToken = '1234'; final ret = await matrixApi.getRoomKeysVersionCurrent(); - expect(FakeMatrixApi.api['GET']['/client/unstable/room_keys/version']({}), + expect(FakeMatrixApi.api['GET']!['/client/unstable/room_keys/version']({}), ret.toJson()); }); test('putRoomKeysVersion', () async { @@ -1696,7 +1696,7 @@ void main() { final ret = await matrixApi.postRoomKeysKeyRoomIdSessionId( roomId, sessionId, '5', session); expect( - FakeMatrixApi.api['PUT'][ + FakeMatrixApi.api['PUT']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); @@ -1708,7 +1708,7 @@ void main() { final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; final ret = await matrixApi.getRoomKeysSingleKey(roomId, sessionId, '5'); expect( - FakeMatrixApi.api['GET'][ + FakeMatrixApi.api['GET']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); @@ -1721,7 +1721,7 @@ void main() { final ret = await matrixApi.deleteRoomKeysSingleKey(roomId, sessionId, '5'); expect( - FakeMatrixApi.api['DELETE'][ + FakeMatrixApi.api['DELETE']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); @@ -1748,7 +1748,7 @@ void main() { }); final ret = await matrixApi.postRoomKeysKeyRoomId(roomId, '5', session); expect( - FakeMatrixApi.api['PUT'][ + FakeMatrixApi.api['PUT']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); @@ -1759,7 +1759,7 @@ void main() { final roomId = '!726s6s6q:example.com'; final ret = await matrixApi.getRoomKeysRoom(roomId, '5'); expect( - FakeMatrixApi.api['GET'][ + FakeMatrixApi.api['GET']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); @@ -1770,7 +1770,7 @@ void main() { final roomId = '!726s6s6q:example.com'; final ret = await matrixApi.deleteRoomKeysRoom(roomId, '5'); expect( - FakeMatrixApi.api['DELETE'][ + FakeMatrixApi.api['DELETE']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); @@ -1801,7 +1801,7 @@ void main() { }); final ret = await matrixApi.postRoomKeysKey('5', session); expect( - FakeMatrixApi.api['PUT'] + FakeMatrixApi.api['PUT']! ['/client/unstable/room_keys/keys?version=5']({}), ret.toJson()); }); @@ -1811,7 +1811,7 @@ void main() { final ret = await matrixApi.getRoomKeys('5'); expect( - FakeMatrixApi.api['GET'] + FakeMatrixApi.api['GET']! ['/client/unstable/room_keys/keys?version=5']({}), ret.toJson()); }); @@ -1821,7 +1821,7 @@ void main() { final ret = await matrixApi.deleteRoomKeys('5'); expect( - FakeMatrixApi.api['DELETE'] + FakeMatrixApi.api['DELETE']! ['/client/unstable/room_keys/keys?version=5']({}), ret.toJson()); }); diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index dca18807..43317512 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -1,4 +1,4 @@ -// @dart=2.9 + /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH From 9e6019b820695f2260d756a00c474dd137167125 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Thu, 1 Jul 2021 15:13:45 +0200 Subject: [PATCH 065/174] fix: return Never --- lib/src/matrix_api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 31dc95be..b1484441 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -63,7 +63,7 @@ class MatrixApi extends Api { set accessToken(String? token) => bearerToken = token; @override - Null unexpectedResponse(http.BaseResponse response, Uint8List responseBody) { + Never unexpectedResponse(http.BaseResponse response, Uint8List responseBody) { if (response.statusCode >= 400 && response.statusCode < 500) { throw MatrixException.fromJson(json.decode(utf8.decode(responseBody))); } From 1a51f813a7fcc128fa5352409127fdbbbd76842e Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Thu, 1 Jul 2021 16:59:54 +0200 Subject: [PATCH 066/174] null safety cleanup --- lib/fake_matrix_api.dart | 1 - lib/matrix_api_lite.dart | 49 +++---- lib/src/matrix_api.dart | 6 +- lib/src/model/algorithm_types.dart | 1 - lib/src/model/auth/authentication_data.dart | 5 +- .../model/auth/authentication_identifier.dart | 5 +- .../model/auth/authentication_password.dart | 9 +- .../auth/authentication_phone_identifier.dart | 1 - .../model/auth/authentication_recaptcha.dart | 1 - ...authentication_third_party_identifier.dart | 4 +- .../auth/authentication_three_pid_creds.dart | 11 +- lib/src/model/auth/authentication_token.dart | 1 - lib/src/model/auth/authentication_types.dart | 1 - .../auth/authentication_user_identifier.dart | 1 - lib/src/model/basic_event.dart | 1 - lib/src/model/basic_event_with_sender.dart | 7 +- lib/src/model/basic_room_event.dart | 1 - lib/src/model/event_types.dart | 2 +- .../events/forwarded_room_key_content.dart | 10 +- .../model/events/olm_plaintext_payload.dart | 13 +- .../model/events/room_encrypted_content.dart | 38 ++--- .../model/events/room_encryption_content.dart | 9 +- lib/src/model/events/room_key_content.dart | 17 ++- .../events/room_key_request_content.dart | 31 ++-- .../secret_storage_default_key_content.dart | 8 +- .../events/secret_storage_key_content.dart | 35 +++-- lib/src/model/events/tombstone_content.dart | 7 +- lib/src/model/events_sync_update.dart | 1 - .../model/matrix_connection_exception.dart | 2 +- lib/src/model/matrix_event.dart | 22 ++- lib/src/model/matrix_exception.dart | 8 +- lib/src/model/matrix_keys.dart | 40 ++--- lib/src/model/message_types.dart | 1 - lib/src/model/presence.dart | 1 - lib/src/model/presence_content.dart | 1 - lib/src/model/request_token_response.dart | 1 - lib/src/model/room_creation_types.dart | 1 - lib/src/model/room_keys_keys.dart | 5 +- lib/src/model/room_summary.dart | 2 +- lib/src/model/room_types.dart | 1 - lib/src/model/stripped_state_event.dart | 9 +- lib/src/model/supported_protocol.dart | 21 +-- lib/src/model/sync_update.dart | 11 +- lib/src/model/third_party_location.dart | 1 - lib/src/model/third_party_user.dart | 1 - .../model/upload_key_signatures_response.dart | 1 - lib/src/utils/logs.dart | 1 - lib/src/utils/map_copy_extension.dart | 1 - lib/src/utils/try_get_map_extension.dart | 32 +--- lib/src/values.dart | 1 + test/event_content_test.dart | 4 +- test/map_copy_extension_test.dart | 1 - test/matrix_api_test.dart | 137 +++++++++--------- test/try_get_map_extension_test.dart | 1 - 54 files changed, 285 insertions(+), 298 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index b1e80ed9..f0f2d16d 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 3a638c49..d6251d92 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -24,17 +23,32 @@ library matrix_api_lite; -export 'src/matrix_api.dart'; -export 'src/values.dart'; export 'src/generated/model.dart'; -export 'src/utils/logs.dart'; -export 'src/utils/map_copy_extension.dart'; -export 'src/utils/try_get_map_extension.dart'; +export 'src/matrix_api.dart'; export 'src/model/algorithm_types.dart'; +export 'src/model/auth/authentication_data.dart'; +export 'src/model/auth/authentication_identifier.dart'; +export 'src/model/auth/authentication_password.dart'; +export 'src/model/auth/authentication_phone_identifier.dart'; +export 'src/model/auth/authentication_recaptcha.dart'; +export 'src/model/auth/authentication_third_party_identifier.dart'; +export 'src/model/auth/authentication_three_pid_creds.dart'; +export 'src/model/auth/authentication_token.dart'; +export 'src/model/auth/authentication_types.dart'; +export 'src/model/auth/authentication_user_identifier.dart'; export 'src/model/basic_event.dart'; export 'src/model/basic_event_with_sender.dart'; export 'src/model/basic_room_event.dart'; export 'src/model/event_types.dart'; +export 'src/model/events/forwarded_room_key_content.dart'; +export 'src/model/events/olm_plaintext_payload.dart'; +export 'src/model/events/room_encrypted_content.dart'; +export 'src/model/events/room_encryption_content.dart'; +export 'src/model/events/room_key_content.dart'; +export 'src/model/events/room_key_request_content.dart'; +export 'src/model/events/secret_storage_default_key_content.dart'; +export 'src/model/events/secret_storage_key_content.dart'; +export 'src/model/events/tombstone_content.dart'; export 'src/model/events_sync_update.dart'; export 'src/model/matrix_connection_exception.dart'; export 'src/model/matrix_event.dart'; @@ -53,22 +67,7 @@ export 'src/model/sync_update.dart'; export 'src/model/third_party_location.dart'; export 'src/model/third_party_user.dart'; export 'src/model/upload_key_signatures_response.dart'; -export 'src/model/auth/authentication_data.dart'; -export 'src/model/auth/authentication_identifier.dart'; -export 'src/model/auth/authentication_password.dart'; -export 'src/model/auth/authentication_phone_identifier.dart'; -export 'src/model/auth/authentication_recaptcha.dart'; -export 'src/model/auth/authentication_third_party_identifier.dart'; -export 'src/model/auth/authentication_three_pid_creds.dart'; -export 'src/model/auth/authentication_token.dart'; -export 'src/model/auth/authentication_types.dart'; -export 'src/model/auth/authentication_user_identifier.dart'; -export 'src/model/events/forwarded_room_key_content.dart'; -export 'src/model/events/olm_plaintext_payload.dart'; -export 'src/model/events/room_encrypted_content.dart'; -export 'src/model/events/room_encryption_content.dart'; -export 'src/model/events/room_key_content.dart'; -export 'src/model/events/room_key_request_content.dart'; -export 'src/model/events/secret_storage_default_key_content.dart'; -export 'src/model/events/secret_storage_key_content.dart'; -export 'src/model/events/tombstone_content.dart'; +export 'src/utils/logs.dart'; +export 'src/utils/map_copy_extension.dart'; +export 'src/utils/try_get_map_extension.dart'; +export 'src/values.dart'; diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index b1484441..88859870 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,6 +28,7 @@ import 'dart:typed_data'; import 'package:http/http.dart' as http; import '../matrix_api_lite.dart'; +import 'generated/api.dart'; import 'model/auth/authentication_data.dart'; import 'model/events_sync_update.dart'; import 'model/matrix_connection_exception.dart'; @@ -41,8 +41,6 @@ import 'model/third_party_location.dart'; import 'model/third_party_user.dart'; import 'model/upload_key_signatures_response.dart'; -import 'generated/api.dart'; - enum RequestType { GET, POST, PUT, DELETE } String describeEnum(Object enumEntry) { @@ -55,11 +53,13 @@ String describeEnum(Object enumEntry) { class MatrixApi extends Api { /// The homeserver this client is communicating with. Uri? get homeserver => baseUri; + set homeserver(Uri? uri) => baseUri = uri; /// This is the access token for the matrix client. When it is undefined, then /// the user needs to sign in first. String? get accessToken => bearerToken; + set accessToken(String? token) => bearerToken = token; @override diff --git a/lib/src/model/algorithm_types.dart b/lib/src/model/algorithm_types.dart index 59144cf3..e4f8548b 100644 --- a/lib/src/model/algorithm_types.dart +++ b/lib/src/model/algorithm_types.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 85d39767..53ea3ecf 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -24,7 +23,7 @@ class AuthenticationData { String type; - String?/*?*//*?*/ session; + String? /*?*/ /*?*/ session; AuthenticationData({required this.type, this.session}); @@ -34,7 +33,7 @@ class AuthenticationData { Map toJson() { final data = {}; - if (type != null) data['type'] = type; + data['type'] = type; if (session != null) data['session'] = session; return data; } diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index 572932a0..ada4778a 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,10 +21,10 @@ * SOFTWARE. */ -import 'authentication_types.dart'; -import 'authentication_user_identifier.dart'; import 'authentication_phone_identifier.dart'; import 'authentication_third_party_identifier.dart'; +import 'authentication_types.dart'; +import 'authentication_user_identifier.dart'; class AuthenticationIdentifier { String type; diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index b1066c2f..2b5cb13a 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,11 +21,10 @@ * SOFTWARE. */ -import 'authentication_user_identifier.dart'; - import 'authentication_data.dart'; import 'authentication_identifier.dart'; import 'authentication_types.dart'; +import 'authentication_user_identifier.dart'; class AuthenticationPassword extends AuthenticationData { String? user; @@ -37,7 +35,10 @@ class AuthenticationPassword extends AuthenticationData { AuthenticationIdentifier identifier; AuthenticationPassword( - {String? session, required this.password, this.user, required this.identifier}) + {String? session, + required this.password, + this.user, + required this.identifier}) : super( type: AuthenticationTypes.password, session: session, diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index 5e3c7779..e6eb8aa6 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index fdedf5b3..20c8d3c2 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index 94b55e28..2860dfdf 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -29,7 +28,8 @@ class AuthenticationThirdPartyIdentifier extends AuthenticationIdentifier { String medium; String address; - AuthenticationThirdPartyIdentifier({required this.medium, required this.address}) + AuthenticationThirdPartyIdentifier( + {required this.medium, required this.address}) : super(type: AuthenticationIdentifierTypes.thirdParty); AuthenticationThirdPartyIdentifier.fromJson(Map json) diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 2961ac56..8a20d904 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -31,7 +30,8 @@ import 'authentication_data.dart'; class AuthenticationThreePidCreds extends AuthenticationData { late List threepidCreds; - AuthenticationThreePidCreds({String? session, required String type, required this.threepidCreds}) + AuthenticationThreePidCreds( + {String? session, required String type, required this.threepidCreds}) : super( type: type, session: session, @@ -65,13 +65,16 @@ class AuthenticationThreePidCreds extends AuthenticationData { } class ThreepidCreds { - String/*!*/ sid; + String /*!*/ sid; String clientSecret; String idServer; String idAccessToken; ThreepidCreds( - {required this.sid, required this.clientSecret, required this.idServer, required this.idAccessToken}); + {required this.sid, + required this.clientSecret, + required this.idServer, + required this.idAccessToken}); ThreepidCreds.fromJson(Map json) : sid = json['sid'], diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index 63233f4f..13749069 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_types.dart b/lib/src/model/auth/authentication_types.dart index 00f13793..ea181e40 100644 --- a/lib/src/model/auth/authentication_types.dart +++ b/lib/src/model/auth/authentication_types.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index 974f7fee..9070dc48 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 666fa516..5ea833f1 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index 4b6114a7..6618fc5a 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -27,7 +26,11 @@ import 'basic_event.dart'; class BasicEventWithSender extends BasicEvent { String senderId; - BasicEventWithSender(); + BasicEventWithSender( + {required String type, + required Map content, + required this.senderId}) + : super(type: type, content: content); BasicEventWithSender.fromJson(Map json) : senderId = json['sender'], diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index 66eff7d8..0e416483 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index 19623f5d..d5adc9ac 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -68,6 +67,7 @@ abstract class EventTypes { static const String CrossSigningMasterKey = 'm.cross_signing.master'; static const String MegolmBackup = 'm.megolm_backup.v1'; static const String SecretStorageDefaultKey = 'm.secret_storage.default_key'; + static String secretStorageKey(String keyId) => 'm.secret_storage.key.$keyId'; // Spaces diff --git a/lib/src/model/events/forwarded_room_key_content.dart b/lib/src/model/events/forwarded_room_key_content.dart index fb8ca523..b4ec3232 100644 --- a/lib/src/model/events/forwarded_room_key_content.dart +++ b/lib/src/model/events/forwarded_room_key_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,8 +21,8 @@ * SOFTWARE. */ -import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; import 'room_key_content.dart'; extension ForwardedRoomKeyContentBasicEventExtension on BasicEvent { @@ -35,12 +34,13 @@ class ForwardedRoomKeyContent extends RoomKeyContent { String senderKey; String senderClaimedEd25519Key; List forwardingCurve25519KeyChain; + ForwardedRoomKeyContent.fromJson(Map json) - : senderKey = json.tryGet('sender_key', ''), + : senderKey = json.tryGet('sender_key') ?? '', senderClaimedEd25519Key = - json.tryGet('sender_claimed_ed25519_key', ''), + json.tryGet('sender_claimed_ed25519_key') ?? '', forwardingCurve25519KeyChain = - json.tryGetList('forwarding_curve25519_key_chain', []), + json.tryGetList('forwarding_curve25519_key_chain') ?? [], super.fromJson(json); @override diff --git a/lib/src/model/events/olm_plaintext_payload.dart b/lib/src/model/events/olm_plaintext_payload.dart index 69a6d0e8..5f67ca1b 100644 --- a/lib/src/model/events/olm_plaintext_payload.dart +++ b/lib/src/model/events/olm_plaintext_payload.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -43,12 +42,12 @@ class OlmPlaintextPayload { factory OlmPlaintextPayload.fromJson(Map json) => OlmPlaintextPayload( - sender: json.tryGet('sender'), - type: json.tryGet('type'), - content: json.tryGetMap('content'), - recipient: json.tryGet('recipient'), - recipientKeys: json.tryGetMap('recipient_keys'), - keys: json.tryGetMap('keys'), + sender: json.tryGet('sender'), + type: json.tryGet('type'), + content: json.tryGetMap('content'), + recipient: json.tryGet('recipient'), + recipientKeys: json.tryGetMap('recipient_keys'), + keys: json.tryGetMap('keys'), ); Map toJson() { diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 3608621a..e062f77f 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -24,8 +23,8 @@ import 'package:matrix_api_lite/src/utils/logs.dart'; -import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; extension RoomEncryptedContentBasicEventExtension on BasicEvent { RoomEncryptedContent get parsedRoomEncryptedContent => @@ -41,18 +40,14 @@ class RoomEncryptedContent { Map? ciphertextOlm; RoomEncryptedContent.fromJson(Map json) - : algorithm = json.tryGet('algorithm', ''), - senderKey = json.tryGet('sender_key', ''), - deviceId = json.tryGet('device_id'), - sessionId = json.tryGet('session_id'), - ciphertextMegolm = json['ciphertext'] is String - ? json.tryGet('ciphertext') - : null, - ciphertextOlm = json['ciphertext'] is Map - ? json - .tryGet>('ciphertext') - ?.map((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))) - : null; + : algorithm = json.tryGet('algorithm') ?? '', + senderKey = json.tryGet('sender_key') ?? '', + deviceId = json.tryGet('device_id'), + sessionId = json.tryGet('session_id'), + ciphertextMegolm = json.tryGet('ciphertext'), + ciphertextOlm = json + .tryGet>('ciphertext') + ?.map((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))); Map toJson() { final data = {}; @@ -68,7 +63,8 @@ class RoomEncryptedContent { data['ciphertext'] = ciphertextMegolm; } if (ciphertextOlm != null) { - data['ciphertext'] = ciphertextOlm!.map((k, v) => MapEntry(k, v.toJson())); + data['ciphertext'] = + ciphertextOlm!.map((k, v) => MapEntry(k, v.toJson())); if (ciphertextMegolm != null) { Logs().wtf( 'ciphertextOlm and ciphertextMegolm are both set, which should never happen!'); @@ -83,17 +79,13 @@ class CiphertextInfo { int type; CiphertextInfo.fromJson(Map json) - : body = json.tryGet('body'), - type = json.tryGet('type'); + : body = json['body'], + type = json['type']; Map toJson() { final data = {}; - if (body != null) { - data['body'] = body; - } - if (type != null) { - data['type'] = type; - } + data['body'] = body; + data['type'] = type; return data; } } diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/src/model/events/room_encryption_content.dart index c639ba67..b88db983 100644 --- a/lib/src/model/events/room_encryption_content.dart +++ b/lib/src/model/events/room_encryption_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,8 +21,8 @@ * SOFTWARE. */ -import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; extension RoomEncryptionContentBasicEventExtension on BasicEvent { RoomEncryptionContent get parsedRoomEncryptionContent => @@ -36,9 +35,9 @@ class RoomEncryptionContent { int? rotationPeriodMsgs; RoomEncryptionContent.fromJson(Map json) - : algorithm = json.tryGet('algorithm', ''), - rotationPeriodMs = json.tryGet('rotation_period_ms'), - rotationPeriodMsgs = json.tryGet('rotation_period_msgs'); + : algorithm = json.tryGet('algorithm') ?? '', + rotationPeriodMs = json.tryGet('rotation_period_ms'), + rotationPeriodMsgs = json.tryGet('rotation_period_msgs'); Map toJson() { final data = {}; diff --git a/lib/src/model/events/room_key_content.dart b/lib/src/model/events/room_key_content.dart index 4149ffad..e179e662 100644 --- a/lib/src/model/events/room_key_content.dart +++ b/lib/src/model/events/room_key_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,8 +21,8 @@ * SOFTWARE. */ -import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; extension RoomKeyContentBasicEventExtension on BasicEvent { RoomKeyContent get parsedRoomKeyContent => RoomKeyContent.fromJson(content); @@ -35,13 +34,17 @@ class RoomKeyContent { String sessionId; String sessionKey; - RoomKeyContent(); + RoomKeyContent( + {required this.algorithm, + required this.roomId, + required this.sessionId, + required this.sessionKey}); RoomKeyContent.fromJson(Map json) - : algorithm = json.tryGet('algorithm', ''), - roomId = json.tryGet('room_id', ''), - sessionId = json.tryGet('session_id', ''), - sessionKey = json.tryGet('session_key', ''); + : algorithm = json.tryGet('algorithm') ?? '', + roomId = json.tryGet('room_id') ?? '', + sessionId = json.tryGet('session_id') ?? '', + sessionKey = json.tryGet('session_key') ?? ''; Map toJson() { final data = {}; diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index 1a7e6871..394d8233 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,8 +21,8 @@ * SOFTWARE. */ -import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; extension RoomKeyRequestContentBasicEventExtension on BasicEvent { RoomKeyRequestContent get parsedRoomKeyRequestContent => @@ -37,11 +36,11 @@ class RoomKeyRequestContent { String requestId; RoomKeyRequestContent.fromJson(Map json) - : body = RequestedKeyInfo.fromJson( + : body = ((x) => x != null ? RequestedKeyInfo.fromJson(x) : null)( json.tryGet>('body')), - action = json.tryGet('action', ''), - requestingDeviceId = json.tryGet('requesting_device_id', ''), - requestId = json.tryGet('request_id', ''); + action = json.tryGet('action') ?? '', + requestingDeviceId = json.tryGet('requesting_device_id') ?? '', + requestId = json.tryGet('request_id') ?? ''; Map toJson() { final data = {}; @@ -59,17 +58,17 @@ class RequestedKeyInfo { String sessionId; String senderKey; - RequestedKeyInfo(); + RequestedKeyInfo( + {required this.algorithm, + required this.roomId, + required this.sessionId, + required this.senderKey}); - factory RequestedKeyInfo.fromJson(Map json) { - if (json == null) return null; - final requestKeyInfo = RequestedKeyInfo(); - requestKeyInfo.algorithm = json.tryGet('algorithm', ''); - requestKeyInfo.roomId = json.tryGet('room_id', ''); - requestKeyInfo.sessionId = json.tryGet('session_id', ''); - requestKeyInfo.senderKey = json.tryGet('sender_key', ''); - return requestKeyInfo; - } + RequestedKeyInfo.fromJson(Map json) + : algorithm = json.tryGet('algorithm') ?? '', + roomId = json.tryGet('room_id') ?? '', + sessionId = json.tryGet('session_id') ?? '', + senderKey = json.tryGet('sender_key') ?? ''; Map toJson() { final data = {}; diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/src/model/events/secret_storage_default_key_content.dart index 389795d0..46394fbf 100644 --- a/lib/src/model/events/secret_storage_default_key_content.dart +++ b/lib/src/model/events/secret_storage_default_key_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,8 +21,8 @@ * SOFTWARE. */ -import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; extension SecretStorageDefaultKeyContentBasicEventExtension on BasicEvent { SecretStorageDefaultKeyContent get parsedSecretStorageDefaultKeyContent => @@ -31,9 +30,10 @@ extension SecretStorageDefaultKeyContentBasicEventExtension on BasicEvent { } class SecretStorageDefaultKeyContent { - String key; + //TODO: Required by spec, we should require it here and make sure to catch it everywhere + String? key; - SecretStorageDefaultKeyContent(); + SecretStorageDefaultKeyContent({required this.key}); SecretStorageDefaultKeyContent.fromJson(Map json) : key = json.tryGet('key'); diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index 8e10a182..b6542bac 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,8 +21,8 @@ * SOFTWARE. */ -import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; extension SecretStorageKeyContentBasicEventExtension on BasicEvent { SecretStorageKeyContent get parsedSecretStorageKeyContent => @@ -42,9 +41,9 @@ class SecretStorageKeyContent { : passphrase = json['passphrase'] is Map ? PassphraseInfo.fromJson(json['passphrase']) : null, - iv = json.tryGet('iv'), - mac = json.tryGet('mac'), - algorithm = json.tryGet('algorithm'); + iv = json.tryGet('iv'), + mac = json.tryGet('mac'), + algorithm = json.tryGet('algorithm'); Map toJson() { final data = {}; @@ -57,24 +56,30 @@ class SecretStorageKeyContent { } class PassphraseInfo { - String algorithm; - String salt; - int iterations; + //TODO: algorithm, salt, iterations are required by spec, + //TODO: we should require it here and make sure to catch it everywhere + String? algorithm; + String? salt; + int? iterations; int? bits; - PassphraseInfo(); + PassphraseInfo( + {required this.algorithm, + required this.salt, + required this.iterations, + this.bits}); PassphraseInfo.fromJson(Map json) - : algorithm = json.tryGet('algorithm'), - salt = json.tryGet('salt'), - iterations = json.tryGet('iterations'), + : algorithm = json.tryGet('algorithm'), + salt = json.tryGet('salt'), + iterations = json.tryGet('iterations'), bits = json.tryGet('bits'); Map toJson() { final data = {}; - if (algorithm != null) data['algorithm'] = algorithm; - if (salt != null) data['salt'] = salt; - if (iterations != null) data['iterations'] = iterations; + data['algorithm'] = algorithm; + data['salt'] = salt; + data['iterations'] = iterations; if (bits != null) data['bits'] = bits; return data; } diff --git a/lib/src/model/events/tombstone_content.dart b/lib/src/model/events/tombstone_content.dart index 93a8221f..18804448 100644 --- a/lib/src/model/events/tombstone_content.dart +++ b/lib/src/model/events/tombstone_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,8 +21,8 @@ * SOFTWARE. */ -import '../basic_event.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; extension TombstoneContentBasicEventExtension on BasicEvent { TombstoneContent get parsedTombstoneContent => @@ -35,8 +34,8 @@ class TombstoneContent { String replacementRoom; TombstoneContent.fromJson(Map json) - : body = json.tryGet('body', ''), - replacementRoom = json.tryGet('replacement_room', ''); + : body = json.tryGet('body') ?? '', + replacementRoom = json.tryGet('replacement_room') ?? ''; Map toJson() { final data = {}; diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart index a93ee5b3..2f35ac74 100644 --- a/lib/src/model/events_sync_update.dart +++ b/lib/src/model/events_sync_update.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/matrix_connection_exception.dart b/lib/src/model/matrix_connection_exception.dart index 96d12af9..97194f64 100644 --- a/lib/src/model/matrix_connection_exception.dart +++ b/lib/src/model/matrix_connection_exception.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -25,6 +24,7 @@ class MatrixConnectionException implements Exception { final dynamic original; final StackTrace stackTrace; + MatrixConnectionException(this.original, this.stackTrace); @override diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index b54856db..516f4b35 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,18 +21,33 @@ * SOFTWARE. */ -import 'stripped_state_event.dart'; import '../utils/map_copy_extension.dart'; +import 'stripped_state_event.dart'; class MatrixEvent extends StrippedStateEvent { String eventId; String? roomId; - late DateTime originServerTs; + DateTime originServerTs; Map? unsigned; Map? prevContent; String? redacts; - MatrixEvent(); + MatrixEvent({ + required String type, + required Map content, + required String senderId, + String? stateKey, + required this.eventId, + this.roomId, + required this.originServerTs, + this.unsigned, + this.prevContent, + this.redacts, + }) : super( + type: type, + content: content, + senderId: senderId, + stateKey: stateKey); MatrixEvent.fromJson(Map json) : eventId = json['event_id'], diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index f2a03e24..3e7ef751 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -62,7 +61,9 @@ class MatrixException implements Exception { /// The frozen request which triggered this Error http.Response? response; - MatrixException(Response this.response) : raw = json.decode(response.body); + MatrixException(http.Response this.response) + : raw = json.decode(response.body); + MatrixException.fromJson(Map content) : raw = content; @override @@ -87,7 +88,7 @@ class MatrixException implements Exception { /// For each endpoint, a server offers one or more 'flows' that the client can use /// to authenticate itself. Each flow comprises a series of stages. If this request /// doesn't need additional authentication, then this is null. - List?/*?*/ get authenticationFlows { + List? get authenticationFlows { if (!raw.containsKey('flows') || !(raw['flows'] is List)) return null; return (raw['flows'] as List) .map((flow) => flow['stages']) @@ -110,5 +111,6 @@ class MatrixException implements Exception { /// to authenticate itself. Each flow comprises a series of stages class AuthenticationFlow { final List stages; + const AuthenticationFlow(this.stages); } diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index 2ad89ed1..01c0538a 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -24,15 +23,16 @@ import '../utils/map_copy_extension.dart'; -class MatrixSignableKey { +abstract class MatrixSignableKey { String userId; - String? identifier; + + String? get identifier; + Map keys; Map>? signatures; Map? unsigned; - MatrixSignableKey(this.userId, this.identifier, this.keys, this.signatures, - {this.unsigned}); + MatrixSignableKey(this.userId, this.keys, this.signatures, {this.unsigned}); // This object is used for signing so we need the raw json too Map? _json; @@ -65,6 +65,7 @@ class MatrixSignableKey { class MatrixCrossSigningKey extends MatrixSignableKey { List usage; + String? get publicKey => identifier; MatrixCrossSigningKey( @@ -73,14 +74,15 @@ class MatrixCrossSigningKey extends MatrixSignableKey { Map keys, Map> signatures, { Map? unsigned, - }) : super(userId, keys?.values?.first, keys, signatures, unsigned: unsigned); + }) : super(userId, keys, signatures, unsigned: unsigned); + + @override + String? get identifier => keys.values.first; @override MatrixCrossSigningKey.fromJson(Map json) - : super.fromJson(json) { - usage = List.from(json['usage']); - identifier = keys?.values?.first; - } + : usage = List.from(json['usage']), + super.fromJson(json); @override Map toJson() { @@ -91,25 +93,29 @@ class MatrixCrossSigningKey extends MatrixSignableKey { } class MatrixDeviceKeys extends MatrixSignableKey { - String get deviceId => identifier!; + String deviceId; List algorithms; + String? get deviceDisplayName => unsigned != null ? unsigned!['device_display_name'] : null; MatrixDeviceKeys( String userId, - String deviceId, + this.deviceId, this.algorithms, Map keys, Map> signatures, { Map? unsigned, - }) : super(userId, deviceId, keys, signatures, unsigned: unsigned); + }) : super(userId, keys, signatures, unsigned: unsigned); @override - MatrixDeviceKeys.fromJson(Map json) : super.fromJson(json) { - identifier = json['device_id']; - algorithms = json['algorithms'].cast(); - } + String? get identifier => deviceId; + + @override + MatrixDeviceKeys.fromJson(Map json) + : algorithms = json['algorithms'].cast(), + deviceId = json['device_id'], + super.fromJson(json); @override Map toJson() { diff --git a/lib/src/model/message_types.dart b/lib/src/model/message_types.dart index e6cbc443..d6745350 100644 --- a/lib/src/model/message_types.dart +++ b/lib/src/model/message_types.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index 4874ea54..73848c2e 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index 0df3f0c2..edf9a1de 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart index 46f24e5c..4be5d726 100644 --- a/lib/src/model/request_token_response.dart +++ b/lib/src/model/request_token_response.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/room_creation_types.dart b/lib/src/model/room_creation_types.dart index be7b75d9..703f0ce1 100644 --- a/lib/src/model/room_creation_types.dart +++ b/lib/src/model/room_creation_types.dart @@ -1,4 +1,3 @@ - abstract class RoomCreationTypes { static const String mSpace = 'm.space'; } diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart index b285c454..39df80b4 100644 --- a/lib/src/model/room_keys_keys.dart +++ b/lib/src/model/room_keys_keys.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -53,9 +52,7 @@ class RoomKeysSingleKey { class RoomKeysRoom { Map sessions; - RoomKeysRoom({required this.sessions}) { - sessions ??= {}; - } + RoomKeysRoom({required this.sessions}); RoomKeysRoom.fromJson(Map json) : sessions = (json['sessions'] as Map) diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index 74dded00..1947d829 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -26,6 +25,7 @@ class RoomSummary { List? mHeroes; int? mJoinedMemberCount; int? mInvitedMemberCount; + RoomSummary.fromJson(Map json) : mHeroes = json['m.heroes'] != null ? List.from(json['m.heroes']) diff --git a/lib/src/model/room_types.dart b/lib/src/model/room_types.dart index 7dbcf0f5..ba551ae9 100644 --- a/lib/src/model/room_types.dart +++ b/lib/src/model/room_types.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index cb8f914d..20bd4927 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -27,7 +26,13 @@ import 'basic_event_with_sender.dart'; class StrippedStateEvent extends BasicEventWithSender { String? stateKey; - StrippedStateEvent(); + StrippedStateEvent( + {required String type, + required Map content, + required String senderId, + this.stateKey}) + : super(type: type, content: content, senderId: senderId); + StrippedStateEvent.fromJson(Map json) : stateKey = json['state_key'], super.fromJson(json); diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart index 32cba75c..0f1fcf50 100644 --- a/lib/src/model/supported_protocol.dart +++ b/lib/src/model/supported_protocol.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -45,9 +44,7 @@ class SupportedProtocol { data['location_fields'] = locationFields; data['icon'] = icon; data['field_types'] = fieldTypes.map((k, v) => MapEntry(k, v.toJson())); - data['instances'] = instances.map((v) => v.toJson()).toList(); - return data; } } @@ -56,10 +53,9 @@ class ProtocolFieldType { String regexp; String placeholder; - ProtocolFieldType.fromJson(Map json) { - regexp = json['regexp']; - placeholder = json['placeholder']; - } + ProtocolFieldType.fromJson(Map json) + : regexp = json['regexp'], + placeholder = json['placeholder']; Map toJson() { final data = {}; @@ -75,12 +71,11 @@ class ProtocolInstance { String? icon; dynamic fields; - ProtocolInstance.fromJson(Map json) { - networkId = json['network_id']; - desc = json['desc']; - icon = json['icon']; - fields = json['fields']; - } + ProtocolInstance.fromJson(Map json) + : networkId = json['network_id'], + desc = json['desc'], + icon = json['icon'], + fields = json['fields']; Map toJson() { final data = {}; diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index 5b93d1ef..878b9343 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -40,7 +39,7 @@ class SyncUpdate { Map? deviceOneTimeKeysCount; List? deviceUnusedFallbackKeyTypes; - SyncUpdate(); + SyncUpdate({required this.nextBatch}); SyncUpdate.fromJson(Map json) : nextBatch = json['next_batch'], @@ -136,6 +135,7 @@ class RoomsUpdate { .map((k, v) => MapEntry(k, LeftRoomUpdate.fromJson(v))) : null; } + Map toJson() { final data = {}; if (join != null) { @@ -224,6 +224,7 @@ class JoinedRoomUpdate extends SyncRoomUpdate { class InvitedRoomUpdate extends SyncRoomUpdate { List? inviteState; + InvitedRoomUpdate.fromJson(Map json) { inviteState = (json['invite_state'] != null && json['invite_state']['events'] != null) @@ -232,6 +233,7 @@ class InvitedRoomUpdate extends SyncRoomUpdate { .toList() : null; } + Map toJson() { final data = {}; if (inviteState != null) { @@ -266,6 +268,7 @@ class LeftRoomUpdate extends SyncRoomUpdate { .toList() : null; } + Map toJson() { final data = {}; if (state != null) { @@ -318,10 +321,12 @@ class TimelineUpdate { class UnreadNotificationCounts { int? highlightCount; int? notificationCount; + UnreadNotificationCounts.fromJson(Map json) { highlightCount = json['highlight_count']; notificationCount = json['notification_count']; } + Map toJson() { final data = {}; if (highlightCount != null) { @@ -337,10 +342,12 @@ class UnreadNotificationCounts { class DeviceListsUpdate { List? changed; List? left; + DeviceListsUpdate.fromJson(Map json) { changed = List.from(json['changed'] ?? []); left = List.from(json['left'] ?? []); } + Map toJson() { final data = {}; if (changed != null) { diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart index fb834daf..a2271f9b 100644 --- a/lib/src/model/third_party_location.dart +++ b/lib/src/model/third_party_location.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart index e230e4ab..a4289b2a 100644 --- a/lib/src/model/third_party_user.dart +++ b/lib/src/model/third_party_user.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/model/upload_key_signatures_response.dart b/lib/src/model/upload_key_signatures_response.dart index 94f3255f..38bf3774 100644 --- a/lib/src/model/upload_key_signatures_response.dart +++ b/lib/src/model/upload_key_signatures_response.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index 105319a3..37852945 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart index d2b89720..2cf95989 100644 --- a/lib/src/utils/map_copy_extension.dart +++ b/lib/src/utils/map_copy_extension.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index 0024aa12..d768a24d 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -25,60 +24,45 @@ import 'logs.dart'; extension TryGetMapExtension on Map { - T tryGet(String key, [T fallbackValue]) { + T? tryGet(String key) { final value = this[key]; if (value != null && !(value is T)) { Logs().w( 'Expected "${T.runtimeType}" in event content for the Key "$key" but got "${value.runtimeType}".'); - return fallbackValue; - } - if (value == null && fallbackValue != null) { - Logs().w( - 'Required field in event content for the Key "$key" is null. Set to "$fallbackValue".'); - return fallbackValue; + return null; } return value; } - List tryGetList(String key, [List fallbackValue]) { + List? tryGetList(String key) { final value = this[key]; if (value != null && !(value is List)) { Logs().w( 'Expected "List<${T.runtimeType}>" in event content for the key "$key" but got "${value.runtimeType}".'); - return fallbackValue; - } - if (value == null && fallbackValue != null) { - Logs().w( - 'Required field in event content for the key "$key" is null. Set to "$fallbackValue".'); - return fallbackValue; + return null; } try { return (value as List).cast(); } catch (_) { Logs().w( 'Unable to create "List<${T.runtimeType}>" in event content for the key "$key"'); - return fallbackValue; + return null; } } - Map tryGetMap(String key, [Map fallbackValue]) { + Map? tryGetMap(String key) { final value = this[key]; if (value != null && !(value is Map)) { Logs().w( 'Expected "Map<${A.runtimeType},${B.runtimeType}>" in event content for the key "$key" but got "${value.runtimeType}".'); - return fallbackValue; - } - if (value == null && fallbackValue != null) { - Logs().w( - 'Required field in event content for the key "$key" is null. Set to "$fallbackValue".'); - return fallbackValue; + return null; } try { return (value as Map).cast(); } catch (_) { Logs().w( 'Unable to create "Map<${A.runtimeType},${B.runtimeType}>" in event content for the key "$key"'); - return fallbackValue; + return null; } } } diff --git a/lib/src/values.dart b/lib/src/values.dart index b7f1c0c5..aa4f66ac 100644 --- a/lib/src/values.dart +++ b/lib/src/values.dart @@ -14,6 +14,7 @@ class TagType { static final favourite = 'm.favourite'; static final lowPriority = 'm.lowpriority'; static final serverNotice = 'm.server_notice'; + static bool isValid(String tag) => tag.startsWith('m.') ? [favourite, lowPriority, serverNotice].contains(tag) : true; diff --git a/test/event_content_test.dart b/test/event_content_test.dart index d7f79670..82099ac7 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH @@ -22,9 +21,10 @@ * SOFTWARE. */ +import 'dart:convert'; + import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; -import 'dart:convert'; void main() { group('Event Content tests', () { diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart index f67b60fc..329771d9 100644 --- a/test/map_copy_extension_test.dart +++ b/test/map_copy_extension_test.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 97b454e4..54a8f0a8 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1,18 +1,17 @@ - /* MIT License -* +* * Copyright (C) 2019, 2020, 2021 Famedly GmbH -* +* * 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 @@ -23,6 +22,7 @@ */ import 'dart:typed_data'; + import 'package:matrix_api_lite/fake_matrix_api.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; @@ -60,8 +60,8 @@ void main() { 'session': 'xxxxxxyz', 'completed': ['example.type.foo'] }); - expect( - exception.authenticationFlows!.first.stages.first, 'example.type.foo'); + expect(exception.authenticationFlows!.first.stages.first, + 'example.type.foo'); expect(exception.authenticationParams!['example.type.baz'], {'example_key': 'foobar'}); expect(exception.session, 'xxxxxxyz'); @@ -111,10 +111,8 @@ void main() { expect((exception as MatrixException).errcode, 'M_FORBIDDEN'); expect(exception.error, MatrixError.M_FORBIDDEN); expect(exception.errorMessage, 'Blabla'); - expect(exception.requireAdditionalAuthentication, - false); - expect( - exception.toString(), 'M_FORBIDDEN: Blabla'); + expect(exception.requireAdditionalAuthentication, false); + expect(exception.toString(), 'M_FORBIDDEN: Blabla'); error = true; } expect(error, true); @@ -146,10 +144,10 @@ void main() { }); test('getLoginTypes', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final loginTypes = await (matrixApi.getLoginFlows() as FutureOr>); - expect(loginTypes.first.type, 'm.login.password'); + final loginTypes = await matrixApi.getLoginFlows(); + expect(loginTypes?.first.type, 'm.login.password'); expect(FakeMatrixApi.api['GET']!['/client/r0/login']({}), - {'flows': loginTypes.map((x) => x.toJson()).toList()}); + {'flows': loginTypes?.map((x) => x.toJson()).toList()}); matrixApi.homeserver = null; }); test('login', () async { @@ -194,8 +192,8 @@ void main() { idAccessToken: '1234', ); expect( - FakeMatrixApi.api['POST']! - ['/client/r0/register/email/requestToken']({}), + FakeMatrixApi + .api['POST']!['/client/r0/register/email/requestToken']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -212,8 +210,8 @@ void main() { idAccessToken: '1234', ); expect( - FakeMatrixApi.api['POST']! - ['/client/r0/register/email/requestToken']({}), + FakeMatrixApi + .api['POST']!['/client/r0/register/email/requestToken']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -281,9 +279,9 @@ void main() { test('getThirdPartyIdentifiers', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await (matrixApi.getAccount3PIDs() as FutureOr>); + final response = await matrixApi.getAccount3PIDs(); expect(FakeMatrixApi.api['GET']!['/client/r0/account/3pid']({}), - {'threepids': response.map((t) => t.toJson()).toList()}); + {'threepids': response?.map((t) => t.toJson()).toList()}); matrixApi.homeserver = matrixApi.accessToken = null; }); test('addThirdPartyIdentifier', () async { @@ -537,13 +535,13 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final states = await (matrixApi.getMembersByRoom( + final states = await matrixApi.getMembersByRoom( '!localpart:server.abc', at: '1234', membership: Membership.join, notMembership: Membership.leave, - ) as FutureOr>); - expect(states.length, 1); + ); + expect(states?.length, 1); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -551,11 +549,11 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final states = await (matrixApi.getJoinedMembersByRoom( + final states = await matrixApi.getJoinedMembersByRoom( '!localpart:server.abc', - ) as FutureOr>); - expect(states.length, 1); - expect(states['@bar:example.com']!.toJson(), { + ); + expect(states?.length, 1); + expect(states?['@bar:example.com']?.toJson(), { 'display_name': 'Bar', 'avatar_url': 'mxc://riot.ovh/printErCATzZijQsSDWorRaK' }); @@ -667,8 +665,8 @@ void main() { ); expect( - FakeMatrixApi.api['GET']! - ['/client/r0/directory/room/%23testalias%3Aexample.com']({}), + FakeMatrixApi.api['GET']![ + '/client/r0/directory/room/%23testalias%3Aexample.com']({}), roomAliasInformation.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -851,8 +849,8 @@ void main() { ); expect( - FakeMatrixApi.api['POST']! - ['/client/r0/publicRooms?server=example.com']({}), + FakeMatrixApi + .api['POST']!['/client/r0/publicRooms?server=example.com']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -913,8 +911,8 @@ void main() { final response = await matrixApi.getUserProfile('@alice:example.com'); expect( - FakeMatrixApi.api['GET']! - ['/client/r0/profile/%40alice%3Aexample.com']({}), + FakeMatrixApi + .api['GET']!['/client/r0/profile/%40alice%3Aexample.com']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1017,8 +1015,8 @@ void main() { ts: 10, ); expect( - FakeMatrixApi.api['GET']! - ['/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']({}), + FakeMatrixApi.api['GET']![ + '/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']({}), openGraphData.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1048,9 +1046,9 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final devices = await (matrixApi.getDevices() as FutureOr>); + final devices = await matrixApi.getDevices(); expect(FakeMatrixApi.api['GET']!['/client/r0/devices']({})['devices'], - devices.map((i) => i.toJson()).toList()); + devices?.map((i) => i.toJson()).toList()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1117,12 +1115,12 @@ void main() { token: '1234', ); expect( - response - .deviceKeys!['@alice:example.com']!['JLAFKJWSCS']!.deviceDisplayName, + response.deviceKeys!['@alice:example.com']!['JLAFKJWSCS']! + .deviceDisplayName, 'Alices mobile phone'); expect( - FakeMatrixApi.api['POST']! - ['/client/r0/keys/query']({'device_keys': {}}), + FakeMatrixApi + .api['POST']!['/client/r0/keys/query']({'device_keys': {}}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1242,10 +1240,10 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await (matrixApi.getPushers() as FutureOr>); + final response = await matrixApi.getPushers(); expect( FakeMatrixApi.api['GET']!['/client/r0/pushers']({}), - {'pushers': response.map((i) => i.toJson()).toList()}, + {'pushers': response?.map((i) => i.toJson()).toList()}, ); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1281,8 +1279,8 @@ void main() { only: '1234', ); expect( - FakeMatrixApi.api['GET']! - ['/client/r0/notifications?from=1234&limit=10&only=1234']({}), + FakeMatrixApi.api['GET']![ + '/client/r0/notifications?from=1234&limit=10&only=1234']({}), response.toJson(), ); @@ -1307,8 +1305,8 @@ void main() { final response = await matrixApi.getPushRule('global', PushRuleKind.content, 'nocake'); expect( - FakeMatrixApi.api['GET']! - ['/client/r0/pushrules/global/content/nocake']({}), + FakeMatrixApi + .api['GET']!['/client/r0/pushrules/global/content/nocake']({}), response.toJson(), ); @@ -1407,8 +1405,8 @@ void main() { final response = await matrixApi.getEvents(from: '1234', roomId: '!1234', timeout: 10); expect( - FakeMatrixApi.api['GET']! - ['/client/r0/events?from=1234&timeout=10&roomId=%211234']({}), + FakeMatrixApi.api['GET']![ + '/client/r0/events?from=1234&timeout=10&roomId=%211234']({}), response.toJson(), ); @@ -1418,12 +1416,12 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await (matrixApi.getRoomTags( - '@alice:example.com', '!localpart:example.com') as FutureOr>); + final response = await matrixApi.getRoomTags( + '@alice:example.com', '!localpart:example.com'); expect( FakeMatrixApi.api['GET']![ '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']({}), - {'tags': response.map((k, v) => MapEntry(k, v.toJson()))}, + {'tags': response?.map((k, v) => MapEntry(k, v.toJson()))}, ); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1507,8 +1505,8 @@ void main() { final response = await matrixApi.getWhoIs('@alice:example.com'); expect( - FakeMatrixApi.api['GET']! - ['/client/r0/admin/whois/%40alice%3Aexample.com']({}), + FakeMatrixApi + .api['GET']!['/client/r0/admin/whois/%40alice%3Aexample.com']({}), response.toJson(), ); @@ -1521,8 +1519,8 @@ void main() { final response = await matrixApi.getEventContext('1234', '1234', limit: 10, filter: '{}'); expect( - FakeMatrixApi.api['GET']! - ['/client/r0/rooms/1234/context/1234?limit=10&filter=%7B%7D']({}), + FakeMatrixApi.api['GET']![ + '/client/r0/rooms/1234/context/1234?limit=10&filter=%7B%7D']({}), response.toJson(), ); @@ -1596,8 +1594,8 @@ void main() { final response = await matrixApi.requestThirdPartyLocationsByAlias('1234'); expect( - FakeMatrixApi.api['GET']! - ['/client/r0/thirdparty/location?alias=1234']({}), + FakeMatrixApi + .api['GET']!['/client/r0/thirdparty/location?alias=1234']({}), response.map((i) => i.toJson()).toList(), ); @@ -1621,8 +1619,8 @@ void main() { final response = await matrixApi.requestOpenIdToken('1234', {}); expect( - FakeMatrixApi.api['POST']! - ['/client/r0/user/1234/openid/request_token']({}), + FakeMatrixApi + .api['POST']!['/client/r0/user/1234/openid/request_token']({}), response.toJson(), ); @@ -1647,8 +1645,8 @@ void main() { }; final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); expect( - FakeMatrixApi.api['POST']! - ['/client/unstable/room_keys/version']({})['version'], + FakeMatrixApi.api['POST']!['/client/unstable/room_keys/version']( + {})['version'], ret); }); test('getRoomKeysVersionCurrent', () async { @@ -1656,7 +1654,8 @@ void main() { matrixApi.accessToken = '1234'; final ret = await matrixApi.getRoomKeysVersionCurrent(); - expect(FakeMatrixApi.api['GET']!['/client/unstable/room_keys/version']({}), + expect( + FakeMatrixApi.api['GET']!['/client/unstable/room_keys/version']({}), ret.toJson()); }); test('putRoomKeysVersion', () async { @@ -1801,8 +1800,8 @@ void main() { }); final ret = await matrixApi.postRoomKeysKey('5', session); expect( - FakeMatrixApi.api['PUT']! - ['/client/unstable/room_keys/keys?version=5']({}), + FakeMatrixApi + .api['PUT']!['/client/unstable/room_keys/keys?version=5']({}), ret.toJson()); }); test('getRoomKeys', () async { @@ -1811,8 +1810,8 @@ void main() { final ret = await matrixApi.getRoomKeys('5'); expect( - FakeMatrixApi.api['GET']! - ['/client/unstable/room_keys/keys?version=5']({}), + FakeMatrixApi + .api['GET']!['/client/unstable/room_keys/keys?version=5']({}), ret.toJson()); }); test('deleteRoomKeys', () async { @@ -1821,8 +1820,8 @@ void main() { final ret = await matrixApi.deleteRoomKeys('5'); expect( - FakeMatrixApi.api['DELETE']! - ['/client/unstable/room_keys/keys?version=5']({}), + FakeMatrixApi + .api['DELETE']!['/client/unstable/room_keys/keys?version=5']({}), ret.toJson()); }); test('AuthenticationData', () { diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index 43317512..d38a1e68 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -1,4 +1,3 @@ - /* MIT License * * Copyright (C) 2019, 2020, 2021 Famedly GmbH From 34b9cc0dcf11e2e2981489c5d077b4bcbf840abc Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Thu, 1 Jul 2021 17:15:06 +0200 Subject: [PATCH 067/174] filter out invalid CiphertextInfo instead of crashing --- .../model/events/room_encrypted_content.dart | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index e062f77f..e124d3ca 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -31,6 +31,14 @@ extension RoomEncryptedContentBasicEventExtension on BasicEvent { RoomEncryptedContent.fromJson(content); } +/// Convert Nullable iterable of MapEntries to Map +extension ToMap on Iterable>? { + Map? toMap() { + final that = this; + return that != null ? Map.fromEntries(that) : null; + } +} + class RoomEncryptedContent { String algorithm; String senderKey; @@ -45,9 +53,19 @@ class RoomEncryptedContent { deviceId = json.tryGet('device_id'), sessionId = json.tryGet('session_id'), ciphertextMegolm = json.tryGet('ciphertext'), + // filter out invalid/incomplete CiphertextInfos ciphertextOlm = json .tryGet>('ciphertext') - ?.map((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))); + ?.entries + .map((e) { + try { + return MapEntry(e.key, CiphertextInfo.fromJson(e.value)); + } catch (_) { + return null; + } + }) + .whereType>() + .toMap(); Map toJson() { final data = {}; From 92a2bd9d7eca67633de5d1ac7b299fc7b032f9ff Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Thu, 1 Jul 2021 17:36:21 +0200 Subject: [PATCH 068/174] null safety test fixes --- lib/fake_matrix_api.dart | 4 +++- lib/src/model/auth/authentication_data.dart | 2 +- lib/src/model/events/room_encrypted_content.dart | 4 ++-- lib/src/utils/try_get_map_extension.dart | 16 ++++++++++++++-- test/matrix_api_test.dart | 6 ++---- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index f0f2d16d..1ca54f5b 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1979,7 +1979,9 @@ class FakeMatrixApi extends MockClient { {'user_id': '@testuser:example.com'}, '/client/r0/register?kind=guest': (var req) => {'user_id': '@testuser:example.com'}, - '/client/r0/rooms/1234/upgrade': (var req) => {}, + '/client/r0/rooms/1234/upgrade': (var req) => { + 'replacement_room': '!1234:fakeServer.notExisting', + }, '/client/r0/user/1234/openid/request_token': (var req) => { 'access_token': 'SomeT0kenHere', 'token_type': 'Bearer', diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 53ea3ecf..3a561798 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -23,7 +23,7 @@ class AuthenticationData { String type; - String? /*?*/ /*?*/ session; + String? session; AuthenticationData({required this.type, this.session}); diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index e124d3ca..911b755e 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -52,10 +52,10 @@ class RoomEncryptedContent { senderKey = json.tryGet('sender_key') ?? '', deviceId = json.tryGet('device_id'), sessionId = json.tryGet('session_id'), - ciphertextMegolm = json.tryGet('ciphertext'), + ciphertextMegolm = json.silentTryGet('ciphertext'), // filter out invalid/incomplete CiphertextInfos ciphertextOlm = json - .tryGet>('ciphertext') + .silentTryGet>('ciphertext') ?.entries .map((e) { try { diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index d768a24d..fe6a9d4d 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -28,7 +28,18 @@ extension TryGetMapExtension on Map { final value = this[key]; if (value != null && !(value is T)) { Logs().w( - 'Expected "${T.runtimeType}" in event content for the Key "$key" but got "${value.runtimeType}".'); + 'Expected "${T.runtimeType}" in event content for the Key "$key" but got "${value.runtimeType}".', + StackTrace.current); + return null; + } + return value; + } + + /// Same as tryGet but without logging any warnings. + /// This is helpful if you have a field that can mean multiple things on purpose. + T? silentTryGet(String key) { + final value = this[key]; + if (value != null && !(value is T)) { return null; } return value; @@ -38,7 +49,8 @@ extension TryGetMapExtension on Map { final value = this[key]; if (value != null && !(value is List)) { Logs().w( - 'Expected "List<${T.runtimeType}>" in event content for the key "$key" but got "${value.runtimeType}".'); + 'Expected "List<${T.runtimeType}>" in event content for the key "$key" but got "${value.runtimeType}".', + StackTrace.current); return null; } try { diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 54a8f0a8..064cef97 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1072,8 +1072,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.deleteDevice('QBUAZIFURK', - auth: AuthenticationData.fromJson({})); + await matrixApi.deleteDevice('QBUAZIFURK'); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1081,8 +1080,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi - .deleteDevices(['QBUAZIFURK'], auth: AuthenticationData.fromJson({})); + await matrixApi.deleteDevices(['QBUAZIFURK']); matrixApi.homeserver = matrixApi.accessToken = null; }); From f5dbacfe07ddf388ba27c63ea9dc115a91991a4b Mon Sep 17 00:00:00 2001 From: Marcus Date: Thu, 1 Jul 2021 15:50:42 +0000 Subject: [PATCH 069/174] remove leftover migration tool comment --- lib/src/model/auth/authentication_three_pid_creds.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 8a20d904..2754b310 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -65,7 +65,7 @@ class AuthenticationThreePidCreds extends AuthenticationData { } class ThreepidCreds { - String /*!*/ sid; ++ String sid; String clientSecret; String idServer; String idAccessToken; From dd7a824512b92117d74b76bc0da84a7406c6270c Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Thu, 1 Jul 2021 18:01:07 +0200 Subject: [PATCH 070/174] remove user field from AuthenticationPassword structure it's not in the spec --- lib/src/model/auth/authentication_password.dart | 10 ++-------- lib/src/model/auth/authentication_three_pid_creds.dart | 2 +- test/matrix_api_test.dart | 3 --- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index 2b5cb13a..b47a17be 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -27,7 +27,6 @@ import 'authentication_types.dart'; import 'authentication_user_identifier.dart'; class AuthenticationPassword extends AuthenticationData { - String? user; String password; /// You may want to cast this as [AuthenticationUserIdentifier] or other @@ -35,25 +34,20 @@ class AuthenticationPassword extends AuthenticationData { AuthenticationIdentifier identifier; AuthenticationPassword( - {String? session, - required this.password, - this.user, - required this.identifier}) + {String? session, required this.password, required this.identifier}) : super( type: AuthenticationTypes.password, session: session, ); AuthenticationPassword.fromJson(Map json) - : user = json['user'], - password = json['password'], + : password = json['password'], identifier = AuthenticationIdentifier.subFromJson(json['identifier']), super.fromJson(json); @override Map toJson() { final data = super.toJson(); - if (user != null) data['user'] = user; data['password'] = password; data['identifier'] = identifier.toJson(); return data; diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 2754b310..1df86aab 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -65,7 +65,7 @@ class AuthenticationThreePidCreds extends AuthenticationData { } class ThreepidCreds { -+ String sid; + String sid; String clientSecret; String idServer; String idAccessToken; diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 064cef97..aa88acd1 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1905,7 +1905,6 @@ void main() { AuthenticationPassword( session: '1', password: 'a', - user: 'a', identifier: AuthenticationUserIdentifier(user: 'a'), ).toJson(), json); @@ -1919,7 +1918,6 @@ void main() { AuthenticationPassword( session: '1', password: 'a', - user: 'a', identifier: AuthenticationThirdPartyIdentifier(medium: 'a', address: 'a'), ).toJson(), @@ -1934,7 +1932,6 @@ void main() { AuthenticationPassword( session: '1', password: 'a', - user: 'a', identifier: AuthenticationPhoneIdentifier(country: 'a', phone: 'a'), ).toJson(), json); From faabc55d28faf7f94ec8afcc4e9de36e384cfa44 Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Thu, 1 Jul 2021 18:05:56 +0200 Subject: [PATCH 071/174] isServer and isAccessToken are optional --- .../model/auth/authentication_three_pid_creds.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 1df86aab..292646a4 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -67,14 +67,14 @@ class AuthenticationThreePidCreds extends AuthenticationData { class ThreepidCreds { String sid; String clientSecret; - String idServer; - String idAccessToken; + String? idServer; + String? idAccessToken; ThreepidCreds( {required this.sid, required this.clientSecret, - required this.idServer, - required this.idAccessToken}); + this.idServer, + this.idAccessToken}); ThreepidCreds.fromJson(Map json) : sid = json['sid'], @@ -86,8 +86,8 @@ class ThreepidCreds { final data = {}; data['sid'] = sid; data['client_secret'] = clientSecret; - data['id_server'] = idServer; - data['id_access_token'] = idAccessToken; + if (idServer != null) data['id_server'] = idServer; + if (idAccessToken != null) data['id_access_token'] = idAccessToken; return data; } } From 4026f480fb8836551e3fdd43f8d11b4d35ff5590 Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Thu, 1 Jul 2021 18:16:47 +0200 Subject: [PATCH 072/174] fix test after removing user field --- test/matrix_api_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index aa88acd1..1ca519da 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1898,7 +1898,6 @@ void main() { 'identifier': {'type': 'm.id.user', 'user': 'a'}, 'password': 'a', 'session': '1', - 'user': 'a', }; expect(AuthenticationPassword.fromJson(json).toJson(), json); expect( From 0d1e7bdf7be1c9ed4051e49993434e5301a36ca6 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Fri, 2 Jul 2021 11:11:29 +0200 Subject: [PATCH 073/174] omit type in tryGet --- lib/src/model/events/room_key_request_content.dart | 8 ++++---- .../model/events/secret_storage_default_key_content.dart | 2 +- lib/src/model/events/secret_storage_key_content.dart | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index 394d8233..e03deed3 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -37,10 +37,10 @@ class RoomKeyRequestContent { RoomKeyRequestContent.fromJson(Map json) : body = ((x) => x != null ? RequestedKeyInfo.fromJson(x) : null)( - json.tryGet>('body')), - action = json.tryGet('action') ?? '', - requestingDeviceId = json.tryGet('requesting_device_id') ?? '', - requestId = json.tryGet('request_id') ?? ''; + json.tryGet('body')), + action = json.tryGet('action') ?? '', + requestingDeviceId = json.tryGet('requesting_device_id') ?? '', + requestId = json.tryGet('request_id') ?? ''; Map toJson() { final data = {}; diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/src/model/events/secret_storage_default_key_content.dart index 46394fbf..470538d4 100644 --- a/lib/src/model/events/secret_storage_default_key_content.dart +++ b/lib/src/model/events/secret_storage_default_key_content.dart @@ -36,7 +36,7 @@ class SecretStorageDefaultKeyContent { SecretStorageDefaultKeyContent({required this.key}); SecretStorageDefaultKeyContent.fromJson(Map json) - : key = json.tryGet('key'); + : key = json.tryGet('key'); Map toJson() { final data = {}; diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index b6542bac..a10b3a06 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -73,7 +73,7 @@ class PassphraseInfo { : algorithm = json.tryGet('algorithm'), salt = json.tryGet('salt'), iterations = json.tryGet('iterations'), - bits = json.tryGet('bits'); + bits = json.tryGet('bits'); Map toJson() { final data = {}; From bf3bed9ef9ebf2f4751778368f6a0d5b8a8a2120 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Fri, 2 Jul 2021 11:18:16 +0200 Subject: [PATCH 074/174] simpler toMap --- lib/src/model/events/room_encrypted_content.dart | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 911b755e..b53c561c 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -32,11 +32,8 @@ extension RoomEncryptedContentBasicEventExtension on BasicEvent { } /// Convert Nullable iterable of MapEntries to Map -extension ToMap on Iterable>? { - Map? toMap() { - final that = this; - return that != null ? Map.fromEntries(that) : null; - } +extension ToMap on Iterable> { + Map toMap() => Map.fromEntries(this); } class RoomEncryptedContent { From c73ea67bcd127bcbb03621dc11fe102446358b06 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Fri, 2 Jul 2021 11:36:42 +0200 Subject: [PATCH 075/174] add note about txnId --- lib/src/model/auth/authentication_token.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index 13749069..fd9c18cd 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -26,6 +26,8 @@ import 'authentication_types.dart'; class AuthenticationToken extends AuthenticationData { String token; + + /// removed in the unstable version of the spec String? txnId; AuthenticationToken({String? session, required this.token, this.txnId}) From 0b8e3f3071ebcb3b209620cd45ca56bbfbf41e49 Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Fri, 2 Jul 2021 12:17:05 +0200 Subject: [PATCH 076/174] make tryGet* safer * check casts (for list and map) at cast time by recreating the list/map instead of throwing on access. * type warnings work now slightly differently: * when we expect nullable fields to be actually null within normal operation you can explicitly set the tryGet type param to an optional type and mute the warning. Otherwise it'll warn that something is null which we expect to something else. --- .../model/events/room_encrypted_content.dart | 4 +- lib/src/utils/try_get_map_extension.dart | 41 ++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index b53c561c..060c328e 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -47,8 +47,8 @@ class RoomEncryptedContent { RoomEncryptedContent.fromJson(Map json) : algorithm = json.tryGet('algorithm') ?? '', senderKey = json.tryGet('sender_key') ?? '', - deviceId = json.tryGet('device_id'), - sessionId = json.tryGet('session_id'), + deviceId = json.tryGet('device_id'), + sessionId = json.tryGet('session_id'), ciphertextMegolm = json.silentTryGet('ciphertext'), // filter out invalid/incomplete CiphertextInfos ciphertextOlm = json diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index fe6a9d4d..41d0c768 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -21,15 +21,16 @@ * SOFTWARE. */ +import 'dart:core'; + import 'logs.dart'; extension TryGetMapExtension on Map { - T? tryGet(String key) { - final value = this[key]; - if (value != null && !(value is T)) { + T? tryGet(String key) { + final Object? value = this[key]; + if (value is! T) { Logs().w( - 'Expected "${T.runtimeType}" in event content for the Key "$key" but got "${value.runtimeType}".', - StackTrace.current); + 'Expected "$T" in event content for the Key "$key" but got "${value.runtimeType}".'); return null; } return value; @@ -37,43 +38,45 @@ extension TryGetMapExtension on Map { /// Same as tryGet but without logging any warnings. /// This is helpful if you have a field that can mean multiple things on purpose. - T? silentTryGet(String key) { - final value = this[key]; - if (value != null && !(value is T)) { + T? silentTryGet(String key) { + final Object? value = this[key]; + if (value is! T) { return null; } return value; } List? tryGetList(String key) { - final value = this[key]; - if (value != null && !(value is List)) { + final Object? value = this[key]; + if (value is! List) { Logs().w( - 'Expected "List<${T.runtimeType}>" in event content for the key "$key" but got "${value.runtimeType}".', + 'Expected "List<$T>" in event content for the key "$key" but got "${value.runtimeType}".', StackTrace.current); return null; } try { - return (value as List).cast(); + // copy entries to ensure type check failures here and not an access + return value.cast().toList(); } catch (_) { - Logs().w( - 'Unable to create "List<${T.runtimeType}>" in event content for the key "$key"'); + Logs() + .w('Unable to create "List<$T>" in event content for the key "$key"'); return null; } } Map? tryGetMap(String key) { - final value = this[key]; - if (value != null && !(value is Map)) { + final Object? value = this[key]; + if (value is! Map) { Logs().w( - 'Expected "Map<${A.runtimeType},${B.runtimeType}>" in event content for the key "$key" but got "${value.runtimeType}".'); + 'Expected "Map<$A,$B>" in event content for the key "$key" but got "${value.runtimeType}".'); return null; } try { - return (value as Map).cast(); + // copy map to ensure type check failures here and not an access + return Map.from(value.cast()); } catch (_) { Logs().w( - 'Unable to create "Map<${A.runtimeType},${B.runtimeType}>" in event content for the key "$key"'); + 'Unable to create "Map<$A,$B>" in event content for the key "$key"'); return null; } } From c10a98ff359c789d2f14e27161b21227d219dc88 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Fri, 2 Jul 2021 14:39:52 +0200 Subject: [PATCH 077/174] fix: log levels for tryGet --- .../model/events/room_encrypted_content.dart | 8 +-- .../model/events/room_encryption_content.dart | 5 +- .../events/room_key_request_content.dart | 2 +- .../events/secret_storage_key_content.dart | 13 ++--- lib/src/utils/try_get_map_extension.dart | 58 +++++++++++++------ 5 files changed, 53 insertions(+), 33 deletions(-) diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 060c328e..4f689566 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -47,12 +47,12 @@ class RoomEncryptedContent { RoomEncryptedContent.fromJson(Map json) : algorithm = json.tryGet('algorithm') ?? '', senderKey = json.tryGet('sender_key') ?? '', - deviceId = json.tryGet('device_id'), - sessionId = json.tryGet('session_id'), - ciphertextMegolm = json.silentTryGet('ciphertext'), + deviceId = json.tryGet('device_id', TryGet.optional), + sessionId = json.tryGet('session_id', TryGet.optional), + ciphertextMegolm = json.tryGet('ciphertext', TryGet.silent), // filter out invalid/incomplete CiphertextInfos ciphertextOlm = json - .silentTryGet>('ciphertext') + .tryGet>('ciphertext', TryGet.silent) ?.entries .map((e) { try { diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/src/model/events/room_encryption_content.dart index b88db983..41173856 100644 --- a/lib/src/model/events/room_encryption_content.dart +++ b/lib/src/model/events/room_encryption_content.dart @@ -36,8 +36,9 @@ class RoomEncryptionContent { RoomEncryptionContent.fromJson(Map json) : algorithm = json.tryGet('algorithm') ?? '', - rotationPeriodMs = json.tryGet('rotation_period_ms'), - rotationPeriodMsgs = json.tryGet('rotation_period_msgs'); + rotationPeriodMs = json.tryGet('rotation_period_ms', TryGet.optional), + rotationPeriodMsgs = + json.tryGet('rotation_period_msgs', TryGet.optional); Map toJson() { final data = {}; diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index e03deed3..53f5597d 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -37,7 +37,7 @@ class RoomKeyRequestContent { RoomKeyRequestContent.fromJson(Map json) : body = ((x) => x != null ? RequestedKeyInfo.fromJson(x) : null)( - json.tryGet('body')), + json.tryGet('body', TryGet.optional)), action = json.tryGet('action') ?? '', requestingDeviceId = json.tryGet('requesting_device_id') ?? '', requestId = json.tryGet('request_id') ?? ''; diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index a10b3a06..de42a723 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -38,12 +38,11 @@ class SecretStorageKeyContent { SecretStorageKeyContent(); SecretStorageKeyContent.fromJson(Map json) - : passphrase = json['passphrase'] is Map - ? PassphraseInfo.fromJson(json['passphrase']) - : null, - iv = json.tryGet('iv'), - mac = json.tryGet('mac'), - algorithm = json.tryGet('algorithm'); + : passphrase = ((x) => x != null ? PassphraseInfo.fromJson(x) : null)( + json.tryGet('passphrase', TryGet.optional)), + iv = json.tryGet('iv', TryGet.optional), + mac = json.tryGet('mac', TryGet.optional), + algorithm = json.tryGet('algorithm', TryGet.optional); Map toJson() { final data = {}; @@ -73,7 +72,7 @@ class PassphraseInfo { : algorithm = json.tryGet('algorithm'), salt = json.tryGet('salt'), iterations = json.tryGet('iterations'), - bits = json.tryGet('bits'); + bits = json.tryGet('bits', TryGet.optional); Map toJson() { final data = {}; diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index 41d0c768..5726f63c 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -25,33 +25,54 @@ import 'dart:core'; import 'logs.dart'; -extension TryGetMapExtension on Map { - T? tryGet(String key) { - final Object? value = this[key]; - if (value is! T) { - Logs().w( - 'Expected "$T" in event content for the Key "$key" but got "${value.runtimeType}".'); - return null; - } - return value; - } +abstract class TryGet { + void call(String key, Type expected, Type actual); + + static const TryGet required = _RequiredLog(); + static const TryGet optional = _OptionalLog(); - /// Same as tryGet but without logging any warnings. /// This is helpful if you have a field that can mean multiple things on purpose. - T? silentTryGet(String key) { + static const TryGet silent = _SilentLog(); +} + +class _RequiredLog implements TryGet { + const _RequiredLog(); + @override + void call(String key, Type expected, Type actual) => Logs().w( + 'Expected "$expected" in event content for the Key "$key" but got "$actual".'); +} + +class _OptionalLog implements TryGet { + const _OptionalLog(); + @override + void call(String key, Type expected, Type actual) { + if (actual != Null) { + Logs().w( + 'Expected "$expected" in event content for the Key "$key" but got "$actual".'); + } + } +} + +class _SilentLog implements TryGet { + const _SilentLog(); + @override + void call(String key, Type expected, Type actual) {} +} + +extension TryGetMapExtension on Map { + T? tryGet(String key, [TryGet log = TryGet.required]) { final Object? value = this[key]; if (value is! T) { + log(key, T, value.runtimeType); return null; } return value; } - List? tryGetList(String key) { + List? tryGetList(String key, [TryGet log = TryGet.required]) { final Object? value = this[key]; if (value is! List) { - Logs().w( - 'Expected "List<$T>" in event content for the key "$key" but got "${value.runtimeType}".', - StackTrace.current); + log(key, T, value.runtimeType); return null; } try { @@ -64,11 +85,10 @@ extension TryGetMapExtension on Map { } } - Map? tryGetMap(String key) { + Map? tryGetMap(String key, [TryGet log = TryGet.required]) { final Object? value = this[key]; if (value is! Map) { - Logs().w( - 'Expected "Map<$A,$B>" in event content for the key "$key" but got "${value.runtimeType}".'); + log(key, {}.runtimeType, value.runtimeType); return null; } try { From bad334d441191805a7a5725633193990cd77fa59 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Mon, 19 Jul 2021 19:43:20 +0200 Subject: [PATCH 078/174] refactor: FilterMap extension --- .../model/events/room_encrypted_content.dart | 17 ++--------------- lib/src/utils/filter_map_extension.dart | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 lib/src/utils/filter_map_extension.dart diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 4f689566..4e348704 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -23,6 +23,7 @@ import 'package:matrix_api_lite/src/utils/logs.dart'; +import '../../utils/filter_map_extension.dart'; import '../../utils/try_get_map_extension.dart'; import '../basic_event.dart'; @@ -31,11 +32,6 @@ extension RoomEncryptedContentBasicEventExtension on BasicEvent { RoomEncryptedContent.fromJson(content); } -/// Convert Nullable iterable of MapEntries to Map -extension ToMap on Iterable> { - Map toMap() => Map.fromEntries(this); -} - class RoomEncryptedContent { String algorithm; String senderKey; @@ -53,16 +49,7 @@ class RoomEncryptedContent { // filter out invalid/incomplete CiphertextInfos ciphertextOlm = json .tryGet>('ciphertext', TryGet.silent) - ?.entries - .map((e) { - try { - return MapEntry(e.key, CiphertextInfo.fromJson(e.value)); - } catch (_) { - return null; - } - }) - .whereType>() - .toMap(); + ?.catchMap((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))); Map toJson() { final data = {}; diff --git a/lib/src/utils/filter_map_extension.dart b/lib/src/utils/filter_map_extension.dart new file mode 100644 index 00000000..11621e76 --- /dev/null +++ b/lib/src/utils/filter_map_extension.dart @@ -0,0 +1,14 @@ +extension FilterMap on Map { + Map filterMap(MapEntry? Function(K, V) f) => + Map.fromEntries( + entries.map((e) => f(e.key, e.value)).whereType>()); + + Map catchMap(MapEntry Function(K, V) f) => + filterMap((k, v) { + try { + return f(k, v); + } catch (_) { + return null; + } + }); +} From cfa633b489bea54c603a841073d8143fa0e058e4 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Thu, 22 Jul 2021 17:08:36 +0200 Subject: [PATCH 079/174] feat: Add image pack event content models --- lib/matrix_api_lite.dart | 1 + lib/src/model/events/image_pack_content.dart | 178 +++++++++++++++++++ test/event_content_test.dart | 87 ++++++++- 3 files changed, 262 insertions(+), 4 deletions(-) create mode 100644 lib/src/model/events/image_pack_content.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index d6251d92..838e242e 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -41,6 +41,7 @@ export 'src/model/basic_event_with_sender.dart'; export 'src/model/basic_room_event.dart'; export 'src/model/event_types.dart'; export 'src/model/events/forwarded_room_key_content.dart'; +export 'src/model/events/image_pack_content.dart'; export 'src/model/events/olm_plaintext_payload.dart'; export 'src/model/events/room_encrypted_content.dart'; export 'src/model/events/room_encryption_content.dart'; diff --git a/lib/src/model/events/image_pack_content.dart b/lib/src/model/events/image_pack_content.dart new file mode 100644 index 00000000..6c1ae0af --- /dev/null +++ b/lib/src/model/events/image_pack_content.dart @@ -0,0 +1,178 @@ +/* MIT License +* +* Copyright (C) 2019, 2020, 2021 Famedly GmbH +* +* 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. +*/ + +import '../basic_event.dart'; +import '../../utils/filter_map_extension.dart'; +import '../../utils/try_get_map_extension.dart'; + +extension ImagePackContentBasicEventExtension on BasicEvent { + ImagePackContent get parsedImagePackContent => + ImagePackContent.fromJson(content); +} + +enum ImagePackUsage { + sticker, + emoticon, +} + +List? imagePackUsageFromJson(List? json) => json + ?.map((v) => { + 'sticker': ImagePackUsage.sticker, + 'emoticon': ImagePackUsage.emoticon, + }[v]) + .whereType() + .toList(); + +List imagePackUsageToJson( + List? usage, List? prevUsage) { + final knownUsages = {'sticker', 'emoticon'}; + final usagesStr = usage + ?.map((v) => { + ImagePackUsage.sticker: 'sticker', + ImagePackUsage.emoticon: 'emoticon', + }[v]) + .whereType() + .toList() ?? + []; + // first we add all the unknown usages and the previous known usages which are new again + final newUsages = prevUsage + ?.where((v) => !knownUsages.contains(v) || usagesStr.contains(v)) + .toList() ?? + []; + // now we need to add the new usages that we didn't add yet + newUsages.addAll(usagesStr.where((v) => !newUsages.contains(v))); + return newUsages; +} + +class ImagePackContent { + // we want to preserve potential custom keys in this object + final Map _json; + + Map images; + ImagePackPackContent pack; + + ImagePackContent({required this.images, required this.pack}) : _json = {}; + + ImagePackContent.fromJson(Map json) + : _json = Map.fromEntries(json.entries.where( + (e) => !['images', 'pack', 'emoticons', 'short'].contains(e.key))), + pack = ImagePackPackContent.fromJson( + json.tryGetMap('pack', TryGet.optional) ?? {}), + images = json + .tryGetMap('images', TryGet.optional) + ?.catchMap( + (k, v) => MapEntry(k, ImagePackImageContent.fromJson(v))) ?? + // the "emoticons" key needs a small migration on the key, ":string:" --> "string" + json + .tryGetMap('emoticons', TryGet.optional) + ?.catchMap((k, v) => MapEntry( + k.startsWith(':') && k.endsWith(':') + ? k.substring(1, k.length - 1) + : k, + ImagePackImageContent.fromJson(v))) ?? + // the "short" key was still just a map from shortcode to mxc uri + json.tryGetMap('short', TryGet.optional)?.catchMap( + (k, v) => MapEntry( + k.startsWith(':') && k.endsWith(':') + ? k.substring(1, k.length - 1) + : k, + ImagePackImageContent(url: Uri.parse(v)))) ?? + {}; + + Map toJson() => { + ..._json, + 'images': images.map((k, v) => MapEntry(k, v.toJson())), + 'pack': pack.toJson(), + }; +} + +class ImagePackImageContent { + // we want to preserve potential custom keys in this object + final Map _json; + + Uri url; + String? body; + Map? info; + List? usage; + + ImagePackImageContent({required this.url, this.body, this.info, this.usage}) + : _json = {}; + + ImagePackImageContent.fromJson(Map json) + : _json = Map.fromEntries(json.entries + .where((e) => !['url', 'body', 'info'].contains(e.key))), + url = Uri.parse(json['url']), + body = json.tryGet('body', TryGet.optional), + info = json.tryGetMap('info', TryGet.optional), + usage = imagePackUsageFromJson( + json.tryGetList('usage', TryGet.optional)); + + Map toJson() { + return { + ...Map.from(_json)..remove('usage'), + 'url': url.toString(), + if (body != null) 'body': body, + if (info != null) 'info': info, + if (usage != null) + 'usage': imagePackUsageToJson( + usage, _json.tryGetList('usage', TryGet.optional)), + }; + } +} + +class ImagePackPackContent { + // we want to preserve potential custom keys in this object + final Map _json; + + String? displayName; + Uri? avatarUrl; + List? usage; + String? attribution; + + ImagePackPackContent( + {this.displayName, this.avatarUrl, this.usage, this.attribution}) + : _json = {}; + + ImagePackPackContent.fromJson(Map json) + : _json = Map.fromEntries(json.entries.where((e) => + !['display_name', 'avatar_url', 'attribution'].contains(e.key))), + displayName = json.tryGet('display_name', TryGet.optional), + // we default to an invalid uri + avatarUrl = + Uri.tryParse(json.tryGet('avatar_url', TryGet.optional) ?? '.::'), + usage = imagePackUsageFromJson( + json.tryGetList('usage', TryGet.optional)), + attribution = json.tryGet('attribution', TryGet.optional); + + Map toJson() { + return { + ...Map.from(_json)..remove('usage'), + if (displayName != null) 'display_name': displayName, + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + if (usage != null) + 'usage': imagePackUsageToJson( + usage, _json.tryGetList('usage', TryGet.optional)), + if (attribution != null) 'attribution': attribution, + }; + } +} diff --git a/test/event_content_test.dart b/test/event_content_test.dart index 82099ac7..67fe9cc9 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -1,17 +1,17 @@ /* MIT License -* +* * Copyright (C) 2019, 2020, 2021 Famedly GmbH -* +* * 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 @@ -167,5 +167,84 @@ void main() { json = jsonDecode(jsonEncode(json)); expect(OlmPlaintextPayload.fromJson(json!).toJson(), json); }); + test('Image Pack Content', () { + // basic parse / unparse + var json = { + 'type': 'some type', + 'content': { + 'images': { + 'emote': { + 'url': 'mxc://example.org/beep', + 'usage': ['emoticon'], + 'org.custom': 'beep', + }, + 'sticker': { + 'url': 'mxc://example.org/boop', + 'usage': ['org.custom', 'sticker', 'org.other.custom'], + }, + }, + 'pack': { + 'display_name': 'Awesome Pack', + 'org.custom': 'boop', + }, + 'org.custom': 'blah', + }, + }; + json = jsonDecode(jsonEncode(json)); + expect(BasicEvent.fromJson(json).parsedImagePackContent.toJson(), + json['content']); + + // emoticons migration + json = { + 'type': 'some type', + 'content': { + 'emoticons': { + ':emote:': { + 'url': 'mxc://example.org/beep', + }, + }, + }, + }; + json = jsonDecode(jsonEncode(json)); + expect( + BasicEvent.fromJson(json) + .parsedImagePackContent + .images['emote'] + ?.toJson(), + { + 'url': 'mxc://example.org/beep', + }); + + json = { + 'type': 'some type', + 'content': { + 'short': { + ':emote:': 'mxc://example.org/beep', + }, + }, + }; + json = jsonDecode(jsonEncode(json)); + expect( + BasicEvent.fromJson(json) + .parsedImagePackContent + .images['emote'] + ?.toJson(), + { + 'url': 'mxc://example.org/beep', + }); + + // invalid url for image + json = { + 'type': 'some type', + 'content': { + 'images': { + 'emote': {}, + }, + }, + }; + json = jsonDecode(jsonEncode(json)); + expect(BasicEvent.fromJson(json).parsedImagePackContent.images['emote'], + null); + }); }); } From 268b05b09f7f351da0c0139006e1549a5ff5a0b3 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 22 Jul 2021 18:17:06 +0200 Subject: [PATCH 080/174] chore: Bump version --- CHANGELOG.md | 8 ++++++++ pubspec.yaml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b668fe74..5cefc84f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.4.0 +- refactor: Migrate to null safety +- refactor: Use openAPI code generation to create most of the methods +- feat: Add image pack event content models +- refactor: FilterMap extension +- fix: log levels for tryGet +- refactor: remove timeouts in matrix_api_lite + ## 0.3.3 - fix: Log filter in wrong direction diff --git a/pubspec.yaml b/pubspec.yaml index ce5eddc1..f1e6a380 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.3.3 +version: 0.4.0 homepage: https://famedly.com environment: From 3dd1230ffbc68f58f5572113d804db714953eaff Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Fri, 23 Jul 2021 06:20:17 +0000 Subject: [PATCH 081/174] Update CHANGELOG.md --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cefc84f..446b6a21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,11 @@ ## 0.4.0 - refactor: Migrate to null safety - refactor: Use openAPI code generation to create most of the methods -- feat: Add image pack event content models -- refactor: FilterMap extension -- fix: log levels for tryGet - refactor: remove timeouts in matrix_api_lite +## 0.3.5 +- feat: Add image pack event content models + ## 0.3.3 - fix: Log filter in wrong direction From 916711cf570e7c5123406b1a49b2ecad29f718b5 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 3 Aug 2021 10:22:45 +0200 Subject: [PATCH 082/174] fix: Make tryget type optional by default I see soo much annoying warnings in the logs since matrix 0.2.0 and to be honest it was never helpful to have this logs. Therefore it seems to make more sense to make those warnings optional. --- lib/src/utils/try_get_map_extension.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index 5726f63c..1cc026bc 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -60,7 +60,7 @@ class _SilentLog implements TryGet { } extension TryGetMapExtension on Map { - T? tryGet(String key, [TryGet log = TryGet.required]) { + T? tryGet(String key, [TryGet log = TryGet.optional]) { final Object? value = this[key]; if (value is! T) { log(key, T, value.runtimeType); @@ -69,7 +69,7 @@ extension TryGetMapExtension on Map { return value; } - List? tryGetList(String key, [TryGet log = TryGet.required]) { + List? tryGetList(String key, [TryGet log = TryGet.optional]) { final Object? value = this[key]; if (value is! List) { log(key, T, value.runtimeType); @@ -85,7 +85,7 @@ extension TryGetMapExtension on Map { } } - Map? tryGetMap(String key, [TryGet log = TryGet.required]) { + Map? tryGetMap(String key, [TryGet log = TryGet.optional]) { final Object? value = this[key]; if (value is! Map) { log(key, {}.runtimeType, value.runtimeType); From c73b7631f534cd507faa16fcd777d7f3e9bb9683 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Tue, 3 Aug 2021 16:10:55 +0200 Subject: [PATCH 083/174] fix: tryGet log levels --- .../events/forwarded_room_key_content.dart | 9 +++-- lib/src/model/events/image_pack_content.dart | 40 ++++++++----------- .../model/events/olm_plaintext_payload.dart | 12 +++--- .../model/events/room_encrypted_content.dart | 8 ++-- .../model/events/room_encryption_content.dart | 7 ++-- lib/src/model/events/room_key_content.dart | 8 ++-- .../events/room_key_request_content.dart | 17 ++++---- .../secret_storage_default_key_content.dart | 2 +- .../events/secret_storage_key_content.dart | 16 ++++---- lib/src/model/events/tombstone_content.dart | 5 ++- 10 files changed, 59 insertions(+), 65 deletions(-) diff --git a/lib/src/model/events/forwarded_room_key_content.dart b/lib/src/model/events/forwarded_room_key_content.dart index b4ec3232..46196692 100644 --- a/lib/src/model/events/forwarded_room_key_content.dart +++ b/lib/src/model/events/forwarded_room_key_content.dart @@ -36,11 +36,12 @@ class ForwardedRoomKeyContent extends RoomKeyContent { List forwardingCurve25519KeyChain; ForwardedRoomKeyContent.fromJson(Map json) - : senderKey = json.tryGet('sender_key') ?? '', + : senderKey = json.tryGet('sender_key', TryGet.required) ?? '', senderClaimedEd25519Key = - json.tryGet('sender_claimed_ed25519_key') ?? '', - forwardingCurve25519KeyChain = - json.tryGetList('forwarding_curve25519_key_chain') ?? [], + json.tryGet('sender_claimed_ed25519_key', TryGet.required) ?? '', + forwardingCurve25519KeyChain = json.tryGetList( + 'forwarding_curve25519_key_chain', TryGet.required) ?? + [], super.fromJson(json); @override diff --git a/lib/src/model/events/image_pack_content.dart b/lib/src/model/events/image_pack_content.dart index 6c1ae0af..31923917 100644 --- a/lib/src/model/events/image_pack_content.dart +++ b/lib/src/model/events/image_pack_content.dart @@ -77,22 +77,19 @@ class ImagePackContent { : _json = Map.fromEntries(json.entries.where( (e) => !['images', 'pack', 'emoticons', 'short'].contains(e.key))), pack = ImagePackPackContent.fromJson( - json.tryGetMap('pack', TryGet.optional) ?? {}), - images = json - .tryGetMap('images', TryGet.optional) - ?.catchMap( - (k, v) => MapEntry(k, ImagePackImageContent.fromJson(v))) ?? + json.tryGetMap('pack') ?? {}), + images = json.tryGetMap('images')?.catchMap( + (k, v) => MapEntry(k, ImagePackImageContent.fromJson(v))) ?? // the "emoticons" key needs a small migration on the key, ":string:" --> "string" - json - .tryGetMap('emoticons', TryGet.optional) - ?.catchMap((k, v) => MapEntry( + json.tryGetMap('emoticons')?.catchMap((k, v) => + MapEntry( k.startsWith(':') && k.endsWith(':') ? k.substring(1, k.length - 1) : k, ImagePackImageContent.fromJson(v))) ?? // the "short" key was still just a map from shortcode to mxc uri - json.tryGetMap('short', TryGet.optional)?.catchMap( - (k, v) => MapEntry( + json.tryGetMap('short')?.catchMap((k, v) => + MapEntry( k.startsWith(':') && k.endsWith(':') ? k.substring(1, k.length - 1) : k, @@ -122,10 +119,9 @@ class ImagePackImageContent { : _json = Map.fromEntries(json.entries .where((e) => !['url', 'body', 'info'].contains(e.key))), url = Uri.parse(json['url']), - body = json.tryGet('body', TryGet.optional), - info = json.tryGetMap('info', TryGet.optional), - usage = imagePackUsageFromJson( - json.tryGetList('usage', TryGet.optional)); + body = json.tryGet('body'), + info = json.tryGetMap('info'), + usage = imagePackUsageFromJson(json.tryGetList('usage')); Map toJson() { return { @@ -134,8 +130,7 @@ class ImagePackImageContent { if (body != null) 'body': body, if (info != null) 'info': info, if (usage != null) - 'usage': imagePackUsageToJson( - usage, _json.tryGetList('usage', TryGet.optional)), + 'usage': imagePackUsageToJson(usage, _json.tryGetList('usage')), }; } } @@ -156,13 +151,11 @@ class ImagePackPackContent { ImagePackPackContent.fromJson(Map json) : _json = Map.fromEntries(json.entries.where((e) => !['display_name', 'avatar_url', 'attribution'].contains(e.key))), - displayName = json.tryGet('display_name', TryGet.optional), + displayName = json.tryGet('display_name'), // we default to an invalid uri - avatarUrl = - Uri.tryParse(json.tryGet('avatar_url', TryGet.optional) ?? '.::'), - usage = imagePackUsageFromJson( - json.tryGetList('usage', TryGet.optional)), - attribution = json.tryGet('attribution', TryGet.optional); + avatarUrl = Uri.tryParse(json.tryGet('avatar_url') ?? '.::'), + usage = imagePackUsageFromJson(json.tryGetList('usage')), + attribution = json.tryGet('attribution'); Map toJson() { return { @@ -170,8 +163,7 @@ class ImagePackPackContent { if (displayName != null) 'display_name': displayName, if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), if (usage != null) - 'usage': imagePackUsageToJson( - usage, _json.tryGetList('usage', TryGet.optional)), + 'usage': imagePackUsageToJson(usage, _json.tryGetList('usage')), if (attribution != null) 'attribution': attribution, }; } diff --git a/lib/src/model/events/olm_plaintext_payload.dart b/lib/src/model/events/olm_plaintext_payload.dart index 5f67ca1b..fe7e0611 100644 --- a/lib/src/model/events/olm_plaintext_payload.dart +++ b/lib/src/model/events/olm_plaintext_payload.dart @@ -42,12 +42,12 @@ class OlmPlaintextPayload { factory OlmPlaintextPayload.fromJson(Map json) => OlmPlaintextPayload( - sender: json.tryGet('sender'), - type: json.tryGet('type'), - content: json.tryGetMap('content'), - recipient: json.tryGet('recipient'), - recipientKeys: json.tryGetMap('recipient_keys'), - keys: json.tryGetMap('keys'), + sender: json.tryGet('sender', TryGet.required), + type: json.tryGet('type', TryGet.required), + content: json.tryGetMap('content', TryGet.required), + recipient: json.tryGet('recipient', TryGet.required), + recipientKeys: json.tryGetMap('recipient_keys', TryGet.required), + keys: json.tryGetMap('keys', TryGet.required), ); Map toJson() { diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 4e348704..a358dc9f 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -41,10 +41,10 @@ class RoomEncryptedContent { Map? ciphertextOlm; RoomEncryptedContent.fromJson(Map json) - : algorithm = json.tryGet('algorithm') ?? '', - senderKey = json.tryGet('sender_key') ?? '', - deviceId = json.tryGet('device_id', TryGet.optional), - sessionId = json.tryGet('session_id', TryGet.optional), + : algorithm = json.tryGet('algorithm', TryGet.required) ?? '', + senderKey = json.tryGet('sender_key', TryGet.required) ?? '', + deviceId = json.tryGet('device_id'), + sessionId = json.tryGet('session_id'), ciphertextMegolm = json.tryGet('ciphertext', TryGet.silent), // filter out invalid/incomplete CiphertextInfos ciphertextOlm = json diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/src/model/events/room_encryption_content.dart index 41173856..24262320 100644 --- a/lib/src/model/events/room_encryption_content.dart +++ b/lib/src/model/events/room_encryption_content.dart @@ -35,10 +35,9 @@ class RoomEncryptionContent { int? rotationPeriodMsgs; RoomEncryptionContent.fromJson(Map json) - : algorithm = json.tryGet('algorithm') ?? '', - rotationPeriodMs = json.tryGet('rotation_period_ms', TryGet.optional), - rotationPeriodMsgs = - json.tryGet('rotation_period_msgs', TryGet.optional); + : algorithm = json.tryGet('algorithm', TryGet.required) ?? '', + rotationPeriodMs = json.tryGet('rotation_period_ms'), + rotationPeriodMsgs = json.tryGet('rotation_period_msgs'); Map toJson() { final data = {}; diff --git a/lib/src/model/events/room_key_content.dart b/lib/src/model/events/room_key_content.dart index e179e662..e8c69893 100644 --- a/lib/src/model/events/room_key_content.dart +++ b/lib/src/model/events/room_key_content.dart @@ -41,10 +41,10 @@ class RoomKeyContent { required this.sessionKey}); RoomKeyContent.fromJson(Map json) - : algorithm = json.tryGet('algorithm') ?? '', - roomId = json.tryGet('room_id') ?? '', - sessionId = json.tryGet('session_id') ?? '', - sessionKey = json.tryGet('session_key') ?? ''; + : algorithm = json.tryGet('algorithm', TryGet.required) ?? '', + roomId = json.tryGet('room_id', TryGet.required) ?? '', + sessionId = json.tryGet('session_id', TryGet.required) ?? '', + sessionKey = json.tryGet('session_key', TryGet.required) ?? ''; Map toJson() { final data = {}; diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index 53f5597d..5599cc03 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -37,10 +37,11 @@ class RoomKeyRequestContent { RoomKeyRequestContent.fromJson(Map json) : body = ((x) => x != null ? RequestedKeyInfo.fromJson(x) : null)( - json.tryGet('body', TryGet.optional)), - action = json.tryGet('action') ?? '', - requestingDeviceId = json.tryGet('requesting_device_id') ?? '', - requestId = json.tryGet('request_id') ?? ''; + json.tryGet('body')), + action = json.tryGet('action', TryGet.required) ?? '', + requestingDeviceId = + json.tryGet('requesting_device_id', TryGet.required) ?? '', + requestId = json.tryGet('request_id', TryGet.required) ?? ''; Map toJson() { final data = {}; @@ -65,10 +66,10 @@ class RequestedKeyInfo { required this.senderKey}); RequestedKeyInfo.fromJson(Map json) - : algorithm = json.tryGet('algorithm') ?? '', - roomId = json.tryGet('room_id') ?? '', - sessionId = json.tryGet('session_id') ?? '', - senderKey = json.tryGet('sender_key') ?? ''; + : algorithm = json.tryGet('algorithm', TryGet.required) ?? '', + roomId = json.tryGet('room_id', TryGet.required) ?? '', + sessionId = json.tryGet('session_id', TryGet.required) ?? '', + senderKey = json.tryGet('sender_key', TryGet.required) ?? ''; Map toJson() { final data = {}; diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/src/model/events/secret_storage_default_key_content.dart index 470538d4..198f6e7d 100644 --- a/lib/src/model/events/secret_storage_default_key_content.dart +++ b/lib/src/model/events/secret_storage_default_key_content.dart @@ -36,7 +36,7 @@ class SecretStorageDefaultKeyContent { SecretStorageDefaultKeyContent({required this.key}); SecretStorageDefaultKeyContent.fromJson(Map json) - : key = json.tryGet('key'); + : key = json.tryGet('key', TryGet.required); Map toJson() { final data = {}; diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index de42a723..d748da34 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -39,10 +39,10 @@ class SecretStorageKeyContent { SecretStorageKeyContent.fromJson(Map json) : passphrase = ((x) => x != null ? PassphraseInfo.fromJson(x) : null)( - json.tryGet('passphrase', TryGet.optional)), - iv = json.tryGet('iv', TryGet.optional), - mac = json.tryGet('mac', TryGet.optional), - algorithm = json.tryGet('algorithm', TryGet.optional); + json.tryGet('passphrase')), + iv = json.tryGet('iv'), + mac = json.tryGet('mac'), + algorithm = json.tryGet('algorithm'); Map toJson() { final data = {}; @@ -69,10 +69,10 @@ class PassphraseInfo { this.bits}); PassphraseInfo.fromJson(Map json) - : algorithm = json.tryGet('algorithm'), - salt = json.tryGet('salt'), - iterations = json.tryGet('iterations'), - bits = json.tryGet('bits', TryGet.optional); + : algorithm = json.tryGet('algorithm', TryGet.required), + salt = json.tryGet('salt', TryGet.required), + iterations = json.tryGet('iterations', TryGet.required), + bits = json.tryGet('bits'); Map toJson() { final data = {}; diff --git a/lib/src/model/events/tombstone_content.dart b/lib/src/model/events/tombstone_content.dart index 18804448..926db2fc 100644 --- a/lib/src/model/events/tombstone_content.dart +++ b/lib/src/model/events/tombstone_content.dart @@ -34,8 +34,9 @@ class TombstoneContent { String replacementRoom; TombstoneContent.fromJson(Map json) - : body = json.tryGet('body') ?? '', - replacementRoom = json.tryGet('replacement_room') ?? ''; + : body = json.tryGet('body', TryGet.required) ?? '', + replacementRoom = + json.tryGet('replacement_room', TryGet.required) ?? ''; Map toJson() { final data = {}; From 2f7c8baf9f5098fa8616afe6d51cf87f65be9b3a Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Thu, 5 Aug 2021 13:11:16 +0200 Subject: [PATCH 084/174] chore: bump version to 0.4.1 --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 446b6a21..1b506b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1 + +fix: change tryGet default loglevel to Optional + ## 0.4.0 - refactor: Migrate to null safety - refactor: Use openAPI code generation to create most of the methods diff --git a/pubspec.yaml b/pubspec.yaml index f1e6a380..5a671d79 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.4.0 +version: 0.4.1 homepage: https://famedly.com environment: From 8d795d6eaa3ac1e60c55ff0316e42e4fa45285ab Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Mon, 9 Aug 2021 19:47:12 +0200 Subject: [PATCH 085/174] chore: update generated code --- lib/src/generated/api.dart | 6 ++++-- lib/src/generated/model.dart | 2 +- test/matrix_api_test.dart | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 87a8ad4f..5c7a200e 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -2474,6 +2474,7 @@ class Api { 'membership': { Membership.invite: 'invite', Membership.join: 'join', + Membership.knock: 'knock', Membership.leave: 'leave', Membership.ban: 'ban' }[membership]!, @@ -2481,6 +2482,7 @@ class Api { 'not_membership': { Membership.invite: 'invite', Membership.join: 'join', + Membership.knock: 'knock', Membership.leave: 'leave', Membership.ban: 'ban' }[notMembership]!, @@ -3534,7 +3536,7 @@ class Api { /// /// returns `content_uri`: /// The [MXC URI](https://spec.matrix.org/unstable/client-server-api/#matrix-content-mxc-uris) to the uploaded content. - Future uploadContent(Uint8List content, + Future uploadContent(Uint8List content, {String? contentType, String? filename}) async { final requestUri = Uri(path: '_matrix/media/r0/upload', queryParameters: { if (filename != null) 'filename': filename, @@ -3548,6 +3550,6 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return json['content_uri'] as String; + return Uri.parse(json['content_uri']); } } diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index 71989bcc..90330e7b 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -1864,7 +1864,7 @@ class RoomMember { } @_NameSource('(generated, rule override generated)') -enum Membership { ban, invite, join, leave } +enum Membership { ban, invite, join, knock, leave } @_NameSource('rule override generated') enum Direction { b, f } diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 1ca519da..15050e2c 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -996,7 +996,7 @@ void main() { matrixApi.accessToken = '1234'; final response = await matrixApi.uploadContent(Uint8List(0), filename: 'file.jpeg'); - expect(response, 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'); + expect(response, Uri.parse('mxc://example.com/AQwafuaFswefuhsfAFAgsw')); var throwsException = false; try { await matrixApi.uploadContent(Uint8List(0), filename: 'file.jpg'); From a554f3463dc17f5be59c7e8a06471fa6fd544e9b Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Fri, 20 Aug 2021 20:35:23 +0800 Subject: [PATCH 086/174] Add more call event for improve voip. --- lib/src/model/event_types.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index d5adc9ac..58c80899 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -46,6 +46,17 @@ abstract class EventTypes { static const String CallAnswer = 'm.call.answer'; static const String CallCandidates = 'm.call.candidates'; static const String CallHangup = 'm.call.hangup'; + static const String CallSelectAnswer = 'm.call.select_answer'; + static const String CallReject = 'm.call.reject'; + static const String CallNegotiate = 'm.call.negotiate'; + static const String CallSDPStreamMetadataChanged = + 'm.call.sdp_stream_metadata_changed'; + static const String CallSDPStreamMetadataChangedPrefix = + 'org.matrix.call.sdp_stream_metadata_changed'; + static const String CallReplaces = 'm.call.replaces'; + static const String CallAssertedIdentity = 'm.call.asserted_identity'; + static const String CallAssertedIdentityPrefix = + 'org.matrix.call.asserted_identity'; static const String Unknown = 'm.unknown'; // To device event types From 09198ce14de4e51f9baccd4727c277092703ddbc Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Fri, 20 Aug 2021 16:01:26 +0200 Subject: [PATCH 087/174] chore: update generated code --- lib/src/generated/api.dart | 15 +++++++++------ lib/src/generated/model.dart | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 5c7a200e..39408a66 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -182,7 +182,7 @@ class Api { /// returns `id_server_unbind_result`: /// An indicator as to whether or not the homeserver was able to unbind /// the 3PID from the identity server. `success` indicates that the - /// indentity server has unbound the identifier whereas `no-support` + /// identity server has unbound the identifier whereas `no-support` /// indicates that the identity server refuses to support the request /// or the homeserver was not able to determine an identity server to /// unbind from. @@ -430,16 +430,18 @@ class Api { /// (and not other members) permission to send state events. Overridden /// by the `power_level_content_override` parameter. /// - /// 4. Events set by the `preset`. Currently these are the `m.room.join_rules`, + /// 4. An `m.room.canonical_alias` event if `room_alias_name` is given. + /// + /// 5. Events set by the `preset`. Currently these are the `m.room.join_rules`, /// `m.room.history_visibility`, and `m.room.guest_access` state events. /// - /// 5. Events listed in `initial_state`, in the order that they are + /// 6. Events listed in `initial_state`, in the order that they are /// listed. /// - /// 6. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` + /// 7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` /// state events). /// - /// 7. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with + /// 8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with /// `membership: invite` and `m.room.third_party_invite`). /// /// The available presets do the following with respect to room state: @@ -503,7 +505,8 @@ class Api { /// would be `#foo:example.com`. /// /// The complete room alias will become the canonical alias for - /// the room. + /// the room and an `m.room.canonical_alias` event will be sent + /// into the room. /// /// [roomVersion] The room version to set for the room. If not provided, the homeserver is /// to use its configured default. If provided, the homeserver will return a diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index 90330e7b..324c5822 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -2873,7 +2873,7 @@ class Filter { RoomFilter? room; } -@_NameSource('rule override generated') +@_NameSource('spec') class OpenIdCredentials { OpenIdCredentials({ required this.accessToken, From 6c16ce31c4695d62e7873789b835fc5fec42d07d Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 20 Aug 2021 15:54:44 +0200 Subject: [PATCH 088/174] chore: Bump version --- CHANGELOG.md | 6 ++++-- pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b506b09..db8ca4a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ -## 0.4.1 +## 0.4.2 +- feat: Add more call event for improve voip. -fix: change tryGet default loglevel to Optional +## 0.4.1 +- fix: change tryGet default loglevel to Optional ## 0.4.0 - refactor: Migrate to null safety diff --git a/pubspec.yaml b/pubspec.yaml index 5a671d79..bccc1c64 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.4.1 +version: 0.4.2 homepage: https://famedly.com environment: From cb71ca9b26a2db7f0ee8d9e3d60c978916455dd1 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Fri, 20 Aug 2021 16:17:37 +0200 Subject: [PATCH 089/174] chore: generate more operations from OpenAPI --- lib/fake_matrix_api.dart | 2 +- lib/matrix_api_lite.dart | 6 - lib/src/generated/api.dart | 876 +++++++++++++++++++++- lib/src/generated/model.dart | 342 +++++++-- lib/src/matrix_api.dart | 401 ---------- lib/src/model/events_sync_update.dart | 53 -- lib/src/model/request_token_response.dart | 38 - lib/src/model/supported_protocol.dart | 91 --- lib/src/model/third_party_location.dart | 43 -- lib/src/model/third_party_user.dart | 43 -- test/matrix_api_test.dart | 122 +-- 11 files changed, 1197 insertions(+), 820 deletions(-) delete mode 100644 lib/src/model/events_sync_update.dart delete mode 100644 lib/src/model/request_token_response.dart delete mode 100644 lib/src/model/supported_protocol.dart delete mode 100644 lib/src/model/third_party_location.dart delete mode 100644 lib/src/model/third_party_user.dart diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 1ca54f5b..d626dccd 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -776,7 +776,7 @@ class FakeMatrixApi extends MockClient { 'u.Customers': {} } }, - '/client/r0/events?from=1234&timeout=10&roomId=%211234': (var req) => { + '/client/r0/events?from=1234&timeout=10&room_id=%211234': (var req) => { 'start': 's3456_9_0', 'end': 's3457_9_0', 'chunk': [ diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 838e242e..8cd63c62 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -50,7 +50,6 @@ export 'src/model/events/room_key_request_content.dart'; export 'src/model/events/secret_storage_default_key_content.dart'; export 'src/model/events/secret_storage_key_content.dart'; export 'src/model/events/tombstone_content.dart'; -export 'src/model/events_sync_update.dart'; export 'src/model/matrix_connection_exception.dart'; export 'src/model/matrix_event.dart'; export 'src/model/matrix_exception.dart'; @@ -58,15 +57,10 @@ export 'src/model/matrix_keys.dart'; export 'src/model/message_types.dart'; export 'src/model/presence.dart'; export 'src/model/presence_content.dart'; -export 'src/model/request_token_response.dart'; export 'src/model/room_creation_types.dart'; -export 'src/model/room_keys_keys.dart'; export 'src/model/room_summary.dart'; export 'src/model/stripped_state_event.dart'; -export 'src/model/supported_protocol.dart'; export 'src/model/sync_update.dart'; -export 'src/model/third_party_location.dart'; -export 'src/model/third_party_user.dart'; export 'src/model/upload_key_signatures_response.dart'; export 'src/utils/logs.dart'; export 'src/utils/map_copy_extension.dart'; diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 39408a66..5a28a352 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -212,6 +212,139 @@ class Api { }[json['id_server_unbind_result']]!; } + /// The homeserver must check that the given email address is **not** + /// already associated with an account on this homeserver. This API should + /// be used to request validation tokens when adding an email address to an + /// account. This API's parameters and response are identical to that of + /// the [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registeremailrequesttoken) + /// endpoint. The homeserver should validate + /// the email itself, either by sending a validation email itself or by using + /// a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [email] The email address to validate. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [sendAttempt] The server will only send an email if the `send_attempt` + /// is a number greater than the most recent one which it has seen, + /// scoped to that `email` + `client_secret` pair. This is to + /// avoid repeatedly sending the same email in the case of request + /// retries between the POSTing user and the identity server. + /// The client should increment this value if they desire a new + /// email (e.g. a reminder) to be sent. If they do not, the server + /// should respond with success but not resend the email. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenTo3PIDEmail( + String clientSecret, String email, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/account/3pid/email/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'email': email, + if (nextLink != null) 'next_link': nextLink, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + + /// The homeserver must check that the given phone number is **not** + /// already associated with an account on this homeserver. This API should + /// be used to request validation tokens when adding a phone number to an + /// account. This API's parameters and response are identical to that of + /// the [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + /// endpoint. The homeserver should validate + /// the phone number itself, either by sending a validation message itself or by using + /// a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the + /// number in `phone_number` should be parsed as if it were dialled from. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [phoneNumber] The phone number to validate. + /// + /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a + /// number greater than the most recent one which it has seen, + /// scoped to that `country` + `phone_number` + `client_secret` + /// triple. This is to avoid repeatedly sending the same SMS in + /// the case of request retries between the POSTing user and the + /// identity server. The client should increment this value if + /// they desire a new SMS (e.g. a reminder) to be sent. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenTo3PIDMSISDN( + String clientSecret, String country, String phoneNumber, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/account/3pid/msisdn/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'country': country, + if (nextLink != null) 'next_link': nextLink, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + /// Removes a user's third party identifier from the provided identity server /// without removing it from the homeserver. /// @@ -356,6 +489,153 @@ class Api { return ignore(json); } + /// The homeserver must check that the given email address **is + /// associated** with an account on this homeserver. This API should be + /// used to request validation tokens when authenticating for the + /// `/account/password` endpoint. + /// + /// This API's parameters and response are identical to that of the + /// [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registeremailrequesttoken) + /// endpoint, except that + /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the + /// given email address could be found. The server may instead send an + /// email to the given address prompting the user to create an account. + /// `M_THREEPID_IN_USE` may not be returned. + /// + /// The homeserver should validate the email itself, either by sending a + /// validation email itself or by using a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [email] The email address to validate. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [sendAttempt] The server will only send an email if the `send_attempt` + /// is a number greater than the most recent one which it has seen, + /// scoped to that `email` + `client_secret` pair. This is to + /// avoid repeatedly sending the same email in the case of request + /// retries between the POSTing user and the identity server. + /// The client should increment this value if they desire a new + /// email (e.g. a reminder) to be sent. If they do not, the server + /// should respond with success but not resend the email. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenToResetPasswordEmail( + String clientSecret, String email, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/account/password/email/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'email': email, + if (nextLink != null) 'next_link': nextLink, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + + /// The homeserver must check that the given phone number **is + /// associated** with an account on this homeserver. This API should be + /// used to request validation tokens when authenticating for the + /// `/account/password` endpoint. + /// + /// This API's parameters and response are identical to that of the + /// [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + /// endpoint, except that + /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the + /// given phone number could be found. The server may instead send the SMS + /// to the given phone number prompting the user to create an account. + /// `M_THREEPID_IN_USE` may not be returned. + /// + /// The homeserver should validate the phone number itself, either by sending a + /// validation message itself or by using a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the + /// number in `phone_number` should be parsed as if it were dialled from. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [phoneNumber] The phone number to validate. + /// + /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a + /// number greater than the most recent one which it has seen, + /// scoped to that `country` + `phone_number` + `client_secret` + /// triple. This is to avoid repeatedly sending the same SMS in + /// the case of request retries between the POSTing user and the + /// identity server. The client should increment this value if + /// they desire a new SMS (e.g. a reminder) to be sent. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenToResetPasswordMSISDN( + String clientSecret, String country, String phoneNumber, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/account/password/msisdn/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'country': country, + if (nextLink != null) 'next_link': nextLink, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + /// Gets information about the owner of a given access token. /// /// Note that, as with the rest of the Client-Server API, @@ -725,6 +1005,61 @@ class Api { return json as Map; } + /// Gets the visibility of a given room on the server's public room directory. + /// + /// [roomId] The room ID. + /// + /// returns `visibility`: + /// The visibility of the room in the directory. + Future getRoomVisibilityOnDirectory(String roomId) async { + final requestUri = Uri( + path: + '_matrix/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? {'public': Visibility.public, 'private': Visibility.private}[v]! + : null)(json['visibility']); + } + + /// Sets the visibility of a given room in the server's public room + /// directory. + /// + /// Servers may choose to implement additional access control checks + /// here, for instance that room visibility can only be changed by + /// the room creator or a server administrator. + /// + /// [roomId] The room ID. + /// + /// [visibility] The new visibility setting for the room. + /// Defaults to 'public'. + Future setRoomVisibilityOnDirectory(String roomId, + {Visibility? visibility}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}'); + final request = Request('PUT', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (visibility != null) + 'visibility': { + Visibility.public: 'public', + Visibility.private: 'private' + }[visibility]!, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + /// Remove a mapping of room alias to room ID. /// /// Servers may choose to implement additional access control checks here, for instance that @@ -795,6 +1130,68 @@ class Api { return ignore(json); } + /// This will listen for new events and return them to the caller. This will + /// block until an event is received, or until the `timeout` is reached. + /// + /// This endpoint was deprecated in r0 of this specification. Clients + /// should instead call the [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) + /// API with a `since` parameter. See + /// the [migration guide](https://matrix.org/docs/guides/migrating-from-client-server-api-v-1#deprecated-endpoints). + /// + /// [from] The token to stream from. This token is either from a previous + /// request to this API or from the initial sync API. + /// + /// [timeout] The maximum time in milliseconds to wait for an event. + @deprecated + Future getEvents({String? from, int? timeout}) async { + final requestUri = Uri(path: '_matrix/client/r0/events', queryParameters: { + if (from != null) 'from': from, + if (timeout != null) 'timeout': timeout.toString(), + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return EventsSyncUpdate.fromJson(json); + } + + /// This will listen for new events related to a particular room and return + /// them to the caller. This will block until an event is received, or until + /// the `timeout` is reached. + /// + /// This API is the same as the normal `/events` endpoint, but can be + /// called by users who have not joined the room. + /// + /// Note that the normal `/events` endpoint has been deprecated. This + /// API will also be deprecated at some point, but its replacement is not + /// yet known. + /// + /// [from] The token to stream from. This token is either from a previous + /// request to this API or from the initial sync API. + /// + /// [timeout] The maximum time in milliseconds to wait for an event. + /// + /// [roomId] The room ID for which events should be returned. + Future peekEvents( + {String? from, int? timeout, String? roomId}) async { + final requestUri = Uri(path: '_matrix/client/r0/events', queryParameters: { + if (from != null) 'from': from, + if (timeout != null) 'timeout': timeout.toString(), + if (roomId != null) 'room_id': roomId, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return EventsSyncUpdate.fromJson(json); + } + /// Get a single event based on `event_id`. You must have permission to /// retrieve this event e.g. by being a member in the room for this event. /// @@ -948,6 +1345,48 @@ class Api { return ClaimKeysResponse.fromJson(json); } + /// Publishes cross-signing keys for the user. + /// + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api). + /// + /// [auth] Additional authentication information for the + /// user-interactive authentication API. + /// + /// [masterKey] Optional. The user\'s master key. + /// + /// [selfSigningKey] Optional. The user\'s self-signing key. Must be signed by + /// the accompanying master key, or by the user\'s most recently + /// uploaded master key if no master key is included in the + /// request. + /// + /// [userSigningKey] Optional. The user\'s user-signing key. Must be signed by + /// the accompanying master key, or by the user\'s most recently + /// uploaded master key if no master key is included in the + /// request. + Future uploadCrossSigningKeys( + {AuthenticationData? auth, + MatrixCrossSigningKey? masterKey, + MatrixCrossSigningKey? selfSigningKey, + MatrixCrossSigningKey? userSigningKey}) async { + final requestUri = + Uri(path: '_matrix/client/unstable/keys/device_signing/upload'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + if (auth != null) 'auth': auth.toJson(), + if (masterKey != null) 'master_key': masterKey.toJson(), + if (selfSigningKey != null) 'self_signing_key': selfSigningKey.toJson(), + if (userSigningKey != null) 'user_signing_key': userSigningKey.toJson(), + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ignore(json); + } + /// Returns the current devices and identity keys for the given users. /// /// [deviceKeys] The keys to be downloaded. A map from user ID, to a list of @@ -981,6 +1420,36 @@ class Api { return QueryKeysResponse.fromJson(json); } + /// Publishes cross-signing signatures for the user. The request body is a + /// map from user ID to key ID to signed JSON object. + /// + /// [signatures] The signatures to be published. + /// + /// returns `failures`: + /// A map from user ID to key ID to an error for any signatures + /// that failed. If a signature was invalid, the `errcode` will + /// be set to `M_INVALID_SIGNATURE`. + Future>>?> + uploadCrossSigningSignatures( + Map>> signatures) async { + final requestUri = Uri(path: '_matrix/client/r0/keys/signatures/upload'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode(signatures)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return ((v) => v != null + ? (v as Map).map((k, v) => MapEntry( + k, + (v as Map) + .map((k, v) => MapEntry(k, v as Map)))) + : null)(json['failures']); + } + /// *Note that this API takes either a room ID or alias, unlike other membership APIs.* /// /// This API "knocks" on the room to ask for permission to join, if the user @@ -1856,12 +2325,173 @@ class Api { return ((v) => v != null ? v as bool : null)(json['available']); } + /// The homeserver must check that the given email address is **not** + /// already associated with an account on this homeserver. The homeserver + /// should validate the email itself, either by sending a validation email + /// itself or by using a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [email] The email address to validate. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [sendAttempt] The server will only send an email if the `send_attempt` + /// is a number greater than the most recent one which it has seen, + /// scoped to that `email` + `client_secret` pair. This is to + /// avoid repeatedly sending the same email in the case of request + /// retries between the POSTing user and the identity server. + /// The client should increment this value if they desire a new + /// email (e.g. a reminder) to be sent. If they do not, the server + /// should respond with success but not resend the email. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenToRegisterEmail( + String clientSecret, String email, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/register/email/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'email': email, + if (nextLink != null) 'next_link': nextLink, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + + /// The homeserver must check that the given phone number is **not** + /// already associated with an account on this homeserver. The homeserver + /// should validate the phone number itself, either by sending a validation + /// message itself or by using a service it has control over. + /// + /// [clientSecret] A unique string generated by the client, and used to identify the + /// validation attempt. It must be a string consisting of the characters + /// `[0-9a-zA-Z.=_-]`. Its length must not exceed 255 characters and it + /// must not be empty. + /// + /// + /// [country] The two-letter uppercase ISO-3166-1 alpha-2 country code that the + /// number in `phone_number` should be parsed as if it were dialled from. + /// + /// [nextLink] Optional. When the validation is completed, the identity server will + /// redirect the user to this URL. This option is ignored when submitting + /// 3PID validation information through a POST request. + /// + /// [phoneNumber] The phone number to validate. + /// + /// [sendAttempt] The server will only send an SMS if the `send_attempt` is a + /// number greater than the most recent one which it has seen, + /// scoped to that `country` + `phone_number` + `client_secret` + /// triple. This is to avoid repeatedly sending the same SMS in + /// the case of request retries between the POSTing user and the + /// identity server. The client should increment this value if + /// they desire a new SMS (e.g. a reminder) to be sent. + /// + /// [idAccessToken] An access token previously registered with the identity server. Servers + /// can treat this as optional to distinguish between r0.5-compatible clients + /// and this specification version. + /// + /// Required if an `id_server` is supplied. + /// + /// [idServer] The hostname of the identity server to communicate with. May optionally + /// include a port. This parameter is ignored when the homeserver handles + /// 3PID verification. + /// + /// This parameter is deprecated with a plan to be removed in a future specification + /// version for `/account/password` and `/register` requests. + Future requestTokenToRegisterMSISDN( + String clientSecret, String country, String phoneNumber, int sendAttempt, + {String? nextLink, String? idAccessToken, String? idServer}) async { + final requestUri = + Uri(path: '_matrix/client/r0/register/msisdn/requestToken'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'client_secret': clientSecret, + 'country': country, + if (nextLink != null) 'next_link': nextLink, + 'phone_number': phoneNumber, + 'send_attempt': sendAttempt, + if (idAccessToken != null) 'id_access_token': idAccessToken, + if (idServer != null) 'id_server': idServer, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RequestTokenResponse.fromJson(json); + } + + /// Delete the keys from the backup. + /// + /// [version] The backup from which to delete the key + Future deleteRoomKeys(String version) async { + final requestUri = + Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { + 'version': version, + }); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeysUpdateResponse.fromJson(json); + } + + /// Retrieve the keys from the backup. + /// + /// [version] The backup from which to retrieve the keys. + Future getRoomKeys(String version) async { + final requestUri = + Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { + 'version': version, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeys.fromJson(json); + } + /// Store several keys in the backup. /// /// [version] The backup in which to store the keys. Must be the current backup. /// /// [backupData] The backup data. - Future postRoomKeysKey( + Future putRoomKeys( String version, RoomKeys backupData) async { final requestUri = Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { @@ -1876,17 +2506,63 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PostRoomKeysKeyResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json); } - /// Store a key in the backup. + /// Delete the keys from the backup for a given room. + /// + /// [roomId] The ID of the room that the specified key is for. + /// + /// [version] The backup from which to delete the key. + Future deleteRoomKeysByRoomId( + String roomId, String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + queryParameters: { + 'version': version, + }); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeysUpdateResponse.fromJson(json); + } + + /// Retrieve the keys from the backup for a given room. + /// + /// [roomId] The ID of the room that the requested key is for. + /// + /// [version] The backup from which to retrieve the key. + Future getRoomKeysByRoomId( + String roomId, String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + queryParameters: { + 'version': version, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeyBackup.fromJson(json); + } + + /// Store several keys in the backup for a given room. /// /// [roomId] The ID of the room that the keys are for. /// /// [version] The backup in which to store the keys. Must be the current backup. /// /// [backupData] The backup data - Future postRoomKeysKeyRoomId( + Future putRoomKeysByRoomId( String roomId, String version, RoomKeyBackup backupData) async { final requestUri = Uri( path: @@ -1903,7 +2579,57 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PostRoomKeysKeyRoomIdResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json); + } + + /// Delete a key from the backup. + /// + /// [roomId] The ID of the room that the specified key is for. + /// + /// [sessionId] The ID of the megolm session whose key is to be deleted. + /// + /// [version] The backup from which to delete the key + Future deleteRoomKeysBySessionId( + String roomId, String sessionId, String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + queryParameters: { + 'version': version, + }); + final request = Request('DELETE', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RoomKeysUpdateResponse.fromJson(json); + } + + /// Retrieve a key from the backup. + /// + /// [roomId] The ID of the room that the requested key is for. + /// + /// [sessionId] The ID of the megolm session whose key is requested. + /// + /// [version] The backup from which to retrieve the key. + Future getRoomKeysBySessionId( + String roomId, String sessionId, String version) async { + final requestUri = Uri( + path: + '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + queryParameters: { + 'version': version, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return KeyBackupData.fromJson(json); } /// Store a key in the backup. @@ -1915,11 +2641,8 @@ class Api { /// [version] The backup in which to store the key. Must be the current backup. /// /// [data] The key data. - Future postRoomKeysKeyRoomIdSessionId( - String roomId, - String sessionId, - String version, - KeyBackupData data) async { + Future putRoomKeysBySessionId(String roomId, + String sessionId, String version, KeyBackupData data) async { final requestUri = Uri( path: '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', @@ -1935,7 +2658,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PostRoomKeysKeyRoomIdSessionIdResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json); } /// Get information about the latest backup version. @@ -3036,6 +3759,131 @@ class Api { return SyncUpdate.fromJson(json); } + /// Retrieve an array of third party network locations from a Matrix room + /// alias. + /// + /// [alias] The Matrix room alias to look up. + Future> queryLocationByAlias(String alias) async { + final requestUri = + Uri(path: '_matrix/client/r0/thirdparty/location', queryParameters: { + 'alias': alias, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => Location.fromJson(v)).toList(); + } + + /// Requesting this endpoint with a valid protocol name results in a list + /// of successful mapping results in a JSON array. Each result contains + /// objects to represent the Matrix room or rooms that represent a portal + /// to this third party network. Each has the Matrix room alias string, + /// an identifier for the particular third party network protocol, and an + /// object containing the network-specific fields that comprise this + /// identifier. It should attempt to canonicalise the identifier as much + /// as reasonably possible given the network type. + /// + /// [protocol] The protocol used to communicate to the third party network. + /// + /// [searchFields] One or more custom fields to help identify the third party + /// location. + Future> queryLocationByProtocol(String protocol, + {String? searchFields}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/thirdparty/location/${Uri.encodeComponent(protocol)}', + queryParameters: { + if (searchFields != null) 'searchFields': searchFields, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => Location.fromJson(v)).toList(); + } + + /// Fetches the metadata from the homeserver about a particular third party protocol. + /// + /// [protocol] The name of the protocol. + Future getProtocolMetadata(String protocol) async { + final requestUri = Uri( + path: + '_matrix/client/r0/thirdparty/protocol/${Uri.encodeComponent(protocol)}'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return Protocol.fromJson(json); + } + + /// Fetches the overall metadata about protocols supported by the + /// homeserver. Includes both the available protocols and all fields + /// required for queries against each protocol. + Future> getProtocols() async { + final requestUri = Uri(path: '_matrix/client/r0/thirdparty/protocols'); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as Map) + .map((k, v) => MapEntry(k, Protocol.fromJson(v))); + } + + /// Retrieve an array of third party users from a Matrix User ID. + /// + /// [userid] The Matrix User ID to look up. + Future> queryUserByID(String userid) async { + final requestUri = + Uri(path: '_matrix/client/r0/thirdparty/user', queryParameters: { + 'userid': userid, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => ThirdPartyUser.fromJson(v)).toList(); + } + + /// Retrieve a Matrix User ID linked to a user on the third party service, given + /// a set of user parameters. + /// + /// [protocol] The name of the protocol. + /// + /// [fields] One or more custom fields that are passed to the AS to help identify the user. + Future> queryUserByProtocol(String protocol, + {String? fields}) async { + final requestUri = Uri( + path: + '_matrix/client/r0/thirdparty/user/${Uri.encodeComponent(protocol)}', + queryParameters: { + if (fields != null) 'fields...': fields, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return (json as List).map((v) => ThirdPartyUser.fromJson(v)).toList(); + } + /// Get some account_data for the client. This config is only visible to the user /// that set the account_data. /// @@ -3531,16 +4379,16 @@ class Api { /// uploadContent /// - /// [contentType] The content type of the file being uploaded - /// /// [filename] The name of the file being uploaded /// /// [content] The content to be uploaded. /// + /// [contentType] The content type of the file being uploaded + /// /// returns `content_uri`: /// The [MXC URI](https://spec.matrix.org/unstable/client-server-api/#matrix-content-mxc-uris) to the uploaded content. Future uploadContent(Uint8List content, - {String? contentType, String? filename}) async { + {String? filename, String? contentType}) async { final requestUri = Uri(path: '_matrix/media/r0/upload', queryParameters: { if (filename != null) 'filename': filename, }); diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index 324c5822..f4f5f2e0 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -165,6 +165,43 @@ class ThreePidCredentials { @_NameSource('generated') enum IdServerUnbindResult { noSupport, success } +@_NameSource('spec') +class RequestTokenResponse { + RequestTokenResponse({ + required this.sid, + this.submitUrl, + }); + + RequestTokenResponse.fromJson(Map json) + : sid = json['sid'] as String, + submitUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['submit_url']); + Map toJson() { + final submitUrl = this.submitUrl; + return { + 'sid': sid, + if (submitUrl != null) 'submit_url': submitUrl.toString(), + }; + } + + /// The session ID. Session IDs are opaque strings that must consist entirely + /// of the characters `[0-9a-zA-Z.=_-]`. Their length must not exceed 255 + /// characters and they must not be empty. + String sid; + + /// An optional field containing a URL where the client must submit the + /// validation token to, with identical parameters to the Identity Service + /// API's `POST /validate/email/submitToken` endpoint (without the requirement + /// for an access token). The homeserver must send this token to the user (if + /// applicable), who should then be prompted to provide it to the client. + /// + /// If this field is not present, the client can assume that verification + /// will happen without the client's involvement provided the homeserver + /// advertises this specification version in the `/versions` response + /// (ie: r0.5.0). + Uri? submitUrl; +} + @_NameSource('rule override generated') class TokenOwnerInfo { TokenOwnerInfo({ @@ -539,6 +576,43 @@ class GetRoomIdByAliasResponse { List? servers; } +@_NameSource('rule override generated') +class EventsSyncUpdate { + EventsSyncUpdate({ + this.chunk, + this.end, + this.start, + }); + + EventsSyncUpdate.fromJson(Map json) + : chunk = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['chunk']), + end = ((v) => v != null ? v as String : null)(json['end']), + start = ((v) => v != null ? v as String : null)(json['start']); + Map toJson() { + final chunk = this.chunk; + final end = this.end; + final start = this.start; + return { + if (chunk != null) 'chunk': chunk.map((v) => v.toJson()).toList(), + if (end != null) 'end': end, + if (start != null) 'start': start, + }; + } + + /// An array of events. + List? chunk; + + /// A token which correlates to the last value in `chunk`. This + /// token should be used in the next request to `/events`. + String? end; + + /// A token which correlates to the first value in `chunk`. This + /// is usually the same token supplied to `from=`. + String? start; +} + /// 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. @_NameSource('spec') @@ -1522,6 +1596,29 @@ class RegisterResponse { String userId; } +@_NameSource('spec') +class RoomKeysUpdateResponse { + RoomKeysUpdateResponse({ + required this.count, + required this.etag, + }); + + RoomKeysUpdateResponse.fromJson(Map json) + : count = json['count'] as int, + etag = json['etag'] as String; + Map toJson() => { + 'count': count, + 'etag': etag, + }; + + /// The number of keys stored in the backup + int count; + + /// The new etag value representing stored keys in the backup. + /// See `GET /room_keys/version/{version}` for more details. + String etag; +} + /// The key data @_NameSource('spec') class KeyBackupData { @@ -1595,75 +1692,6 @@ class RoomKeys { Map rooms; } -@_NameSource('generated') -class PostRoomKeysKeyResponse { - PostRoomKeysKeyResponse({ - required this.count, - required this.etag, - }); - - PostRoomKeysKeyResponse.fromJson(Map json) - : count = json['count'] as int, - etag = json['etag'] as String; - Map toJson() => { - 'count': count, - 'etag': etag, - }; - - /// The number of keys stored in the backup - int count; - - /// The new etag value representing stored keys in the backup. - /// See `GET /room_keys/version/{version}` for more details. - String etag; -} - -@_NameSource('generated') -class PostRoomKeysKeyRoomIdResponse { - PostRoomKeysKeyRoomIdResponse({ - required this.count, - required this.etag, - }); - - PostRoomKeysKeyRoomIdResponse.fromJson(Map json) - : count = json['count'] as int, - etag = json['etag'] as String; - Map toJson() => { - 'count': count, - 'etag': etag, - }; - - /// The number of keys stored in the backup - int count; - - /// The new etag value representing stored keys in the backup. - /// See `GET /room_keys/version/{version}` for more details. - String etag; -} - -@_NameSource('generated') -class PostRoomKeysKeyRoomIdSessionIdResponse { - PostRoomKeysKeyRoomIdSessionIdResponse({ - required this.count, - required this.etag, - }); - - PostRoomKeysKeyRoomIdSessionIdResponse.fromJson(Map json) - : count = json['count'] as int, - etag = json['etag'] as String; - Map toJson() => { - 'count': count, - 'etag': etag, - }; - - /// The number of keys stored in the backup - int count; - - /// The new etag value representing stored keys in the backup. - /// See `GET /room_keys/version/{version}` for more details. - String etag; -} - @_NameSource('rule override generated') enum BackupAlgorithm { mMegolmBackupV1Curve25519AesSha2 } @@ -2635,6 +2663,182 @@ class SearchResults { ResultCategories searchCategories; } +@_NameSource('spec') +class Location { + Location({ + required this.alias, + required this.fields, + required this.protocol, + }); + + Location.fromJson(Map json) + : alias = json['alias'] as String, + fields = json['fields'] as Map, + protocol = json['protocol'] as String; + Map toJson() => { + 'alias': alias, + 'fields': fields, + 'protocol': protocol, + }; + + /// An alias for a matrix room. + String alias; + + /// Information used to identify this third party location. + Map fields; + + /// The protocol ID that the third party location is a part of. + String protocol; +} + +/// Definition of valid values for a field. +@_NameSource('spec') +class FieldType { + FieldType({ + required this.placeholder, + required this.regexp, + }); + + FieldType.fromJson(Map json) + : placeholder = json['placeholder'] as String, + regexp = json['regexp'] as String; + Map toJson() => { + 'placeholder': placeholder, + 'regexp': regexp, + }; + + /// An placeholder serving as a valid example of the field value. + String placeholder; + + /// A regular expression for validation of a field's value. This may be relatively + /// coarse to verify the value as the application service providing this protocol + /// may apply additional validation or filtering. + String regexp; +} + +@_NameSource('spec') +class ProtocolInstance { + ProtocolInstance({ + required this.desc, + required this.fields, + this.icon, + required this.networkId, + }); + + ProtocolInstance.fromJson(Map json) + : desc = json['desc'] as String, + fields = json['fields'] as Map, + icon = ((v) => v != null ? v as String : null)(json['icon']), + networkId = json['network_id'] as String; + Map toJson() { + final icon = this.icon; + return { + 'desc': desc, + 'fields': fields, + if (icon != null) 'icon': icon, + 'network_id': networkId, + }; + } + + /// A human-readable description for the protocol, such as the name. + String desc; + + /// Preset values for `fields` the client may use to search by. + Map fields; + + /// An optional content URI representing the protocol. Overrides the one provided + /// at the higher level Protocol object. + String? icon; + + /// A unique identifier across all instances. + String networkId; +} + +@_NameSource('spec') +class Protocol { + Protocol({ + required this.fieldTypes, + required this.icon, + required this.instances, + required this.locationFields, + required this.userFields, + }); + + Protocol.fromJson(Map json) + : fieldTypes = (json['field_types'] as Map) + .map((k, v) => MapEntry(k, FieldType.fromJson(v))), + icon = json['icon'] as String, + instances = (json['instances'] as List) + .map((v) => ProtocolInstance.fromJson(v)) + .toList(), + locationFields = + (json['location_fields'] as List).map((v) => v as String).toList(), + userFields = + (json['user_fields'] as List).map((v) => v as String).toList(); + Map toJson() => { + 'field_types': fieldTypes.map((k, v) => MapEntry(k, v.toJson())), + 'icon': icon, + 'instances': instances.map((v) => v.toJson()).toList(), + 'location_fields': locationFields.map((v) => v).toList(), + 'user_fields': userFields.map((v) => v).toList(), + }; + + /// The type definitions for the fields defined in the `user_fields` and + /// `location_fields`. Each entry in those arrays MUST have an entry here. The + /// `string` key for this object is field name itself. + /// + /// May be an empty object if no fields are defined. + Map fieldTypes; + + /// A content URI representing an icon for the third party protocol. + String icon; + + /// A list of objects representing independent instances of configuration. + /// For example, multiple networks on IRC if multiple are provided by the + /// same application service. + List instances; + + /// Fields which may be used to identify a third party location. These should be + /// ordered to suggest the way that entities may be grouped, where higher + /// groupings are ordered first. For example, the name of a network should be + /// searched before the name of a channel. + List locationFields; + + /// Fields which may be used to identify a third party user. These should be + /// ordered to suggest the way that entities may be grouped, where higher + /// groupings are ordered first. For example, the name of a network should be + /// searched before the nickname of a user. + List userFields; +} + +@_NameSource('rule override spec') +class ThirdPartyUser { + ThirdPartyUser({ + required this.fields, + required this.protocol, + required this.userid, + }); + + ThirdPartyUser.fromJson(Map json) + : fields = json['fields'] as Map, + protocol = json['protocol'] as String, + userid = json['userid'] as String; + Map toJson() => { + 'fields': fields, + 'protocol': protocol, + 'userid': userid, + }; + + /// Information used to identify this third party location. + Map fields; + + /// The protocol ID that the third party location is a part of. + String protocol; + + /// A Matrix User ID represting a third party user. + String userid; +} + @_NameSource('generated') enum EventFormat { client, federation } diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 88859870..f64b633c 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -29,27 +29,13 @@ import 'package:http/http.dart' as http; import '../matrix_api_lite.dart'; import 'generated/api.dart'; -import 'model/auth/authentication_data.dart'; -import 'model/events_sync_update.dart'; import 'model/matrix_connection_exception.dart'; import 'model/matrix_exception.dart'; import 'model/matrix_keys.dart'; -import 'model/request_token_response.dart'; -import 'model/room_keys_keys.dart'; -import 'model/supported_protocol.dart'; -import 'model/third_party_location.dart'; -import 'model/third_party_user.dart'; import 'model/upload_key_signatures_response.dart'; enum RequestType { GET, POST, PUT, DELETE } -String describeEnum(Object enumEntry) { - final description = enumEntry.toString(); - final indexOfDot = description.indexOf('.'); - assert(indexOfDot != -1 && indexOfDot < description.length - 1); - return description.substring(indexOfDot + 1); -} - class MatrixApi extends Api { /// The homeserver this client is communicating with. Uri? get homeserver => baseUri; @@ -164,203 +150,6 @@ class MatrixApi extends Api { return jsonResp!; } - /// The homeserver must check that the given email address is not already associated - /// with an account on this homeserver. The homeserver should validate the email - /// itself, either by sending a validation email itself or by using a service it - /// has control over. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register-email-requesttoken - Future requestEmailToken( - String email, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/register/email/requestToken', - data: { - 'email': email, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// The homeserver must check that the given phone number is not already associated with an - /// account on this homeserver. The homeserver should validate the phone number itself, - /// either by sending a validation message itself or by using a service it has control over. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register-msisdn-requesttoken - Future requestMsisdnToken( - String country, - String phoneNumber, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/register/msisdn/requestToken', - data: { - 'country': country, - 'phone_number': phoneNumber, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// The homeserver must check that the given email address is associated with - /// an account on this homeserver. This API should be used to request - /// validation tokens when authenticating for the /account/password endpoint. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password-email-requesttoken - Future resetPasswordUsingEmail( - String email, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/password/email/requestToken', - data: { - 'email': email, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// The homeserver must check that the given phone number is associated with - /// an account on this homeserver. This API should be used to request validation - /// tokens when authenticating for the /account/password endpoint. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password-msisdn-requesttoken - Future resetPasswordUsingMsisdn( - String country, - String phoneNumber, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/password/msisdn/requestToken', - data: { - 'country': country, - 'phone_number': phoneNumber, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// This API should be used to request validation tokens when adding an email address to an account. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-email-requesttoken - Future requestEmailValidationToken( - String email, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/3pid/email/requestToken', - data: { - 'email': email, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// This API should be used to request validation tokens when adding a phone number to an account. - /// https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-msisdn-requesttoken - Future requestMsisdnValidationToken( - String country, - String phoneNumber, - String clientSecret, - int sendAttempt, { - String? nextLink, - String? idServer, - String? idAccessToken, - }) async { - final response = await request( - RequestType.POST, '/client/r0/account/3pid/msisdn/requestToken', - data: { - 'country': country, - 'phone_number': phoneNumber, - 'send_attempt': sendAttempt, - 'client_secret': clientSecret, - if (nextLink != null) 'next_link': nextLink, - if (idServer != null) 'id_server': idServer, - if (idAccessToken != null) 'id_access_token': idAccessToken, - }); - return RequestTokenResponse.fromJson(response); - } - - /// Looks up the contents of a state event in a room. If the user is joined to the room then the - /// state is taken from the current state of the room. If the user has left the room then the - /// state is taken from the state of the room when they left. - /// https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-state-eventtype-statekey - Future> requestStateContent( - String roomId, String eventType, - [String? stateKey]) async { - var url = - '/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/'; - if (stateKey != null) { - url += Uri.encodeComponent(stateKey); - } - final response = await request( - RequestType.GET, - url, - ); - return response; - } - - /// Gets the visibility of a given room on the server's public room directory. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-directory-list-room-roomid - Future getRoomVisibilityOnDirectory(String roomId) async { - final response = await request( - RequestType.GET, - '/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}', - ); - return Visibility.values - .firstWhere((v) => describeEnum(v) == response['visibility']); - } - - /// Sets the visibility of a given room in the server's public room directory. - /// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-directory-list-room-roomid - Future setRoomVisibilityOnDirectory( - String roomId, Visibility visibility) async { - await request( - RequestType.PUT, - '/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}', - data: { - 'visibility': describeEnum(visibility), - }, - ); - return; - } - /// Publishes end-to-end encryption keys for the device. /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query Future> uploadKeys( @@ -382,26 +171,6 @@ class MatrixApi extends Api { return Map.from(response['one_time_key_counts']); } - /// Uploads your own cross-signing keys. - /// https://github.com/matrix-org/matrix-doc/pull/2536 - Future uploadDeviceSigningKeys({ - MatrixCrossSigningKey? masterKey, - MatrixCrossSigningKey? selfSigningKey, - MatrixCrossSigningKey? userSigningKey, - AuthenticationData? auth, - }) async { - await request( - RequestType.POST, - '/client/unstable/keys/device_signing/upload', - data: { - if (masterKey != null) 'master_key': masterKey.toJson(), - if (selfSigningKey != null) 'self_signing_key': selfSigningKey.toJson(), - if (userSigningKey != null) 'user_signing_key': userSigningKey.toJson(), - if (auth != null) 'auth': auth.toJson(), - }, - ); - } - /// Uploads new signatures of keys /// https://github.com/matrix-org/matrix-doc/pull/2536 Future uploadKeySignatures( @@ -449,174 +218,4 @@ class MatrixApi extends Api { ); return; } - - /// This will listen for new events related to a particular room and return them to the - /// caller. This will block until an event is received, or until the timeout is reached. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-events - Future getEvents({ - String? from, - int? timeout, - String? roomId, - }) async { - final response = - await request(RequestType.GET, '/client/r0/events', query: { - if (from != null) 'from': from, - if (timeout != null) 'timeout': timeout.toString(), - if (roomId != null) 'roomId': roomId, - }); - return EventsSyncUpdate.fromJson(response); - } - - /// Fetches the overall metadata about protocols supported by the homeserver. Includes - /// both the available protocols and all fields required for queries against each protocol. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-protocols - Future> requestSupportedProtocols() async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/protocols', - ); - return response.map((k, v) => MapEntry(k, SupportedProtocol.fromJson(v))); - } - - /// Fetches the metadata from the homeserver about a particular third party protocol. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-protocol-protocol - Future requestSupportedProtocol(String protocol) async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/protocol/${Uri.encodeComponent(protocol)}', - ); - return SupportedProtocol.fromJson(response); - } - - /// Requesting this endpoint with a valid protocol name results in a list of successful - /// mapping results in a JSON array. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-location-protocol - Future> requestThirdPartyLocations( - String protocol) async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/location/${Uri.encodeComponent(protocol)}', - ); - return (response['chunk'] as List) - .map((i) => ThirdPartyLocation.fromJson(i)) - .toList(); - } - - /// Retrieve a Matrix User ID linked to a user on the third party service, given a set of - /// user parameters. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-user-protocol - Future> requestThirdPartyUsers(String protocol) async { - final response = await request( - RequestType.GET, - '/client/r0/thirdparty/user/${Uri.encodeComponent(protocol)}', - ); - return (response['chunk'] as List) - .map((i) => ThirdPartyUser.fromJson(i)) - .toList(); - } - - /// Retrieve an array of third party network locations from a Matrix room alias. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-location - Future> requestThirdPartyLocationsByAlias( - String alias) async { - final response = await request( - RequestType.GET, '/client/r0/thirdparty/location', - query: { - 'alias': alias, - }); - return (response['chunk'] as List) - .map((i) => ThirdPartyLocation.fromJson(i)) - .toList(); - } - - /// Retrieve an array of third party users from a Matrix User ID. - /// https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-thirdparty-user - Future> requestThirdPartyUsersByUserId( - String userId) async { - final response = - await request(RequestType.GET, '/client/r0/thirdparty/user', query: { - 'userid': userId, - }); - return (response['chunk'] as List) - .map((i) => ThirdPartyUser.fromJson(i)) - .toList(); - } - - /// Deletes a room key backup - /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-version-version - Future deleteRoomKeysBackup(String version) async { - await request( - RequestType.DELETE, - '/client/unstable/room_keys/version/${Uri.encodeComponent(version)}', - ); - } - - /// Gets a single room key - /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys-roomid-sessionid - Future getRoomKeysSingleKey( - String roomId, String sessionId, String version) async { - final ret = await request( - RequestType.GET, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', - query: {'version': version}, - ); - return RoomKeysSingleKey.fromJson(ret); - } - - /// Deletes a single room key - /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys-roomid-sessionid - Future deleteRoomKeysSingleKey( - String roomId, String sessionId, String version) async { - final ret = await request( - RequestType.DELETE, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', - query: {'version': version}, - ); - return RoomKeysUpdateResponse.fromJson(ret); - } - - /// Gets room keys for a room - /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys-roomid - Future getRoomKeysRoom(String roomId, String version) async { - final ret = await request( - RequestType.GET, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', - query: {'version': version}, - ); - return RoomKeysRoom.fromJson(ret); - } - - /// Deletes room keys for a room - /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys-roomid - Future deleteRoomKeysRoom( - String roomId, String version) async { - final ret = await request( - RequestType.DELETE, - '/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', - query: {'version': version}, - ); - return RoomKeysUpdateResponse.fromJson(ret); - } - - /// get all room keys - /// https://matrix.org/docs/spec/client_server/unstable#get-matrix-client-r0-room-keys-keys - Future getRoomKeys(String version) async { - final ret = await request( - RequestType.GET, - '/client/unstable/room_keys/keys', - query: {'version': version}, - ); - return RoomKeys.fromJson(ret); - } - - /// delete all room keys - /// https://matrix.org/docs/spec/client_server/unstable#delete-matrix-client-r0-room-keys-keys - Future deleteRoomKeys(String version) async { - final ret = await request( - RequestType.DELETE, - '/client/unstable/room_keys/keys', - query: {'version': version}, - ); - return RoomKeysUpdateResponse.fromJson(ret); - } } diff --git a/lib/src/model/events_sync_update.dart b/lib/src/model/events_sync_update.dart deleted file mode 100644 index 2f35ac74..00000000 --- a/lib/src/model/events_sync_update.dart +++ /dev/null @@ -1,53 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'matrix_event.dart'; - -class EventsSyncUpdate { - String? start; - String? end; - List? chunk; - - EventsSyncUpdate.fromJson(Map json) - : start = json['start'], - end = json['end'], - chunk = json['chunk'] != null - ? (json['chunk'] as List) - .map((i) => MatrixEvent.fromJson(i)) - .toList() - : null; - - Map toJson() { - final data = {}; - if (start != null) { - data['start'] = start; - } - if (end != null) { - data['end'] = end; - } - if (chunk != null) { - data['chunk'] = chunk!.map((i) => i.toJson()).toList(); - } - return data; - } -} diff --git a/lib/src/model/request_token_response.dart b/lib/src/model/request_token_response.dart deleted file mode 100644 index 4be5d726..00000000 --- a/lib/src/model/request_token_response.dart +++ /dev/null @@ -1,38 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class RequestTokenResponse { - String sid; - String? submitUrl; - - RequestTokenResponse.fromJson(Map json) - : sid = json['sid'], - submitUrl = json['submit_url']; - - Map toJson() { - final data = {}; - data['sid'] = sid; - data['submit_url'] = submitUrl; - return data; - } -} diff --git a/lib/src/model/supported_protocol.dart b/lib/src/model/supported_protocol.dart deleted file mode 100644 index 0f1fcf50..00000000 --- a/lib/src/model/supported_protocol.dart +++ /dev/null @@ -1,91 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -class SupportedProtocol { - List userFields; - List locationFields; - String icon; - Map fieldTypes; - List instances; - - SupportedProtocol.fromJson(Map json) - : userFields = json['user_fields'].cast(), - locationFields = json['location_fields'].cast(), - icon = json['icon'], - fieldTypes = (json['field_types'] as Map) - .map((k, v) => MapEntry(k, ProtocolFieldType.fromJson(v))), - instances = (json['instances'] as List) - .map((v) => ProtocolInstance.fromJson(v)) - .toList(); - - Map toJson() { - final data = {}; - data['user_fields'] = userFields; - data['location_fields'] = locationFields; - data['icon'] = icon; - data['field_types'] = fieldTypes.map((k, v) => MapEntry(k, v.toJson())); - data['instances'] = instances.map((v) => v.toJson()).toList(); - return data; - } -} - -class ProtocolFieldType { - String regexp; - String placeholder; - - ProtocolFieldType.fromJson(Map json) - : regexp = json['regexp'], - placeholder = json['placeholder']; - - Map toJson() { - final data = {}; - data['regexp'] = regexp; - data['placeholder'] = placeholder; - return data; - } -} - -class ProtocolInstance { - String networkId; - String desc; - String? icon; - dynamic fields; - - ProtocolInstance.fromJson(Map json) - : networkId = json['network_id'], - desc = json['desc'], - icon = json['icon'], - fields = json['fields']; - - Map toJson() { - final data = {}; - data['network_id'] = networkId; - data['desc'] = desc; - if (icon != null) { - data['icon'] = icon; - } - data['fields'] = fields; - - return data; - } -} diff --git a/lib/src/model/third_party_location.dart b/lib/src/model/third_party_location.dart deleted file mode 100644 index a2271f9b..00000000 --- a/lib/src/model/third_party_location.dart +++ /dev/null @@ -1,43 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import '../utils/map_copy_extension.dart'; - -class ThirdPartyLocation { - String alias; - String protocol; - Map fields; - - ThirdPartyLocation.fromJson(Map json) - : alias = json['alias'], - protocol = json['protocol'], - fields = (json['fields'] as Map).copy(); - - Map toJson() { - final data = {}; - data['alias'] = alias; - data['protocol'] = protocol; - data['fields'] = fields; - return data; - } -} diff --git a/lib/src/model/third_party_user.dart b/lib/src/model/third_party_user.dart deleted file mode 100644 index a4289b2a..00000000 --- a/lib/src/model/third_party_user.dart +++ /dev/null @@ -1,43 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import '../utils/map_copy_extension.dart'; - -class ThirdPartyUser { - String userId; - String protocol; - Map fields; - - ThirdPartyUser.fromJson(Map json) - : userId = json['userid'], - protocol = json['protocol'], - fields = (json['fields'] as Map).copy(); - - Map toJson() { - final data = {}; - data['userid'] = userId; - data['protocol'] = protocol; - data['fields'] = fields; - return data; - } -} diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 15050e2c..d5fecb78 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -180,10 +180,10 @@ void main() { registerResponse.toJson()); matrixApi.homeserver = null; }); - test('requestEmailToken', () async { + test('requestTokenToRegisterEmail', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestEmailToken( + final response = await matrixApi.requestTokenToRegisterEmail( 'alice@example.com', '1234', 1, @@ -197,10 +197,10 @@ void main() { response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestMsisdnToken', () async { + test('requestTokenToRegisterMSISDN', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestMsisdnToken( + final response = await matrixApi.requestTokenToRegisterMSISDN( 'en', '1234', '1234', @@ -228,10 +228,10 @@ void main() { ); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('resetPasswordUsingEmail', () async { + test('requestTokenToResetPasswordEmail', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.resetPasswordUsingEmail( + await matrixApi.requestTokenToResetPasswordEmail( 'alice@example.com', '1234', 1, @@ -241,10 +241,10 @@ void main() { ); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('resetPasswordUsingMsisdn', () async { + test('requestTokenToResetPasswordMSISDN', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.resetPasswordUsingMsisdn( + await matrixApi.requestTokenToResetPasswordMSISDN( 'en', '1234', '1234', @@ -324,10 +324,10 @@ void main() { expect(response, IdServerUnbindResult.success); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestEmailValidationToken', () async { + test('requestTokenTo3PIDEmail', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestEmailValidationToken( + await matrixApi.requestTokenTo3PIDEmail( 'alice@example.com', '1234', 1, @@ -337,10 +337,10 @@ void main() { ); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestMsisdnValidationToken', () async { + test('requestTokenTo3PIDMSISDN', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestMsisdnValidationToken( + await matrixApi.requestTokenTo3PIDMSISDN( 'en', '1234', '1234', @@ -351,7 +351,7 @@ void main() { ); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestMsisdnValidationToken', () async { + test('requestTokenTo3PIDMSISDN', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getTokenOwner(); @@ -511,11 +511,11 @@ void main() { expect(event.eventId, '143273582443PhrSn:example.org'); matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestStateContent', () async { + test('getRoomStateWithKey', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.requestStateContent( + await matrixApi.getRoomStateWithKey( '!localpart:server.abc', 'm.room.member', '@getme:example.com', @@ -811,8 +811,8 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.setRoomVisibilityOnDirectory( - '!localpart:example.com', Visibility.private); + await matrixApi.setRoomVisibilityOnDirectory('!localpart:example.com', + visibility: Visibility.private); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -1151,7 +1151,7 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('uploadDeviceSigningKeys', () async { + test('uploadCrossSigningKeys', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1182,7 +1182,7 @@ void main() { }, 'signatures': {}, }); - await matrixApi.uploadDeviceSigningKeys( + await matrixApi.uploadCrossSigningKeys( masterKey: masterKey, selfSigningKey: selfSigningKey, userSigningKey: userSigningKey); @@ -1400,11 +1400,11 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = - await matrixApi.getEvents(from: '1234', roomId: '!1234', timeout: 10); + final response = await matrixApi.peekEvents( + from: '1234', roomId: '!1234', timeout: 10); expect( FakeMatrixApi.api['GET']![ - '/client/r0/events?from=1234&timeout=10&roomId=%211234']({}), + '/client/r0/events?from=1234&timeout=10&room_id=%211234']({}), response.toJson(), ); @@ -1537,11 +1537,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestSupportedProtocols', () async { + test('getProtocols', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestSupportedProtocols(); + final response = await matrixApi.getProtocols(); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/protocols']({}), response.map((k, v) => MapEntry(k, v.toJson())), @@ -1549,11 +1549,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestSupportedProtocol', () async { + test('getProtocol', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestSupportedProtocol('irc'); + final response = await matrixApi.getProtocolMetadata('irc'); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/protocol/irc']({}), response.toJson(), @@ -1561,11 +1561,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestThirdPartyLocations', () async { + test('queryLocationByProtocol', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestThirdPartyLocations('irc'); + final response = await matrixApi.queryLocationByProtocol('irc'); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/location/irc']({}), response.map((i) => i.toJson()).toList(), @@ -1573,11 +1573,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestThirdPartyUsers', () async { + test('queryUserByProtocol', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestThirdPartyUsers('irc'); + final response = await matrixApi.queryUserByProtocol('irc'); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/user/irc']({}), response.map((i) => i.toJson()).toList(), @@ -1585,12 +1585,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestThirdPartyLocationsByAlias', () async { + test('queryLocationByAlias', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = - await matrixApi.requestThirdPartyLocationsByAlias('1234'); + final response = await matrixApi.queryLocationByAlias('1234'); expect( FakeMatrixApi .api['GET']!['/client/r0/thirdparty/location?alias=1234']({}), @@ -1599,11 +1598,11 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); - test('requestThirdPartyUsersByUserId', () async { + test('queryUserByID', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - final response = await matrixApi.requestThirdPartyUsersByUserId('1234'); + final response = await matrixApi.queryUserByID('1234'); expect( FakeMatrixApi.api['GET']!['/client/r0/thirdparty/user?userid=1234']({}), response.map((i) => i.toJson()).toList(), @@ -1667,13 +1666,13 @@ void main() { }; await matrixApi.putRoomKeysVersion('5', algorithm, authData); }); - test('deleteRoomKeysBackup', () async { + test('deleteRoomKeys', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; - await matrixApi.deleteRoomKeysBackup('5'); + await matrixApi.deleteRoomKeys('5'); }); - test('postRoomKeysKeyRoomIdSessionId', () async { + test('putRoomKeysBySessionId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1690,39 +1689,40 @@ void main() { 'mac': 'QzKV/fgAs4U', }, }); - final ret = await matrixApi.postRoomKeysKeyRoomIdSessionId( + final ret = await matrixApi.putRoomKeysBySessionId( roomId, sessionId, '5', session); expect( FakeMatrixApi.api['PUT']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); - test('getRoomKeysSingleKey', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final ret = await matrixApi.getRoomKeysSingleKey(roomId, sessionId, '5'); - expect( - FakeMatrixApi.api['GET']![ - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), - ret.toJson()); - }); - test('deleteRoomKeysSingleKey', () async { + test('getRoomKeysBySessionId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; final ret = - await matrixApi.deleteRoomKeysSingleKey(roomId, sessionId, '5'); + await matrixApi.getRoomKeysBySessionId(roomId, sessionId, '5'); + expect( + FakeMatrixApi.api['GET']![ + '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + ret.toJson()); + }); + test('deleteRoomKeysBySessionId', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final ret = + await matrixApi.deleteRoomKeysBySessionId(roomId, sessionId, '5'); expect( FakeMatrixApi.api['DELETE']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); - test('postRoomKeysKeyRoomId', () async { + test('putRoomKeysByRoomId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1743,35 +1743,35 @@ void main() { }, }, }); - final ret = await matrixApi.postRoomKeysKeyRoomId(roomId, '5', session); + final ret = await matrixApi.putRoomKeysByRoomId(roomId, '5', session); expect( FakeMatrixApi.api['PUT']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); - test('getRoomKeysRoom', () async { + test('getRoomKeysByRoomId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; - final ret = await matrixApi.getRoomKeysRoom(roomId, '5'); + final ret = await matrixApi.getRoomKeysByRoomId(roomId, '5'); expect( FakeMatrixApi.api['GET']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); - test('deleteRoomKeysRoom', () async { + test('deleteRoomKeysByRoomId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; - final ret = await matrixApi.deleteRoomKeysRoom(roomId, '5'); + final ret = await matrixApi.deleteRoomKeysByRoomId(roomId, '5'); expect( FakeMatrixApi.api['DELETE']![ '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); - test('postRoomKeysKey', () async { + test('putRoomKeys', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1796,7 +1796,7 @@ void main() { }, }, }); - final ret = await matrixApi.postRoomKeysKey('5', session); + final ret = await matrixApi.putRoomKeys('5', session); expect( FakeMatrixApi .api['PUT']!['/client/unstable/room_keys/keys?version=5']({}), From d16c83f5dbfc513cd8692bfdd5d2ab01dfb71348 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Thu, 12 Aug 2021 23:41:17 +0200 Subject: [PATCH 090/174] refactor: remove uploadKeySignatures (use uploadCrossSigningSignatures) --- lib/matrix_api_lite.dart | 1 - lib/src/matrix_api.dart | 32 ---------- .../model/upload_key_signatures_response.dart | 59 ------------------- test/matrix_api_test.dart | 47 --------------- 4 files changed, 139 deletions(-) delete mode 100644 lib/src/model/upload_key_signatures_response.dart diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 8cd63c62..096b476d 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -61,7 +61,6 @@ export 'src/model/room_creation_types.dart'; export 'src/model/room_summary.dart'; export 'src/model/stripped_state_event.dart'; export 'src/model/sync_update.dart'; -export 'src/model/upload_key_signatures_response.dart'; export 'src/utils/logs.dart'; export 'src/utils/map_copy_extension.dart'; export 'src/utils/try_get_map_extension.dart'; diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index f64b633c..903d2bee 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -32,7 +32,6 @@ import 'generated/api.dart'; import 'model/matrix_connection_exception.dart'; import 'model/matrix_exception.dart'; import 'model/matrix_keys.dart'; -import 'model/upload_key_signatures_response.dart'; enum RequestType { GET, POST, PUT, DELETE } @@ -171,37 +170,6 @@ class MatrixApi extends Api { return Map.from(response['one_time_key_counts']); } - /// Uploads new signatures of keys - /// https://github.com/matrix-org/matrix-doc/pull/2536 - Future uploadKeySignatures( - List keys) async { - final payload = {}; - for (final key in keys) { - if (key.identifier == null || - key.signatures == null || - key.signatures!.isEmpty) { - continue; - } - if (!payload.containsKey(key.userId)) { - payload[key.userId] = {}; - } - if (payload[key.userId].containsKey(key.identifier)) { - // we need to merge signature objects - payload[key.userId][key.identifier]['signatures'] - .addAll(key.signatures); - } else { - // we can just add signatures - payload[key.userId][key.identifier] = key.toJson(); - } - } - final response = await request( - RequestType.POST, - '/client/r0/keys/signatures/upload', - data: payload, - ); - return UploadKeySignaturesResponse.fromJson(response); - } - /// This endpoint allows the creation, modification and deletion of pushers /// for this user ID. The behaviour of this endpoint varies depending on the /// values in the JSON body. diff --git a/lib/src/model/upload_key_signatures_response.dart b/lib/src/model/upload_key_signatures_response.dart deleted file mode 100644 index 38bf3774..00000000 --- a/lib/src/model/upload_key_signatures_response.dart +++ /dev/null @@ -1,59 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'matrix_exception.dart'; - -class UploadKeySignaturesResponse { - Map>? failures; - - UploadKeySignaturesResponse.fromJson(Map json) - : failures = json['failures'] != null - ? (json['failures'] as Map).map( - (k, v) => MapEntry( - k, - (v as Map).map((k, v) => MapEntry( - k, - MatrixException.fromJson(v), - )), - ), - ) - : null; - - Map toJson() { - final data = {}; - if (failures != null) { - data['failures'] = failures!.map( - (k, v) => MapEntry( - k, - v.map( - (k, v) => MapEntry( - k, - v.raw, - ), - ), - ), - ); - } - return data; - } -} diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index d5fecb78..f615e5c5 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1187,53 +1187,6 @@ void main() { selfSigningKey: selfSigningKey, userSigningKey: userSigningKey); }); - test('uploadKeySignatures', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final key1 = MatrixDeviceKeys.fromJson({ - 'user_id': '@alice:example.com', - 'device_id': 'JLAFKJWSCS', - 'algorithms': [ - AlgorithmTypes.olmV1Curve25519AesSha2, - AlgorithmTypes.megolmV1AesSha2 - ], - 'keys': { - 'curve25519:JLAFKJWSCS': - '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI', - 'ed25519:JLAFKJWSCS': 'lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI' - }, - 'signatures': { - '@alice:example.com': { - 'ed25519:JLAFKJWSCS': - 'dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA' - } - }, - 'unsigned': {'device_display_name': 'Alices mobile phone'}, - }); - final key2 = MatrixDeviceKeys.fromJson({ - 'user_id': '@alice:example.com', - 'device_id': 'JLAFKJWSCS', - 'algorithms': [ - AlgorithmTypes.olmV1Curve25519AesSha2, - AlgorithmTypes.megolmV1AesSha2 - ], - 'keys': { - 'curve25519:JLAFKJWSCS': - '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI', - 'ed25519:JLAFKJWSCS': 'lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI' - }, - 'signatures': { - '@alice:example.com': {'ed25519:OTHERDEVICE': 'OTHERSIG'} - }, - 'unsigned': {'device_display_name': 'Alices mobile phone'}, - }); - final ret = await matrixApi.uploadKeySignatures([key1, key2]); - expect( - FakeMatrixApi.api['POST']!['/client/r0/keys/signatures/upload']({}), - ret.toJson(), - ); - }); test('requestPushers', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; From 5e06721639728d9e146c0058961b73e5edbb31b5 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Mon, 30 Aug 2021 07:55:21 +0000 Subject: [PATCH 091/174] fix: Make type in AuthenticationData nullable It seems that there is a problem in the matrix Spec according to this. the Spec says that the type is required and session is nullable. But for using this endpoint: https://spec.matrix.org/unstable/client-server-api/#client-behaviour-1-1 We need to send an auth object which only contains the session. We should file an issue at the spec and ask there for more information. Currently we should make type nullable as well because otherwise this would break uiaRequests in the app for SSO. --- lib/src/model/auth/authentication_data.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 3a561798..1f4cfc31 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -22,10 +22,10 @@ */ class AuthenticationData { - String type; + String? type; String? session; - AuthenticationData({required this.type, this.session}); + AuthenticationData({this.type, this.session}); AuthenticationData.fromJson(Map json) : type = json['type'], @@ -33,7 +33,7 @@ class AuthenticationData { Map toJson() { final data = {}; - data['type'] = type; + if (type != null) data['type'] = type; if (session != null) data['session'] = session; return data; } From dc0b3c715e613da8a50b66419863cf3a1537669a Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Mon, 30 Aug 2021 08:02:41 +0000 Subject: [PATCH 092/174] docs: Add comment with link to issue --- lib/src/model/auth/authentication_data.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 1f4cfc31..02633ca3 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -22,6 +22,8 @@ */ class AuthenticationData { + // Should be non-nullable according to the spec but this leads to this problem + // https://github.com/matrix-org/matrix-doc/issues/3370 String? type; String? session; From 2dffb824ce1484f97a73383c3fb4c02091dd097c Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 9 Sep 2021 10:01:12 +0200 Subject: [PATCH 093/174] chore: Bump version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db8ca4a7..bb2b1b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.3 +- fix: Make type in AuthenticationData nullable +- refactor: remove uploadKeySignatures (use uploadCrossSigningSignatures) + ## 0.4.2 - feat: Add more call event for improve voip. diff --git a/pubspec.yaml b/pubspec.yaml index bccc1c64..4f839429 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.4.2 +version: 0.4.3 homepage: https://famedly.com environment: From e92802e8787fc474d4609f63b8497cfcb81ccd88 Mon Sep 17 00:00:00 2001 From: Marcus Date: Thu, 9 Sep 2021 10:41:11 +0000 Subject: [PATCH 094/174] chore: add missing metadata to pubspec --- pubspec.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pubspec.yaml b/pubspec.yaml index 4f839429..884a6df6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,6 +2,8 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. version: 0.4.3 homepage: https://famedly.com +repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ +issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues environment: sdk: ">=2.12.0 <3.0.0" From 05400ec0ef82f4b071ba1f10b2f1c9cce91d0b90 Mon Sep 17 00:00:00 2001 From: Jindra Date: Wed, 1 Sep 2021 14:55:59 +0200 Subject: [PATCH 095/174] ci: Run pub publish from CI --- .gitlab-ci.yml | 51 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d5294662..e77bede1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,6 +2,7 @@ stages: - coverage - builddocs - deploy + - publish test: tags: @@ -48,4 +49,52 @@ pages: paths: - public only: - - main \ No newline at end of file + - main + +dry-run: + stage: publish + image: google/dart + script: + - dart pub get + - dart pub publish --dry-run + only: + - merge_requests + +pub-dev: + stage: publish + image: google/dart + script: + - | + if [ -z "${PUB_DEV_PUBLISH_ACCESS_TOKEN}" ]; then + echo "Missing PUB_DEV_PUBLISH_ACCESS_TOKEN environment variable" + exit 1 + fi + + if [ -z "${PUB_DEV_PUBLISH_REFRESH_TOKEN}" ]; then + echo "Missing PUB_DEV_PUBLISH_REFRESH_TOKEN environment variable" + exit 1 + fi + + if [ -z "${PUB_DEV_PUBLISH_TOKEN_ENDPOINT}" ]; then + echo "Missing PUB_DEV_PUBLISH_TOKEN_ENDPOINT environment variable" + exit 1 + fi + + if [ -z "${PUB_DEV_PUBLISH_EXPIRATION}" ]; then + echo "Missing PUB_DEV_PUBLISH_EXPIRATION environment variable" + exit 1 + fi + + cat < ~/.pub-cache/credentials.json + { + "accessToken":"$(echo "${PUB_DEV_PUBLISH_ACCESS_TOKEN}" | base64 -d)", + "refreshToken":"$(echo "${PUB_DEV_PUBLISH_REFRESH_TOKEN}" | base64 -d)", + "tokenEndpoint":"${PUB_DEV_PUBLISH_TOKEN_ENDPOINT}", + "scopes":["https://www.googleapis.com/auth/userinfo.email","openid"], + "expiration":${PUB_DEV_PUBLISH_EXPIRATION} + } + EOF + - dart pub get + - dart pub publish --dry-run + only: + - tags From 0f7ce914e7071750a2f939e504d2f0945f4cc0b2 Mon Sep 17 00:00:00 2001 From: Jindra Date: Wed, 1 Sep 2021 15:15:20 +0200 Subject: [PATCH 096/174] ci: change only tags to CI_COMMIT_TAG --- .gitlab-ci.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e77bede1..e8d9ec1f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -57,8 +57,6 @@ dry-run: script: - dart pub get - dart pub publish --dry-run - only: - - merge_requests pub-dev: stage: publish @@ -95,6 +93,6 @@ pub-dev: } EOF - dart pub get - - dart pub publish --dry-run - only: - - tags + - dart pub publish + rules: + - if: $CI_COMMIT_TAG From 57706bd02e44c2b0a1715c6839defa4a3662e078 Mon Sep 17 00:00:00 2001 From: Jindra Date: Tue, 14 Sep 2021 15:07:55 +0200 Subject: [PATCH 097/174] ci: add rm /docs and publish --force --- .gitlab-ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e8d9ec1f..e6636750 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,6 +55,7 @@ dry-run: stage: publish image: google/dart script: + - rm -rf ./docs - dart pub get - dart pub publish --dry-run @@ -62,6 +63,7 @@ pub-dev: stage: publish image: google/dart script: + - rm -rf ./docs - | if [ -z "${PUB_DEV_PUBLISH_ACCESS_TOKEN}" ]; then echo "Missing PUB_DEV_PUBLISH_ACCESS_TOKEN environment variable" @@ -93,6 +95,6 @@ pub-dev: } EOF - dart pub get - - dart pub publish + - dart pub publish --force rules: - if: $CI_COMMIT_TAG From 5c3db7a6029ef29f3fb7d5526caa135991727a79 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Mon, 27 Sep 2021 13:25:12 +0200 Subject: [PATCH 098/174] chore: workaround for invalid getTurnServer responses from synapse --- lib/src/matrix_api.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 903d2bee..9494289f 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -186,4 +186,17 @@ class MatrixApi extends Api { ); return; } + + /// This API provides credentials for the client to use when initiating + /// calls. + @override + Future getTurnServer() async { + final json = await request(RequestType.GET, '/client/r0/voip/turnServer'); + + // fix invalid responses from synapse + // https://github.com/matrix-org/synapse/pull/10922 + json['ttl'] = json['ttl'].toInt(); + + return TurnServerCredentials.fromJson(json); + } } From a9f1e0b3ee84858bdbea1be2919d5c6649a33ce5 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Mon, 27 Sep 2021 14:56:13 +0200 Subject: [PATCH 099/174] chore: Bump version --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb2b1b4a..9a39920a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.4.4 +- chore: workaround for invalid getTurnServer responses from synapse + ## 0.4.3 - fix: Make type in AuthenticationData nullable - refactor: remove uploadKeySignatures (use uploadCrossSigningSignatures) diff --git a/pubspec.yaml b/pubspec.yaml index 884a6df6..b947fe0e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.4.3 +version: 0.4.4 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 7a4bb507fe52eee244e2401fd27ead4e2dc893c5 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Mon, 11 Oct 2021 15:23:11 +0200 Subject: [PATCH 100/174] chore: codegen update (convert to json explicitly) --- lib/src/generated/api.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 5a28a352..7a898127 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -1436,7 +1436,8 @@ class Api { final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; - request.bodyBytes = utf8.encode(jsonEncode(signatures)); + request.bodyBytes = utf8.encode(jsonEncode(signatures + .map((k, v) => MapEntry(k, v.map((k, v) => MapEntry(k, v)))))); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); @@ -2500,7 +2501,7 @@ class Api { final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; - request.bodyBytes = utf8.encode(jsonEncode(backupData)); + request.bodyBytes = utf8.encode(jsonEncode(backupData.toJson())); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); @@ -2573,7 +2574,7 @@ class Api { final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; - request.bodyBytes = utf8.encode(jsonEncode(backupData)); + request.bodyBytes = utf8.encode(jsonEncode(backupData.toJson())); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); @@ -2652,7 +2653,7 @@ class Api { final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; - request.bodyBytes = utf8.encode(jsonEncode(data)); + request.bodyBytes = utf8.encode(jsonEncode(data.toJson())); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); @@ -3954,7 +3955,7 @@ class Api { final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; - request.bodyBytes = utf8.encode(jsonEncode(filter)); + request.bodyBytes = utf8.encode(jsonEncode(filter.toJson())); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); From 3e7a6df81b809b9f1de28af4fb3f83fe3639f065 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Thu, 4 Nov 2021 15:23:01 +0100 Subject: [PATCH 101/174] fix: threepidCreds should be threepid_creds and an object For context, see https://github.com/matrix-org/matrix-doc/pull/3471 Basically the spec was wrong and didn't match what clients and servers were doing. Might fix registration on matrix.org. BREAKING CHANGE: Any client that implements the email portion will fail to build now. --- .../auth/authentication_three_pid_creds.dart | 21 +++------- test/matrix_api_test.dart | 41 +++++++------------ 2 files changed, 20 insertions(+), 42 deletions(-) diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index 292646a4..b6278160 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -28,7 +28,7 @@ import 'authentication_data.dart'; /// Or phone number based identity: /// https://matrix.org/docs/spec/client_server/r0.6.1#phone-number-msisdn-based-identity-homeserver class AuthenticationThreePidCreds extends AuthenticationData { - late List threepidCreds; + late ThreepidCreds threepidCreds; AuthenticationThreePidCreds( {String? session, required String type, required this.threepidCreds}) @@ -39,27 +39,16 @@ class AuthenticationThreePidCreds extends AuthenticationData { AuthenticationThreePidCreds.fromJson(Map json) : super.fromJson(json) { - if (json['threepidCreds'] != null) { - threepidCreds = (json['threepidCreds'] as List) - .map((item) => ThreepidCreds.fromJson(item)) - .toList(); - } - - // This is so extremly stupid... kill it with fire! - if (json['threepid_creds'] != null) { - threepidCreds = (json['threepid_creds'] as List) - .map((item) => ThreepidCreds.fromJson(item)) - .toList(); + final creds = json['threepid_creds']; + if (creds is Map) { + threepidCreds = ThreepidCreds.fromJson(creds); } } @override Map toJson() { final data = super.toJson(); - data['threepidCreds'] = threepidCreds.map((t) => t.toJson()).toList(); - // Help me! I'm prisoned in a developer factory against my will, - // where we are forced to work with json like this!! - data['threepid_creds'] = threepidCreds.map((t) => t.toJson()).toList(); + data['threepid_creds'] = threepidCreds.toJson(); return data; } } diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index f615e5c5..af414dea 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1807,37 +1807,26 @@ void main() { test('AuthenticationThreePidCreds', () { final json = { 'type': 'm.login.email.identity', - 'threepidCreds': [ - { - 'sid': '1', - 'client_secret': 'a', - 'id_server': 'matrix.org', - 'id_access_token': 'a', - }, - ], - 'threepid_creds': [ - { - 'sid': '1', - 'client_secret': 'a', - 'id_server': 'matrix.org', - 'id_access_token': 'a', - }, - ], + 'threepid_creds': { + 'sid': '1', + 'client_secret': 'a', + 'id_server': 'matrix.org', + 'id_access_token': 'a', + }, 'session': '1', }; expect(AuthenticationThreePidCreds.fromJson(json).toJson(), json); expect( AuthenticationThreePidCreds( - session: '1', - type: AuthenticationTypes.emailIdentity, - threepidCreds: [ - ThreepidCreds( - sid: '1', - clientSecret: 'a', - idServer: 'matrix.org', - idAccessToken: 'a', - ), - ]).toJson(), + session: '1', + type: AuthenticationTypes.emailIdentity, + threepidCreds: ThreepidCreds( + sid: '1', + clientSecret: 'a', + idServer: 'matrix.org', + idAccessToken: 'a', + ), + ).toJson(), json); }); test('AuthenticationIdentifier', () { From a975c07ed4b0b3f40a1b69554055a25339f2f821 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Thu, 4 Nov 2021 15:57:54 +0100 Subject: [PATCH 102/174] chore: Bump version --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a39920a..5dc14f12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.5.0 +- fix: threepidCreds should be threepid_creds and an object + ## 0.4.4 - chore: workaround for invalid getTurnServer responses from synapse diff --git a/pubspec.yaml b/pubspec.yaml index b947fe0e..f026f99f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.4.4 +version: 0.5.0 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 238c5addb3d5db76699ff2a4d942c7f5f16dbd85 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Wed, 10 Nov 2021 09:31:02 +0100 Subject: [PATCH 103/174] feat: Add constructors to SyncUpdate classes In the SDK we have multiple points where we use fake syncs to update the data model. This constructors would make it much easier to work with them. --- lib/src/model/sync_update.dart | 46 ++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index 878b9343..09b015d9 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -39,7 +39,16 @@ class SyncUpdate { Map? deviceOneTimeKeysCount; List? deviceUnusedFallbackKeyTypes; - SyncUpdate({required this.nextBatch}); + SyncUpdate({ + required this.nextBatch, + this.rooms, + this.presence, + this.accountData, + this.toDevice, + this.deviceLists, + this.deviceOneTimeKeysCount, + this.deviceUnusedFallbackKeyTypes, + }); SyncUpdate.fromJson(Map json) : nextBatch = json['next_batch'], @@ -119,7 +128,7 @@ class RoomsUpdate { Map? invite; Map? leave; - RoomsUpdate(); + RoomsUpdate({this.join, this.invite, this.leave}); RoomsUpdate.fromJson(Map json) { join = json['join'] != null @@ -161,7 +170,14 @@ class JoinedRoomUpdate extends SyncRoomUpdate { List? accountData; UnreadNotificationCounts? unreadNotifications; - JoinedRoomUpdate(); + JoinedRoomUpdate({ + this.summary, + this.state, + this.timeline, + this.ephemeral, + this.accountData, + this.unreadNotifications, + }); JoinedRoomUpdate.fromJson(Map json) { summary = @@ -225,6 +241,8 @@ class JoinedRoomUpdate extends SyncRoomUpdate { class InvitedRoomUpdate extends SyncRoomUpdate { List? inviteState; + InvitedRoomUpdate({this.inviteState}); + InvitedRoomUpdate.fromJson(Map json) { inviteState = (json['invite_state'] != null && json['invite_state']['events'] != null) @@ -250,7 +268,11 @@ class LeftRoomUpdate extends SyncRoomUpdate { TimelineUpdate? timeline; List? accountData; - LeftRoomUpdate(); + LeftRoomUpdate({ + this.state, + this.timeline, + this.accountData, + }); LeftRoomUpdate.fromJson(Map json) { state = (json['state'] != null && json['state']['events'] != null) @@ -293,7 +315,11 @@ class TimelineUpdate { bool? limited; String? prevBatch; - TimelineUpdate(); + TimelineUpdate({ + this.events, + this.limited, + this.prevBatch, + }); TimelineUpdate.fromJson(Map json) { events = json['events'] != null @@ -322,6 +348,11 @@ class UnreadNotificationCounts { int? highlightCount; int? notificationCount; + UnreadNotificationCounts({ + this.notificationCount, + this.highlightCount, + }); + UnreadNotificationCounts.fromJson(Map json) { highlightCount = json['highlight_count']; notificationCount = json['notification_count']; @@ -343,6 +374,11 @@ class DeviceListsUpdate { List? changed; List? left; + DeviceListsUpdate({ + this.changed, + this.left, + }); + DeviceListsUpdate.fromJson(Map json) { changed = List.from(json['changed'] ?? []); left = List.from(json['left'] ?? []); From 6f4f69106ea5f0a9b1c603371045f2231662094e Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Wed, 10 Nov 2021 09:32:05 +0100 Subject: [PATCH 104/174] chore: Bump version --- CHANGELOG.md | 3 +++ lib/src/model/sync_update.dart | 6 +++++- pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dc14f12..e1ccc41d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.5.1 +- feat: Add constructors to SyncUpdate classes + ## 0.5.0 - fix: threepidCreds should be threepid_creds and an object diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index 09b015d9..95aaf3e5 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -128,7 +128,11 @@ class RoomsUpdate { Map? invite; Map? leave; - RoomsUpdate({this.join, this.invite, this.leave}); + RoomsUpdate({ + this.join, + this.invite, + this.leave, + }); RoomsUpdate.fromJson(Map json) { join = json['join'] != null diff --git a/pubspec.yaml b/pubspec.yaml index f026f99f..ef5aa3dd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.5.0 +version: 0.5.1 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 2383cef43837c3da4a038cd83125c78109b2c53c Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Tue, 23 Nov 2021 10:31:35 +0100 Subject: [PATCH 105/174] feat: Colored logs on native and web This uses the developer.logs method to print logs on native and console.logs on web. Therefore we have native colored logs everywhere without the use of a package. It highlights errors and warnings on web much better and supports collapsing stacktraces on web. --- lib/src/utils/logs.dart | 18 ++------------- lib/src/utils/print_logs_native.dart | 34 ++++++++++++++++++++++++++++ lib/src/utils/print_logs_web.dart | 34 ++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 lib/src/utils/print_logs_native.dart create mode 100644 lib/src/utils/print_logs_web.dart diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index 37852945..f9ae4394 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -21,6 +21,8 @@ * SOFTWARE. */ +import 'print_logs_native.dart' if (dart.library.html) 'print_logs_web.dart'; + enum Level { wtf, error, @@ -124,20 +126,4 @@ class LogEvent { this.stackTrace, this.level = Level.debug, }); - - void printOut() { - var logsStr = - '# [${level.toString().split('.').last.toUpperCase()}] $title'; - if (exception != null) { - logsStr += ' - ' + exception.toString(); - } - // ignore: avoid_print - print(logsStr); - if (stackTrace != null) { - // ignore: avoid_print - print('## Stacktrace:'); - // ignore: avoid_print - print(stackTrace.toString()); - } - } } diff --git a/lib/src/utils/print_logs_native.dart b/lib/src/utils/print_logs_native.dart new file mode 100644 index 00000000..b6790e4e --- /dev/null +++ b/lib/src/utils/print_logs_native.dart @@ -0,0 +1,34 @@ +import 'package:matrix_api_lite/matrix_api_lite.dart'; + +extension PrintLogs on LogEvent { + void printOut() { + var logsStr = title; + if (exception != null) { + logsStr += ' - ' + exception.toString(); + } + if (stackTrace != null) { + logsStr += '\n${stackTrace.toString()}'; + } + switch (level) { + case Level.wtf: + logsStr = '\x1B[31m!!!CRITICAL!!! $logsStr\x1B[0m'; + break; + case Level.error: + logsStr = '\x1B[31m$logsStr\x1B[0m'; + break; + case Level.warning: + logsStr = '\x1B[33m$logsStr\x1B[0m'; + break; + case Level.info: + logsStr = '\x1B[32m$logsStr\x1B[0m'; + break; + case Level.debug: + logsStr = '\x1B[34m$logsStr\x1B[0m'; + break; + case Level.verbose: + break; + } + // ignore: avoid_print + print('[Matrix] $logsStr'); + } +} diff --git a/lib/src/utils/print_logs_web.dart b/lib/src/utils/print_logs_web.dart new file mode 100644 index 00000000..ea67b71d --- /dev/null +++ b/lib/src/utils/print_logs_web.dart @@ -0,0 +1,34 @@ +import 'package:matrix_api_lite/matrix_api_lite.dart'; +import 'dart:html'; + +extension PrintLogs on LogEvent { + void printOut() { + var logsStr = '[Matrix] $title'; + if (exception != null) { + logsStr += ' - ' + exception.toString(); + } + if (stackTrace != null) { + logsStr += '\n${stackTrace.toString()}'; + } + switch (level) { + case Level.wtf: + window.console.error('!!!CRITICAL!!! $logsStr'); + break; + case Level.error: + window.console.error(logsStr); + break; + case Level.warning: + window.console.warn(logsStr); + break; + case Level.info: + window.console.info(logsStr); + break; + case Level.debug: + window.console.debug(logsStr); + break; + case Level.verbose: + window.console.log(logsStr); + break; + } + } +} From 6a3c25a8bd971b0e18d90e52944dea3836f94ccc Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Wed, 24 Nov 2021 07:56:42 +0100 Subject: [PATCH 106/174] chore: Make some tryGet errors verbose and display line tryGet messages can spam the logs and may be better if they are just verbose instead of warnings. Also now we display the line where this tryGet call was. --- lib/src/utils/try_get_map_extension.dart | 23 +++++++++++++++++------ test/try_get_map_extension_test.dart | 12 ++++++------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index 1cc026bc..fbaa7e11 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -39,7 +39,7 @@ class _RequiredLog implements TryGet { const _RequiredLog(); @override void call(String key, Type expected, Type actual) => Logs().w( - 'Expected "$expected" in event content for the Key "$key" but got "$actual".'); + 'Expected required "$expected" in event content for the Key "$key" but got "$actual" at ${StackTrace.current.firstLine}'); } class _OptionalLog implements TryGet { @@ -48,7 +48,7 @@ class _OptionalLog implements TryGet { void call(String key, Type expected, Type actual) { if (actual != Null) { Logs().w( - 'Expected "$expected" in event content for the Key "$key" but got "$actual".'); + 'Expected optional "$expected" in event content for the Key "$key" but got "$actual" at ${StackTrace.current.firstLine}'); } } } @@ -79,8 +79,8 @@ extension TryGetMapExtension on Map { // copy entries to ensure type check failures here and not an access return value.cast().toList(); } catch (_) { - Logs() - .w('Unable to create "List<$T>" in event content for the key "$key"'); + Logs().v( + 'Unable to create "List<$T>" in event content for the key "$key" at ${StackTrace.current.firstLine}'); return null; } } @@ -95,9 +95,20 @@ extension TryGetMapExtension on Map { // copy map to ensure type check failures here and not an access return Map.from(value.cast()); } catch (_) { - Logs().w( - 'Unable to create "Map<$A,$B>" in event content for the key "$key"'); + Logs().v( + 'Unable to create "Map<$A,$B>" in event content for the key "$key" at ${StackTrace.current.firstLine}'); return null; } } } + +extension on StackTrace { + String get firstLine { + final lines = toString().split('\n'); + return lines.length >= 3 + ? lines[2].replaceFirst('#2 ', '') + : lines.isNotEmpty + ? lines.first + : '(unknown position)'; + } +} diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index d38a1e68..7fe70c28 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -26,7 +26,7 @@ import 'package:test/test.dart'; void main() { group('Try-get-map-extension', () { - Logs().level = Level.error; + Logs().level = Level.verbose; test('it should work', () { final data = { 'str': 'foxies', @@ -40,12 +40,12 @@ void main() { expect(data.tryGet('str'), null); expect(data.tryGet('int'), 42); expect(data.tryGet('list'), [2, 3, 4]); - expect(data.tryGet>('map')?.tryGet('beep'), + expect(data.tryGetMap('map')?.tryGet('beep'), 'boop'); - expect(data.tryGet>('map')?.tryGet('meep'), - null); - expect(data.tryGet>('pam')?.tryGet('beep'), - null); + expect( + data.tryGetMap('map')?.tryGet('meep'), null); + expect( + data.tryGetMap('pam')?.tryGet('beep'), null); }); }); } From c7d182a0a7925b5ceb657d093ac2f33bd1390c3d Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Fri, 26 Nov 2021 07:23:02 +0000 Subject: [PATCH 107/174] chore: Bump version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1ccc41d..799b3f26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.2 +- feat: Colored logs on native and web +- chore: Make some tryGet errors verbose and display line + ## 0.5.1 - feat: Add constructors to SyncUpdate classes diff --git a/pubspec.yaml b/pubspec.yaml index ef5aa3dd..3e7d6b78 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.5.1 +version: 0.5.2 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 454e27239cdb5ec111b85ff200ec75ef6fdc70ab Mon Sep 17 00:00:00 2001 From: Sorunome Date: Tue, 7 Dec 2021 21:10:59 +0100 Subject: [PATCH 108/174] chore: Add missing matrix error types as per spec The full list of error codes is here: https://spec.matrix.org/v1.1/client-server-api/#standard-error-response --- lib/src/model/matrix_exception.dart | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 3e7ef751..822d9845 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -1,17 +1,17 @@ /* MIT License -* +* * Copyright (C) 2019, 2020, 2021 Famedly GmbH -* +* * 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 @@ -40,6 +40,23 @@ enum MatrixError { M_MISSING_PARAM, M_UNSUPPORTED_ROOM_VERSION, M_UNRECOGNIZED, + M_BAD_JSON, + M_NOT_JSON, + M_UNAUTHORIZED, + M_USER_DEACTIVATED, + M_INVALID_USERNAME, + M_ROOM_IN_USE, + M_INVALID_ROOM_STATE, + M_SERVER_NOT_TRUSTED, + M_INCOMPATIBLE_ROOM_VERSION, + M_BAD_STATE, + M_GUEST_ACCESS_FORBIDDEN, + M_CAPTCHA_NEEDED, + M_CAPTCHA_INVALID, + M_INVALID_PARAM, + M_EXCLUSIVE, + M_RESOURCE_LIMIT_EXCEEDED, + M_CANNOT_LEAVE_SERVER_NOTICE_ROOM, } /// Represents a special response from the Homeserver for errors. From 793ddddd3f7d66cfa62b96ae5b2cd24a22f54282 Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Tue, 7 Dec 2021 03:44:35 +0100 Subject: [PATCH 109/174] feat: add additionalProperties in PusherData --- lib/src/generated/model.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index f4f5f2e0..b4883db6 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -1281,15 +1281,20 @@ class PusherData { PusherData({ this.format, this.url, + this.additionalProperties = const {}, }); PusherData.fromJson(Map json) : format = ((v) => v != null ? v as String : null)(json['format']), - url = ((v) => v != null ? Uri.parse(v) : null)(json['url']); + url = ((v) => v != null ? Uri.parse(v) : null)(json['url']), + additionalProperties = Map.fromEntries(json.entries + .where((e) => !['format', 'url'].contains(e.key)) + .map((e) => MapEntry(e.key, e.value as dynamic))); Map toJson() { final format = this.format; final url = this.url; return { + ...additionalProperties, if (format != null) 'format': format, if (url != null) 'url': url.toString(), }; @@ -1302,6 +1307,8 @@ class PusherData { /// Required if `kind` is `http`. The URL to use to send /// notifications to. Uri? url; + + Map additionalProperties; } @_NameSource('spec') From 477780d7793b6f8e414dc46ab2c878bef6e6c93b Mon Sep 17 00:00:00 2001 From: Lukas Lihotzki Date: Thu, 25 Nov 2021 17:06:38 +0100 Subject: [PATCH 110/174] feat: deletePusher --- lib/src/generated/model.dart | 63 +++++++++++++++++++++++++----------- lib/src/matrix_api.dart | 17 ++++++++++ 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index b4883db6..edc8d356 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -1312,50 +1312,80 @@ class PusherData { } @_NameSource('spec') -class Pusher { - Pusher({ - required this.appDisplayName, +class PusherId { + PusherId({ required this.appId, + required this.pushkey, + }); + + PusherId.fromJson(Map json) + : appId = json['app_id'] as String, + pushkey = json['pushkey'] as String; + Map toJson() => { + 'app_id': appId, + 'pushkey': pushkey, + }; + + /// This is a reverse-DNS style identifier for the application. + /// Max length, 64 chars. + String appId; + + /// This is a unique identifier for this pusher. See `/set` for + /// more detail. + /// Max length, 512 bytes. + String pushkey; +} + +@_NameSource('spec') +class Pusher implements PusherId { + Pusher({ + required this.appId, + required this.pushkey, + required this.appDisplayName, required this.data, required this.deviceDisplayName, required this.kind, required this.lang, this.profileTag, - required this.pushkey, }); Pusher.fromJson(Map json) - : appDisplayName = json['app_display_name'] as String, - appId = json['app_id'] as String, + : appId = json['app_id'] as String, + pushkey = json['pushkey'] as String, + appDisplayName = json['app_display_name'] as String, data = PusherData.fromJson(json['data']), deviceDisplayName = json['device_display_name'] as String, kind = json['kind'] as String, lang = json['lang'] as String, profileTag = - ((v) => v != null ? v as String : null)(json['profile_tag']), - pushkey = json['pushkey'] as String; + ((v) => v != null ? v as String : null)(json['profile_tag']); Map toJson() { final profileTag = this.profileTag; return { - 'app_display_name': appDisplayName, 'app_id': appId, + 'pushkey': pushkey, + 'app_display_name': appDisplayName, 'data': data.toJson(), 'device_display_name': deviceDisplayName, 'kind': kind, 'lang': lang, if (profileTag != null) 'profile_tag': profileTag, - 'pushkey': pushkey, }; } - /// A string that will allow the user to identify what application - /// owns this pusher. - String appDisplayName; - /// This is a reverse-DNS style identifier for the application. /// Max length, 64 chars. String appId; + /// This is a unique identifier for this pusher. See `/set` for + /// more detail. + /// Max length, 512 bytes. + String pushkey; + + /// A string that will allow the user to identify what application + /// owns this pusher. + String appDisplayName; + /// A dictionary of information for the pusher implementation /// itself. PusherData data; @@ -1375,11 +1405,6 @@ class Pusher { /// This string determines which set of device specific rules this /// pusher executes. String? profileTag; - - /// This is a unique identifier for this pusher. See `/set` for - /// more detail. - /// Max length, 512 bytes. - String pushkey; } @_NameSource('spec') diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 9494289f..f0fd488f 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -173,6 +173,9 @@ class MatrixApi extends Api { /// This endpoint allows the creation, modification and deletion of pushers /// for this user ID. The behaviour of this endpoint varies depending on the /// values in the JSON body. + /// + /// See [deletePusher] to issue requests with `kind: null`. + /// /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-pushers-set Future postPusher(Pusher pusher, {bool? append}) async { final data = pusher.toJson(); @@ -187,6 +190,20 @@ class MatrixApi extends Api { return; } + /// Variant of postPusher operation that deletes pushers by setting `kind: null`. + /// + /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-pushers-set + Future deletePusher(PusherId pusher) async { + final data = PusherData.fromJson(pusher.toJson()).toJson(); + data['kind'] = null; + await request( + RequestType.POST, + '/client/r0/pushers/set', + data: data, + ); + return; + } + /// This API provides credentials for the client to use when initiating /// calls. @override From c25f893a4ac5d40504bd5e5978a5d8475d4fc1a9 Mon Sep 17 00:00:00 2001 From: Sorunome Date: Thu, 9 Dec 2021 12:50:27 +0100 Subject: [PATCH 111/174] chore: Bump version --- CHANGELOG.md | 5 +++++ pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 799b3f26..fbcde4db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.5.3 +- chore: Add missing matrix error types as per spec +- feat: add additionalProperties in PusherData +- feat: deletePusher + ## 0.5.2 - feat: Colored logs on native and web - chore: Make some tryGet errors verbose and display line diff --git a/pubspec.yaml b/pubspec.yaml index 3e7d6b78..58d86b0b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.5.2 +version: 0.5.3 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 2fa6561f362372fd0ff974751c90e45cf03c4049 Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Fri, 18 Mar 2022 23:04:01 +0800 Subject: [PATCH 112/174] chore: Add GroupCallPrefix/GroupCallMemberPrefix to EventTypes. chore: fix flutter analyze issue. --- lib/src/matrix_api.dart | 3 --- lib/src/model/event_types.dart | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index f0fd488f..6eccfbac 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -29,9 +29,6 @@ import 'package:http/http.dart' as http; import '../matrix_api_lite.dart'; import 'generated/api.dart'; -import 'model/matrix_connection_exception.dart'; -import 'model/matrix_exception.dart'; -import 'model/matrix_keys.dart'; enum RequestType { GET, POST, PUT, DELETE } diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index 58c80899..b948c8a2 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -57,6 +57,8 @@ abstract class EventTypes { static const String CallAssertedIdentity = 'm.call.asserted_identity'; static const String CallAssertedIdentityPrefix = 'org.matrix.call.asserted_identity'; + static const String GroupCallPrefix = 'org.matrix.msc3401.call'; + static const String GroupCallMemberPrefix = 'org.matrix.msc3401.call.member'; static const String Unknown = 'm.unknown'; // To device event types From d6bb91f7e1e2473099608490ba1d9aade90356af Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 16 Mar 2022 16:31:02 +0100 Subject: [PATCH 113/174] chore: Update to matrix v1.2 --- .gitignore | 4 + lib/fake_matrix_api.dart | 350 +++++++------- lib/src/generated/api.dart | 619 +++++++++++++------------ lib/src/generated/model.dart | 680 +++++++++++++++++++--------- lib/src/generated/model.g.dart | 802 +++++++++++++++++++++++++++++++++ lib/src/matrix_api.dart | 28 +- pubspec.yaml | 3 + test/matrix_api_test.dart | 110 +++-- 8 files changed, 1829 insertions(+), 767 deletions(-) create mode 100644 lib/src/generated/model.g.dart diff --git a/.gitignore b/.gitignore index 0ab205ed..4d9b87d1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,10 @@ test/.test_coverage.dart coverage/ coverage_badge.svg +# codegen related +*.bak +*.bakmacoscompat + # IntelliJ related *.iml *.ipr diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index d626dccd..37e02927 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -89,17 +89,17 @@ class FakeMatrixApi extends MockClient { statusCode = 405; } } else if (method == 'PUT' && - action.contains('/client/r0/sendToDevice/')) { + action.contains('/client/v3/sendToDevice/')) { res = {}; } else if (method == 'GET' && - action.contains('/client/r0/rooms/') && + action.contains('/client/v3/rooms/') && action.contains('/state/m.room.member/')) { res = {'displayname': ''}; } else if (method == 'PUT' && action.contains( - '/client/r0/rooms/!1234%3AfakeServer.notExisting/send/')) { + '/client/v3/rooms/!1234%3AfakeServer.notExisting/send/')) { res = {'event_id': '\$event${FakeMatrixApi.eventCounter++}'}; - } else if (action.contains('/client/r0/sync')) { + } else if (action.contains('/client/v3/sync')) { res = { 'next_batch': DateTime.now().millisecondsSinceEpoch.toString }; @@ -752,11 +752,11 @@ class FakeMatrixApi extends MockClient { 'errcode': 'M_FORBIDDEN', 'error': 'Blabla', }, - '/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10': (var req) => { + '/media/v3/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10': (var req) => { 'og:image': 'mxc://example.com/ascERGshawAWawugaAcauga', 'matrix:image:size': 102400 }, - '/media/r0/config': (var req) => {'m.upload.size': 50000000}, + '/media/v3/config': (var req) => {'m.upload.size': 50000000}, '/.well-known/matrix/client': (var req) => { 'm.homeserver': { 'base_url': 'https://fakeserver.notexisting', @@ -768,7 +768,7 @@ class FakeMatrixApi extends MockClient { 'app_url': 'https://custom.app.fakeserver.notexisting' } }, - '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags': + '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags': (var req) => { 'tags': { 'm.favourite': {'order': 0.1}, @@ -776,7 +776,7 @@ class FakeMatrixApi extends MockClient { 'u.Customers': {} } }, - '/client/r0/events?from=1234&timeout=10&room_id=%211234': (var req) => { + '/client/v3/events?from=1234&timeout=10&room_id=%211234': (var req) => { 'start': 's3456_9_0', 'end': 's3457_9_0', 'chunk': [ @@ -796,35 +796,35 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/thirdparty/location?alias=1234': (var req) => [ + '/client/v3/thirdparty/location?alias=1234': (var req) => [ { 'alias': '#freenode_#matrix:matrix.org', 'protocol': 'irc', 'fields': {'network': 'freenode', 'channel': '#matrix'} } ], - '/client/r0/thirdparty/location/irc': (var req) => [ + '/client/v3/thirdparty/location/irc': (var req) => [ { 'alias': '#freenode_#matrix:matrix.org', 'protocol': 'irc', 'fields': {'network': 'freenode', 'channel': '#matrix'} } ], - '/client/r0/thirdparty/user/irc': (var req) => [ + '/client/v3/thirdparty/user/irc': (var req) => [ { 'userid': '@_gitter_jim:matrix.org', 'protocol': 'gitter', 'fields': {'user': 'jim'} } ], - '/client/r0/thirdparty/user?userid=1234': (var req) => [ + '/client/v3/thirdparty/user?userid=1234': (var req) => [ { 'userid': '@_gitter_jim:matrix.org', 'protocol': 'gitter', 'fields': {'user': 'jim'} } ], - '/client/r0/thirdparty/protocol/irc': (var req) => { + '/client/v3/thirdparty/protocol/irc': (var req) => { 'user_fields': ['network', 'nickname'], 'location_fields': ['network', 'channel'], 'icon': 'mxc://example.org/aBcDeFgH', @@ -845,7 +845,7 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/thirdparty/protocols': (var req) => { + '/client/v3/thirdparty/protocols': (var req) => { 'irc': { 'user_fields': ['network', 'nickname'], 'location_fields': ['network', 'channel'], @@ -888,9 +888,9 @@ class FakeMatrixApi extends MockClient { ] } }, - '/client/r0/account/whoami': (var req) => + '/client/v3/account/whoami': (var req) => {'user_id': 'alice@example.com'}, - '/client/r0/capabilities': (var req) => { + '/client/v3/capabilities': (var req) => { 'capabilities': { 'm.change_password': {'enabled': false}, 'm.room_versions': { @@ -905,7 +905,7 @@ class FakeMatrixApi extends MockClient { 'com.example.custom.ratelimit': {'max_requests_per_hour': 600} } }, - '/client/r0/rooms/1234/context/1234?limit=10&filter=%7B%7D': (var req) => + '/client/v3/rooms/1234/context/1234?limit=10&filter=%7B%7D': (var req) => { 'end': 't29-57_2_0_2', 'events_after': [ @@ -996,7 +996,7 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/admin/whois/%40alice%3Aexample.com': (var req) => { + '/client/v3/admin/whois/%40alice%3Aexample.com': (var req) => { 'user_id': '@peter:rabbit.rocks', 'devices': { 'teapot': { @@ -1020,15 +1020,15 @@ class FakeMatrixApi extends MockClient { } } }, - '/client/r0/user/%40alice%3Aexample.com/account_data/test.account.data': + '/client/v3/user/%40alice%3Aexample.com/account_data/test.account.data': (var req) => {'foo': 'bar'}, - '/client/r0/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data': + '/client/v3/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data': (var req) => {'foo': 'bar'}, - '/client/r0/directory/room/%23testalias%3Aexample.com': (var reqI) => { + '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => { 'room_id': '!abnjk1jdasj98:capuchins.com', 'servers': ['capuchins.com', 'matrix.org', 'another.com'] }, - '/client/r0/account/3pid': (var req) => { + '/client/v3/account/3pid': (var req) => { 'threepids': [ { 'medium': 'email', @@ -1038,7 +1038,7 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/devices': (var req) => { + '/client/v3/devices': (var req) => { 'devices': [ { 'device_id': 'QBUAZIFURK', @@ -1048,7 +1048,7 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/notifications?from=1234&limit=10&only=1234': (var req) => { + '/client/v3/notifications?from=1234&limit=10&only=1234': (var req) => { 'next_token': 'abcdef', 'notifications': [ { @@ -1074,21 +1074,21 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/devices/QBUAZIFURK': (var req) => { + '/client/v3/devices/QBUAZIFURK': (var req) => { 'device_id': 'QBUAZIFURK', 'display_name': 'android', 'last_seen_ip': '1.2.3.4', 'last_seen_ts': 1474491775024 }, - '/client/r0/profile/%40alice%3Aexample.com/displayname': (var reqI) => + '/client/v3/profile/%40alice%3Aexample.com/displayname': (var reqI) => {'displayname': 'Alice M'}, - '/client/r0/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => + '/client/v3/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => {'avatar_url': 'mxc://test'}, - '/client/r0/profile/%40alice%3Aexample.com': (var reqI) => { + '/client/v3/profile/%40alice%3Aexample.com': (var reqI) => { 'avatar_url': 'mxc://test', 'displayname': 'Alice M', }, - '/client/r0/voip/turnServer': (var req) => { + '/client/v3/voip/turnServer': (var req) => { 'username': '1443779631:@user:example.com', 'password': 'JlKfBy1QwLrO20385QyAtEyIv0=', 'uris': [ @@ -1098,18 +1098,18 @@ class FakeMatrixApi extends MockClient { ], 'ttl': 86400 }, - '/client/r0/presence/${Uri.encodeComponent('@alice:example.com')}/status': + '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status': (var req) => { 'presence': 'unavailable', 'last_active_ago': 420845, 'status_msg': 'test', 'currently_active': false }, - '/client/r0/keys/changes?from=1234&to=1234': (var req) => { + '/client/v3/keys/changes?from=1234&to=1234': (var req) => { 'changed': ['@alice:example.com', '@bob:example.org'], 'left': ['@clara:example.com', '@doug:example.org'] }, - '/client/r0/pushers': (var req) => { + '/client/v3/pushers': (var req) => { 'pushers': [ { 'pushkey': 'Xp/MzCt8/9DcSNE9cuiaoT5Ac55job3TdLSSmtmYl4A=', @@ -1126,11 +1126,10 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/publicRooms?limit=10&since=1234&server=example.com': + '/client/v3/publicRooms?limit=10&since=1234&server=example.com': (var req) => { 'chunk': [ { - 'aliases': ['#murrays:cheese.bar'], 'canonical_alias': '#murrays:cheese.bar', 'avatar_url': 'mxc://bleeker.street/CHEDDARandBRIE', 'guest_can_join': false, @@ -1145,30 +1144,30 @@ class FakeMatrixApi extends MockClient { 'prev_batch': 'p1902', 'total_room_count_estimate': 115 }, - '/client/r0/rooms/!localpart%3Aexample.com/aliases': (var req) => { + '/client/v3/rooms/!localpart%3Aexample.com/aliases': (var req) => { 'aliases': [ '#somewhere:example.com', '#another:example.com', '#hat_trick:example.com' ] }, - '/client/r0/joined_rooms': (var req) => { + '/client/v3/joined_rooms': (var req) => { 'joined_rooms': ['!foo:example.com'] }, - '/client/r0/directory/list/room/!localpart%3Aexample.com': (var req) => + '/client/v3/directory/list/room/!localpart%3Aexample.com': (var req) => {'visibility': 'public'}, - '/client/r0/rooms/1/state/m.room.member/@alice:example.com': (var req) => + '/client/v3/rooms/1/state/m.room.member/@alice:example.com': (var req) => {'displayname': 'Alice'}, - '/client/r0/profile/%40getme%3Aexample.com': (var req) => { + '/client/v3/profile/%40getme%3Aexample.com': (var req) => { 'avatar_url': 'mxc://test', 'displayname': 'You got me', }, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.member/@getme%3Aexample.com': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.member/@getme%3Aexample.com': (var req) => { 'avatar_url': 'mxc://test', 'displayname': 'You got me', }, - '/client/r0/rooms/!localpart%3Aserver.abc/state': (var req) => [ + '/client/v3/rooms/!localpart%3Aserver.abc/state': (var req) => [ { 'content': {'join_rule': 'public'}, 'type': 'm.room.join_rules', @@ -1233,12 +1232,12 @@ class FakeMatrixApi extends MockClient { 'state_key': '' } ], - '/client/r0/rooms/!localpart:server.abc/state/m.room.member/@getme:example.com': + '/client/v3/rooms/!localpart:server.abc/state/m.room.member/@getme:example.com': (var req) => { 'avatar_url': 'mxc://test', 'displayname': 'You got me', }, - '/client/r0/rooms/!localpart:server.abc/event/1234': (var req) => { + '/client/v3/rooms/!localpart:server.abc/event/1234': (var req) => { 'content': { 'body': 'This is an example text message', 'msgtype': 'm.text', @@ -1252,7 +1251,7 @@ class FakeMatrixApi extends MockClient { 'origin_server_ts': 1432735824653, 'unsigned': {'age': 1234} }, - '/client/r0/rooms/!localpart%3Aserver.abc/event/1234': (var req) => { + '/client/v3/rooms/!localpart%3Aserver.abc/event/1234': (var req) => { 'content': { 'body': 'This is an example text message', 'msgtype': 'm.text', @@ -1266,11 +1265,11 @@ class FakeMatrixApi extends MockClient { 'origin_server_ts': 1432735824653, 'unsigned': {'age': 1234} }, - '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': + '/client/v3/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': (var req) => messagesResponse, - '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': + '/client/v3/rooms/!localpart%3Aserver.abc/messages?from=&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': (var req) => messagesResponse, - '/client/r0/rooms/!1234%3Aexample.com/messages?from=1234&dir=b&limit=100&filter=%7B%22lazy_load_members%22%3Atrue%7D': + '/client/v3/rooms/!1234%3Aexample.com/messages?from=1234&dir=b&limit=100&filter=%7B%22lazy_load_members%22%3Atrue%7D': (var req) => messagesResponse, '/client/versions': (var req) => { 'versions': [ @@ -1283,12 +1282,12 @@ class FakeMatrixApi extends MockClient { ], 'unstable_features': {'m.lazy_load_members': true}, }, - '/client/r0/login': (var req) => { + '/client/v3/login': (var req) => { 'flows': [ {'type': 'm.login.password'} ] }, - '/client/r0/rooms/!localpart%3Aserver.abc/joined_members': (var req) => { + '/client/v3/rooms/!localpart%3Aserver.abc/joined_members': (var req) => { 'joined': { '@bar:example.com': { 'display_name': 'Bar', @@ -1296,7 +1295,7 @@ class FakeMatrixApi extends MockClient { } } }, - '/client/r0/rooms/!localpart%3Aserver.abc/members?at=1234&membership=join¬_membership=leave': + '/client/v3/rooms/!localpart%3Aserver.abc/members?at=1234&membership=join¬_membership=leave': (var req) => { 'chunk': [ { @@ -1315,7 +1314,7 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/rooms/!696r7674:example.com/members': (var req) => { + '/client/v3/rooms/!696r7674:example.com/members': (var req) => { 'chunk': [ { 'content': { @@ -1333,7 +1332,7 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/rooms/!726s6s6q:example.com/members': (var req) => { + '/client/v3/rooms/!726s6s6q:example.com/members': (var req) => { 'chunk': [ { 'content': { @@ -1351,7 +1350,7 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/rooms/!localpart%3Aserver.abc/members': (var req) => { + '/client/v3/rooms/!localpart%3Aserver.abc/members': (var req) => { 'chunk': [ { 'content': { @@ -1369,20 +1368,20 @@ class FakeMatrixApi extends MockClient { } ] }, - '/client/r0/pushrules/global/content/nocake': (var req) => { + '/client/v3/pushrules/global/content/nocake': (var req) => { 'actions': ['dont_notify'], 'pattern': 'cake*lie', 'rule_id': 'nocake', 'enabled': true, 'default': false }, - '/client/r0/pushrules/global/content/nocake/enabled': (var req) => { + '/client/v3/pushrules/global/content/nocake/enabled': (var req) => { 'enabled': true, }, - '/client/r0/pushrules/global/content/nocake/actions': (var req) => { + '/client/v3/pushrules/global/content/nocake/actions': (var req) => { 'actions': ['notify'] }, - '/client/r0/pushrules': (var req) => { + '/client/v3/pushrules': (var req) => { 'global': { 'content': [ { @@ -1527,15 +1526,15 @@ class FakeMatrixApi extends MockClient { ] } }, - '/client/r0/sync?filter=%7B%22room%22%3A%7B%22include_leave%22%3Atrue%2C%22timeline%22%3A%7B%22limit%22%3A10%7D%7D%7D&timeout=0': + '/client/v3/sync?filter=%7B%22room%22%3A%7B%22include_leave%22%3Atrue%2C%22timeline%22%3A%7B%22limit%22%3A10%7D%7D%7D&timeout=0': (var req) => archiveSyncResponse, - '/client/r0/sync?filter=%7B%22room%22%3A%7B%22state%22%3A%7B%22lazy_load_members%22%3Atrue%7D%7D%7D': + '/client/v3/sync?filter=%7B%22room%22%3A%7B%22state%22%3A%7B%22lazy_load_members%22%3Atrue%7D%7D%7D': (var req) => syncResponse, - '/client/r0/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15': + '/client/v3/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15': (var req) => syncResponse, - '/client/r0/register/available?username=testuser': (var req) => + '/client/v3/register/available?username=testuser': (var req) => {'available': true}, - '/client/r0/user/${Uri.encodeComponent('alice@example.com')}/filter/1234': + '/client/v3/user/${Uri.encodeComponent('alice@example.com')}/filter/1234': (var req) => { 'room': { 'state': { @@ -1566,7 +1565,7 @@ class FakeMatrixApi extends MockClient { 'event_format': 'client', 'event_fields': ['type', 'content', 'sender'] }, - '/client/unstable/room_keys/version': (var req) => { + '/client/v3/room_keys/version': (var req) => { 'algorithm': AlgorithmTypes.megolmBackupV1Curve25519AesSha2, 'auth_data': { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', @@ -1576,7 +1575,7 @@ class FakeMatrixApi extends MockClient { 'etag': '0', 'version': '5', }, - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': (var req) => { 'first_message_index': 0, 'forwarded_count': 0, @@ -1588,7 +1587,7 @@ class FakeMatrixApi extends MockClient { 'mac': 'QzKV/fgAs4U', }, }, - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': (var req) => { 'sessions': { 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU': { @@ -1605,7 +1604,7 @@ class FakeMatrixApi extends MockClient { }, }, }, - '/client/unstable/room_keys/keys?version=5': (var req) => { + '/client/v3/room_keys/keys?version=5': (var req) => { 'rooms': { '!726s6s6q:example.com': { 'sessions': { @@ -1627,16 +1626,16 @@ class FakeMatrixApi extends MockClient { }, }, 'POST': { - '/client/r0/delete_devices': (var req) => {}, - '/client/r0/account/3pid/add': (var req) => {}, - '/client/r0/account/3pid/bind': (var req) => {}, - '/client/r0/account/3pid/delete': (var req) => + '/client/v3/delete_devices': (var req) => {}, + '/client/v3/account/3pid/add': (var req) => {}, + '/client/v3/account/3pid/bind': (var req) => {}, + '/client/v3/account/3pid/delete': (var req) => {'id_server_unbind_result': 'success'}, - '/client/r0/account/3pid/unbind': (var req) => + '/client/v3/account/3pid/unbind': (var req) => {'id_server_unbind_result': 'success'}, - '/client/r0/account/password': (var req) => {}, - '/client/r0/rooms/1234/report/1234': (var req) => {}, - '/client/r0/search': (var req) => { + '/client/v3/account/password': (var req) => {}, + '/client/v3/rooms/1234/report/1234': (var req) => {}, + '/client/v3/search': (var req) => { 'search_categories': { 'room_events': { 'groups': { @@ -1674,9 +1673,9 @@ class FakeMatrixApi extends MockClient { } } }, - '/client/r0/account/deactivate': (var req) => + '/client/v3/account/deactivate': (var req) => {'id_server_unbind_result': 'success'}, - '/client/r0/user_directory/search': (var req) => { + '/client/v3/user_directory/search': (var req) => { 'results': [ { 'user_id': '@foo:bar.com', @@ -1686,39 +1685,38 @@ class FakeMatrixApi extends MockClient { ], 'limited': false }, - '/client/r0/register/email/requestToken': (var req) => { + '/client/v3/register/email/requestToken': (var req) => { 'sid': '123abc', 'submit_url': 'https://example.org/path/to/submitToken' }, - '/client/r0/register/msisdn/requestToken': (var req) => { + '/client/v3/register/msisdn/requestToken': (var req) => { 'sid': '123abc', 'submit_url': 'https://example.org/path/to/submitToken' }, - '/client/r0/account/password/email/requestToken': (var req) => { + '/client/v3/account/password/email/requestToken': (var req) => { 'sid': '123abc', 'submit_url': 'https://example.org/path/to/submitToken' }, - '/client/r0/account/password/msisdn/requestToken': (var req) => { + '/client/v3/account/password/msisdn/requestToken': (var req) => { 'sid': '123abc', 'submit_url': 'https://example.org/path/to/submitToken' }, - '/client/r0/account/3pid/email/requestToken': (var req) => { + '/client/v3/account/3pid/email/requestToken': (var req) => { 'sid': '123abc', 'submit_url': 'https://example.org/path/to/submitToken' }, - '/client/r0/account/3pid/msisdn/requestToken': (var req) => { + '/client/v3/account/3pid/msisdn/requestToken': (var req) => { 'sid': '123abc', 'submit_url': 'https://example.org/path/to/submitToken' }, - '/client/r0/rooms/!localpart%3Aexample.com/receipt/m.read/%241234%3Aexample.com': + '/client/v3/rooms/!localpart%3Aexample.com/receipt/m.read/%241234%3Aexample.com': (var req) => {}, - '/client/r0/rooms/!localpart%3Aexample.com/read_markers': (var req) => {}, - '/client/r0/user/${Uri.encodeComponent('alice@example.com')}/filter': + '/client/v3/rooms/!localpart%3Aexample.com/read_markers': (var req) => {}, + '/client/v3/user/${Uri.encodeComponent('alice@example.com')}/filter': (var req) => {'filter_id': '1234'}, - '/client/r0/publicRooms?server=example.com': (var req) => { + '/client/v3/publicRooms?server=example.com': (var req) => { 'chunk': [ { - 'aliases': ['#murrays:cheese.bar'], 'canonical_alias': '#murrays:cheese.bar', 'avatar_url': 'mxc://bleeker.street/CHEDDARandBRIE', 'guest_can_join': false, @@ -1733,7 +1731,7 @@ class FakeMatrixApi extends MockClient { 'prev_batch': 'p1902', 'total_room_count_estimate': 115 }, - '/client/r0/keys/claim': (var req) => { + '/client/v3/keys/claim': (var req) => { 'failures': {}, 'one_time_keys': { if (decodeJson(req)['one_time_keys']['@alice:example.com'] != @@ -1769,25 +1767,25 @@ class FakeMatrixApi extends MockClient { }, } }, - '/client/r0/rooms/!localpart%3Aexample.com/invite': (var req) => {}, - '/client/r0/rooms/!localpart%3Aexample.com/leave': (var req) => {}, - '/client/r0/rooms/!localpart%3Aexample.com/forget': (var req) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/kick': (var req) => {}, - '/client/r0/rooms/!localpart%3Aexample.com/kick': (var req) => {}, - '/client/r0/rooms/!localpart%3Aexample.com/ban': (var req) => {}, - '/client/r0/rooms/!localpart%3Aexample.com/unban': (var req) => {}, - '/client/r0/rooms/!localpart%3Aexample.com/join': (var req) => + '/client/v3/rooms/!localpart%3Aexample.com/invite': (var req) => {}, + '/client/v3/rooms/!localpart%3Aexample.com/leave': (var req) => {}, + '/client/v3/rooms/!localpart%3Aexample.com/forget': (var req) => {}, + '/client/v3/rooms/!localpart%3Aserver.abc/kick': (var req) => {}, + '/client/v3/rooms/!localpart%3Aexample.com/kick': (var req) => {}, + '/client/v3/rooms/!localpart%3Aexample.com/ban': (var req) => {}, + '/client/v3/rooms/!localpart%3Aexample.com/unban': (var req) => {}, + '/client/v3/rooms/!localpart%3Aexample.com/join': (var req) => {'room_id': '!localpart:example.com'}, - '/client/r0/join/!localpart%3Aexample.com?server_name=example.com&server_name=example.abc': + '/client/v3/join/!localpart%3Aexample.com?server_name=example.com&server_name=example.abc': (var req) => {'room_id': '!localpart:example.com'}, - '/client/r0/keys/upload': (var req) => { + '/client/v3/keys/upload': (var req) => { 'one_time_key_counts': { 'curve25519': 10, 'signed_curve25519': decodeJson(req)['one_time_keys']?.keys?.length ?? 0, } }, - '/client/r0/keys/query': (var req) => { + '/client/v3/keys/query': (var req) => { 'failures': {}, 'device_keys': { '@alice:example.com': { @@ -1970,32 +1968,32 @@ class FakeMatrixApi extends MockClient { }, }, }, - '/client/r0/register': (var req) => { + '/client/v3/register': (var req) => { 'user_id': '@testuser:example.com', 'access_token': '1234', 'device_id': 'ABCD', }, - '/client/r0/register?kind=user': (var req) => + '/client/v3/register?kind=user': (var req) => {'user_id': '@testuser:example.com'}, - '/client/r0/register?kind=guest': (var req) => + '/client/v3/register?kind=guest': (var req) => {'user_id': '@testuser:example.com'}, - '/client/r0/rooms/1234/upgrade': (var req) => { + '/client/v3/rooms/1234/upgrade': (var req) => { 'replacement_room': '!1234:fakeServer.notExisting', }, - '/client/r0/user/1234/openid/request_token': (var req) => { + '/client/v3/user/1234/openid/request_token': (var req) => { 'access_token': 'SomeT0kenHere', 'token_type': 'Bearer', 'matrix_server_name': 'example.com', 'expires_in': 3600 }, - '/client/r0/user/@test:fakeServer.notExisting/openid/request_token': + '/client/v3/user/@test:fakeServer.notExisting/openid/request_token': (var req) => { 'access_token': 'SomeT0kenHere', 'token_type': 'Bearer', 'matrix_server_name': 'example.com', 'expires_in': 3600 }, - '/client/r0/login': (var req) => { + '/client/v3/login': (var req) => { 'user_id': '@test:fakeServer.notExisting', 'access_token': 'abc123', 'device_id': 'GHTYAJCE', @@ -2004,160 +2002,160 @@ class FakeMatrixApi extends MockClient { 'm.identity_server': {'base_url': 'https://id.example.org'} } }, - '/media/r0/upload?filename=file.jpeg': (var req) => + '/media/v3/upload?filename=file.jpeg': (var req) => {'content_uri': 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'}, - '/client/r0/logout': (var reqI) => {}, - '/client/r0/pushers/set': (var reqI) => {}, - '/client/r0/join/1234': (var reqI) => {'room_id': '1234'}, - '/client/r0/logout/all': (var reqI) => {}, - '/client/r0/createRoom': (var reqI) => { + '/client/v3/logout': (var reqI) => {}, + '/client/v3/pushers/set': (var reqI) => {}, + '/client/v3/join/1234': (var reqI) => {'room_id': '1234'}, + '/client/v3/logout/all': (var reqI) => {}, + '/client/v3/createRoom': (var reqI) => { 'room_id': '!1234:fakeServer.notExisting', }, - '/client/r0/rooms/!localpart%3Aserver.abc/read_markers': (var reqI) => {}, - '/client/r0/rooms/!localpart:server.abc/kick': (var reqI) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/ban': (var reqI) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/unban': (var reqI) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/invite': (var reqI) => {}, - '/client/unstable/keys/device_signing/upload': (var reqI) { + '/client/v3/rooms/!localpart%3Aserver.abc/read_markers': (var reqI) => {}, + '/client/v3/rooms/!localpart:server.abc/kick': (var reqI) => {}, + '/client/v3/rooms/!localpart%3Aserver.abc/ban': (var reqI) => {}, + '/client/v3/rooms/!localpart%3Aserver.abc/unban': (var reqI) => {}, + '/client/v3/rooms/!localpart%3Aserver.abc/invite': (var reqI) => {}, + '/client/v3/keys/device_signing/upload': (var reqI) { return {}; }, - '/client/r0/keys/signatures/upload': (var reqI) => {'failures': {}}, - '/client/unstable/room_keys/version': (var reqI) => {'version': '5'}, + '/client/v3/keys/signatures/upload': (var reqI) => {'failures': {}}, + '/client/v3/room_keys/version': (var reqI) => {'version': '5'}, }, 'PUT': { - '/client/r0/user/%40test%3AfakeServer.notExisting/account_data/m.ignored_user_list': + '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/m.ignored_user_list': (var req) => {}, - '/client/r0/presence/${Uri.encodeComponent('@alice:example.com')}/status': + '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status': (var req) => {}, - '/client/r0/pushrules/global/content/nocake/enabled': (var req) => {}, - '/client/r0/pushrules/global/content/nocake/actions': (var req) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.history_visibility': + '/client/v3/pushrules/global/content/nocake/enabled': (var req) => {}, + '/client/v3/pushrules/global/content/nocake/actions': (var req) => {}, + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.history_visibility': (var req) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.join_rules': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.join_rules': (var req) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.guest_access': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.guest_access': (var req) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/send/m.call.invite/1234': + '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.invite/1234': (var req) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/send/m.call.answer/1234': + '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.answer/1234': (var req) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/send/m.call.candidates/1234': + '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.candidates/1234': (var req) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/send/m.call.hangup/1234': + '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.hangup/1234': (var req) => {}, - '/client/r0/rooms/!1234%3Aexample.com/redact/1143273582443PhrSn%3Aexample.org/1234': + '/client/v3/rooms/!1234%3Aexample.com/redact/1143273582443PhrSn%3Aexample.org/1234': (var req) => {'event_id': '1234'}, - '/client/r0/pushrules/global/room/!localpart%3Aserver.abc': (var req) => + '/client/v3/pushrules/global/room/!localpart%3Aserver.abc': (var req) => {}, - '/client/r0/pushrules/global/override/.m.rule.master/enabled': + '/client/v3/pushrules/global/override/.m.rule.master/enabled': (var req) => {}, - '/client/r0/pushrules/global/content/nocake?before=1&after=2': + '/client/v3/pushrules/global/content/nocake?before=1&after=2': (var req) => {}, - '/client/r0/devices/QBUAZIFURK': (var req) => {}, - '/client/r0/directory/room/%23testalias%3Aexample.com': (var reqI) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/send/m.room.message/testtxid': + '/client/v3/devices/QBUAZIFURK': (var req) => {}, + '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => {}, + '/client/v3/rooms/!localpart%3Aserver.abc/send/m.room.message/testtxid': (var reqI) => { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', }, - '/client/r0/rooms/!localpart%3Aserver.abc/send/m.reaction/testtxid': + '/client/v3/rooms/!localpart%3Aserver.abc/send/m.reaction/testtxid': (var reqI) => { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', }, - '/client/r0/rooms/!localpart%3Aexample.com/typing/%40alice%3Aexample.com': + '/client/v3/rooms/!localpart%3Aexample.com/typing/%40alice%3Aexample.com': (var req) => {}, - '/client/r0/rooms/!1234%3Aexample.com/send/m.room.message/1234': + '/client/v3/rooms/!1234%3Aexample.com/send/m.room.message/1234': (var reqI) => { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', }, - '/client/r0/rooms/!1234%3Aexample.com/send/m.room.message/newresend': + '/client/v3/rooms/!1234%3Aexample.com/send/m.room.message/newresend': (var reqI) => { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', }, - '/client/r0/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': + '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': (var req) => {}, - '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': + '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': (var req) => {}, - '/client/r0/user/%40alice%3Aexample.com/account_data/test.account.data': + '/client/v3/user/%40alice%3Aexample.com/account_data/test.account.data': (var req) => {}, - '/client/r0/user/%40test%3AfakeServer.notExisting/account_data/best%20animal': + '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/best%20animal': (var req) => {}, - '/client/r0/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data': + '/client/v3/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data': (var req) => {}, - '/client/r0/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/account_data/com.famedly.marked_unread': + '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/account_data/com.famedly.marked_unread': (var req) => {}, - '/client/r0/user/%40test%3AfakeServer.notExisting/account_data/m.direct': + '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/m.direct': (var req) => {}, - '/client/r0/user/%40othertest%3AfakeServer.notExisting/account_data/m.direct': + '/client/v3/user/%40othertest%3AfakeServer.notExisting/account_data/m.direct': (var req) => {}, - '/client/r0/profile/%40alice%3Aexample.com/displayname': (var reqI) => {}, - '/client/r0/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => {}, - '/client/r0/profile/%40test%3AfakeServer.notExisting/avatar_url': + '/client/v3/profile/%40alice%3Aexample.com/displayname': (var reqI) => {}, + '/client/v3/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => {}, + '/client/v3/profile/%40test%3AfakeServer.notExisting/avatar_url': (var reqI) => {}, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.encryption': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.encryption': (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.avatar': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.avatar': (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, - '/client/r0/rooms/!localpart%3Aserver.abc/send/m.room.message/1234': + '/client/v3/rooms/!localpart%3Aserver.abc/send/m.room.message/1234': (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, - '/client/r0/rooms/!localpart%3Aserver.abc/redact/1234/1234': (var reqI) => + '/client/v3/rooms/!localpart%3Aserver.abc/redact/1234/1234': (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.name': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.name': (var reqI) => { 'event_id': '42', }, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.topic': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.topic': (var reqI) => { 'event_id': '42', }, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.pinned_events': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.pinned_events': (var reqI) => { 'event_id': '42', }, - '/client/r0/rooms/!localpart%3Aserver.abc/state/m.room.power_levels': + '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.power_levels': (var reqI) => { 'event_id': '42', }, - '/client/r0/directory/list/room/!localpart%3Aexample.com': (var req) => + '/client/v3/directory/list/room/!localpart%3Aexample.com': (var req) => {}, - '/client/unstable/room_keys/version/5': (var req) => {}, - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': + '/client/v3/room_keys/version/5': (var req) => {}, + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': (var req) => { 'etag': 'asdf', 'count': 1, }, - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': (var req) => { 'etag': 'asdf', 'count': 1, }, - '/client/unstable/room_keys/keys?version=5': (var req) => { + '/client/v3/room_keys/keys?version=5': (var req) => { 'etag': 'asdf', 'count': 1, }, }, 'DELETE': { '/unknown/token': (var req) => {'errcode': 'M_UNKNOWN_TOKEN'}, - '/client/r0/devices/QBUAZIFURK': (var req) => {}, - '/client/r0/directory/room/%23testalias%3Aexample.com': (var reqI) => {}, - '/client/r0/pushrules/global/content/nocake': (var req) => {}, - '/client/r0/pushrules/global/override/!localpart%3Aserver.abc': + '/client/v3/devices/QBUAZIFURK': (var req) => {}, + '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => {}, + '/client/v3/pushrules/global/content/nocake': (var req) => {}, + '/client/v3/pushrules/global/override/!localpart%3Aserver.abc': (var req) => {}, - '/client/r0/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': + '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': (var req) => {}, - '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': + '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': (var req) => {}, - '/client/unstable/room_keys/version/5': (var req) => {}, - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': + '/client/v3/room_keys/version/5': (var req) => {}, + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': (var req) => { 'etag': 'asdf', 'count': 1, }, - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5': (var req) => { 'etag': 'asdf', 'count': 1, }, - '/client/unstable/room_keys/keys?version=5': (var req) => { + '/client/v3/room_keys/keys?version=5': (var req) => { 'etag': 'asdf', 'count': 1, }, diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 7a898127..66df959e 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -42,6 +42,85 @@ class Api { return DiscoveryInformation.fromJson(json); } + /// Queries the server to determine if a given registration token is still + /// valid at the time of request. This is a point-in-time check where the + /// token might still expire by the time it is used. + /// + /// Servers should be sure to rate limit this endpoint to avoid brute force + /// attacks. + /// + /// [token] The token to check validity of. + /// + /// returns `valid`: + /// True if the token is still valid, false otherwise. This should + /// additionally be false if the token is not a recognised token by + /// the server. + Future registrationTokenValidity(String token) async { + final requestUri = Uri( + path: '_matrix/client/v1/register/m.login.registration_token/validity', + queryParameters: { + 'token': token, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return json['valid'] as bool; + } + + /// Paginates over the space tree in a depth-first manner to locate child rooms of a given space. + /// + /// Where a child room is unknown to the local server, federation is used to fill in the details. + /// The servers listed in the `via` array should be contacted to attempt to fill in missing rooms. + /// + /// Only [`m.space.child`](#mspacechild) state events of the room are considered. Invalid child + /// rooms and parent events are not covered by this endpoint. + /// + /// [roomId] The room ID of the space to get a hierarchy for. + /// + /// [suggestedOnly] Optional (default `false`) flag to indicate whether or not the server should only consider + /// suggested rooms. Suggested rooms are annotated in their [`m.space.child`](#mspacechild) event + /// contents. + /// + /// [limit] Optional limit for the maximum number of rooms to include per response. Must be an integer + /// greater than zero. + /// + /// Servers should apply a default value, and impose a maximum value to avoid resource exhaustion. + /// + /// [maxDepth] Optional limit for how far to go into the space. Must be a non-negative integer. + /// + /// When reached, no further child rooms will be returned. + /// + /// Servers should apply a default value, and impose a maximum value to avoid resource exhaustion. + /// + /// [from] A pagination token from a previous result. If specified, `max_depth` and `suggested_only` cannot + /// be changed from the first request. + Future getSpaceHierarchy(String roomId, + {bool? suggestedOnly, + double? limit, + double? maxDepth, + String? from}) async { + final requestUri = Uri( + path: + '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/hierarchy', + queryParameters: { + if (suggestedOnly != null) 'suggested_only': suggestedOnly.toString(), + if (limit != null) 'limit': limit.toString(), + if (maxDepth != null) 'max_depth': maxDepth.toString(), + if (from != null) 'from': from, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetSpaceHierarchyResponse.fromJson(json); + } + /// Gets a list of the third party identifiers that the homeserver has /// associated with the user's account. /// @@ -53,7 +132,7 @@ class Api { /// /// returns `threepids` Future?> getAccount3PIDs() async { - final requestUri = Uri(path: '_matrix/client/r0/account/3pid'); + final requestUri = Uri(path: '_matrix/client/v3/account/3pid'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -78,9 +157,23 @@ class Api { /// than dual-purpose. /// /// [threePidCreds] The third party credentials to associate with the account. + /// + /// returns `submit_url`: + /// An optional field containing a URL where the client must + /// submit the validation token to, with identical parameters + /// to the Identity Service API's `POST + /// /validate/email/submitToken` endpoint (without the requirement + /// for an access token). The homeserver must send this token to the + /// user (if applicable), who should then be prompted to provide it + /// to the client. + /// + /// If this field is not present, the client can assume that + /// verification will happen without the client's involvement + /// provided the homeserver advertises this specification version + /// in the `/versions` response (ie: r0.5.0). @deprecated - Future post3PIDs(ThreePidCredentials threePidCreds) async { - final requestUri = Uri(path: '_matrix/client/r0/account/3pid'); + Future post3PIDs(ThreePidCredentials threePidCreds) async { + final requestUri = Uri(path: '_matrix/client/v3/account/3pid'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -92,7 +185,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return null; + return ((v) => v != null ? Uri.parse(v) : null)(json['submit_url']); } /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api). @@ -111,7 +204,7 @@ class Api { /// [sid] The session identifier given by the homeserver. Future add3PID(String clientSecret, String sid, {AuthenticationData? auth}) async { - final requestUri = Uri(path: '_matrix/client/r0/account/3pid/add'); + final requestUri = Uri(path: '_matrix/client/v3/account/3pid/add'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -145,7 +238,7 @@ class Api { /// [sid] The session identifier given by the identity server. Future bind3PID(String clientSecret, String idAccessToken, String idServer, String sid) async { - final requestUri = Uri(path: '_matrix/client/r0/account/3pid/bind'); + final requestUri = Uri(path: '_matrix/client/v3/account/3pid/bind'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -189,34 +282,29 @@ class Api { Future delete3pidFromAccount( String address, ThirdPartyIdentifierMedium medium, {String? idServer}) async { - final requestUri = Uri(path: '_matrix/client/r0/account/3pid/delete'); + final requestUri = Uri(path: '_matrix/client/v3/account/3pid/delete'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ 'address': address, if (idServer != null) 'id_server': idServer, - 'medium': { - ThirdPartyIdentifierMedium.email: 'email', - ThirdPartyIdentifierMedium.msisdn: 'msisdn' - }[medium]!, + 'medium': medium.name, })); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return { - 'no-support': IdServerUnbindResult.noSupport, - 'success': IdServerUnbindResult.success - }[json['id_server_unbind_result']]!; + return IdServerUnbindResult.values + .fromString(json['id_server_unbind_result'])!; } /// The homeserver must check that the given email address is **not** /// already associated with an account on this homeserver. This API should /// be used to request validation tokens when adding an email address to an /// account. This API's parameters and response are identical to that of - /// the [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registeremailrequesttoken) + /// the [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3registeremailrequesttoken) /// endpoint. The homeserver should validate /// the email itself, either by sending a validation email itself or by using /// a service it has control over. @@ -258,7 +346,7 @@ class Api { String clientSecret, String email, int sendAttempt, {String? nextLink, String? idAccessToken, String? idServer}) async { final requestUri = - Uri(path: '_matrix/client/r0/account/3pid/email/requestToken'); + Uri(path: '_matrix/client/v3/account/3pid/email/requestToken'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ @@ -281,7 +369,7 @@ class Api { /// already associated with an account on this homeserver. This API should /// be used to request validation tokens when adding a phone number to an /// account. This API's parameters and response are identical to that of - /// the [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + /// the [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3registermsisdnrequesttoken) /// endpoint. The homeserver should validate /// the phone number itself, either by sending a validation message itself or by using /// a service it has control over. @@ -325,7 +413,7 @@ class Api { String clientSecret, String country, String phoneNumber, int sendAttempt, {String? nextLink, String? idAccessToken, String? idServer}) async { final requestUri = - Uri(path: '_matrix/client/r0/account/3pid/msisdn/requestToken'); + Uri(path: '_matrix/client/v3/account/3pid/msisdn/requestToken'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ @@ -370,27 +458,22 @@ class Api { Future unbind3pidFromAccount( String address, ThirdPartyIdentifierMedium medium, {String? idServer}) async { - final requestUri = Uri(path: '_matrix/client/r0/account/3pid/unbind'); + final requestUri = Uri(path: '_matrix/client/v3/account/3pid/unbind'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ 'address': address, if (idServer != null) 'id_server': idServer, - 'medium': { - ThirdPartyIdentifierMedium.email: 'email', - ThirdPartyIdentifierMedium.msisdn: 'msisdn' - }[medium]!, + 'medium': medium.name, })); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return { - 'no-support': IdServerUnbindResult.noSupport, - 'success': IdServerUnbindResult.success - }[json['id_server_unbind_result']]!; + return IdServerUnbindResult.values + .fromString(json['id_server_unbind_result'])!; } /// Deactivate the user's account, removing all ability for the user to @@ -428,7 +511,7 @@ class Api { /// for the user. Future deactivateAccount( {AuthenticationData? auth, String? idServer}) async { - final requestUri = Uri(path: '_matrix/client/r0/account/deactivate'); + final requestUri = Uri(path: '_matrix/client/v3/account/deactivate'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -441,10 +524,8 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return { - 'no-support': IdServerUnbindResult.noSupport, - 'success': IdServerUnbindResult.success - }[json['id_server_unbind_result']]!; + return IdServerUnbindResult.values + .fromString(json['id_server_unbind_result'])!; } /// Changes the password for an account on this homeserver. @@ -472,7 +553,7 @@ class Api { /// [newPassword] The new password for the account. Future changePassword(String newPassword, {AuthenticationData? auth, bool? logoutDevices}) async { - final requestUri = Uri(path: '_matrix/client/r0/account/password'); + final requestUri = Uri(path: '_matrix/client/v3/account/password'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -495,7 +576,7 @@ class Api { /// `/account/password` endpoint. /// /// This API's parameters and response are identical to that of the - /// [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registeremailrequesttoken) + /// [`/register/email/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3registeremailrequesttoken) /// endpoint, except that /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the /// given email address could be found. The server may instead send an @@ -542,7 +623,7 @@ class Api { String clientSecret, String email, int sendAttempt, {String? nextLink, String? idAccessToken, String? idServer}) async { final requestUri = - Uri(path: '_matrix/client/r0/account/password/email/requestToken'); + Uri(path: '_matrix/client/v3/account/password/email/requestToken'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ @@ -567,7 +648,7 @@ class Api { /// `/account/password` endpoint. /// /// This API's parameters and response are identical to that of the - /// [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0registermsisdnrequesttoken) + /// [`/register/msisdn/requestToken`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3registermsisdnrequesttoken) /// endpoint, except that /// `M_THREEPID_NOT_FOUND` may be returned if no account matching the /// given phone number could be found. The server may instead send the SMS @@ -616,7 +697,7 @@ class Api { String clientSecret, String country, String phoneNumber, int sendAttempt, {String? nextLink, String? idAccessToken, String? idServer}) async { final requestUri = - Uri(path: '_matrix/client/r0/account/password/msisdn/requestToken'); + Uri(path: '_matrix/client/v3/account/password/msisdn/requestToken'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ @@ -645,7 +726,7 @@ class Api { /// is registered by the appservice, and return it in the response /// body. Future getTokenOwner() async { - final requestUri = Uri(path: '_matrix/client/r0/account/whoami'); + final requestUri = Uri(path: '_matrix/client/v3/account/whoami'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -665,7 +746,7 @@ class Api { /// [userId] The user to look up. Future getWhoIs(String userId) async { final requestUri = Uri( - path: '_matrix/client/r0/admin/whois/${Uri.encodeComponent(userId)}'); + path: '_matrix/client/v3/admin/whois/${Uri.encodeComponent(userId)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -683,7 +764,7 @@ class Api { /// The custom capabilities the server supports, using the /// Java package naming convention. Future getCapabilities() async { - final requestUri = Uri(path: '_matrix/client/r0/capabilities'); + final requestUri = Uri(path: '_matrix/client/v3/capabilities'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -737,9 +818,9 @@ class Api { /// `creation_content`. /// /// [creationContent] Extra keys, such as `m.federate`, to be added to the content - /// of the [`m.room.create`](client-server-api/#mroomcreate) event. The server will clobber the following + /// of the [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate) event. The server will overwrite the following /// keys: `creator`, `room_version`. Future versions of the specification - /// may allow the server to clobber other keys. + /// may allow the server to overwrite other keys. /// /// [initialState] A list of state events to set in the new room. This allows /// the user to override the default state events set in the new @@ -747,7 +828,7 @@ class Api { /// with type, state_key and content keys set. /// /// Takes precedence over events set by `preset`, but gets - /// overriden by `name` and `topic` keys. + /// overridden by `name` and `topic` keys. /// /// [invite] A list of user IDs to invite to the room. This will tell the /// server to invite everyone in the list to the newly created room. @@ -765,7 +846,7 @@ class Api { /// /// [powerLevelContentOverride] The power level content to override in the default power level /// event. This object is applied on top of the generated - /// [`m.room.power_levels`](client-server-api/#mroompower_levels) + /// [`m.room.power_levels`](https://spec.matrix.org/unstable/client-server-api/#mroompower_levels) /// event content prior to it being sent to the room. Defaults to /// overriding nothing. /// @@ -819,7 +900,7 @@ class Api { String? roomVersion, String? topic, Visibility? visibility}) async { - final requestUri = Uri(path: '_matrix/client/r0/createRoom'); + final requestUri = Uri(path: '_matrix/client/v3/createRoom'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -834,20 +915,11 @@ class Api { if (name != null) 'name': name, if (powerLevelContentOverride != null) 'power_level_content_override': powerLevelContentOverride, - if (preset != null) - 'preset': { - CreateRoomPreset.privateChat: 'private_chat', - CreateRoomPreset.publicChat: 'public_chat', - CreateRoomPreset.trustedPrivateChat: 'trusted_private_chat' - }[preset]!, + if (preset != null) 'preset': preset.name, if (roomAliasName != null) 'room_alias_name': roomAliasName, if (roomVersion != null) 'room_version': roomVersion, if (topic != null) 'topic': topic, - if (visibility != null) - 'visibility': { - Visibility.public: 'public', - Visibility.private: 'private' - }[visibility]!, + if (visibility != null) 'visibility': visibility.name, })); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -867,7 +939,7 @@ class Api { /// [devices] The list of device IDs to delete. Future deleteDevices(List devices, {AuthenticationData? auth}) async { - final requestUri = Uri(path: '_matrix/client/r0/delete_devices'); + final requestUri = Uri(path: '_matrix/client/v3/delete_devices'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -888,7 +960,7 @@ class Api { /// returns `devices`: /// A list of all registered devices for this user. Future?> getDevices() async { - final requestUri = Uri(path: '_matrix/client/r0/devices'); + final requestUri = Uri(path: '_matrix/client/v3/devices'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -911,7 +983,7 @@ class Api { /// user-interactive authentication API. Future deleteDevice(String deviceId, {AuthenticationData? auth}) async { final requestUri = - Uri(path: '_matrix/client/r0/devices/${Uri.encodeComponent(deviceId)}'); + Uri(path: '_matrix/client/v3/devices/${Uri.encodeComponent(deviceId)}'); final request = Request('DELETE', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -931,7 +1003,7 @@ class Api { /// [deviceId] The device to retrieve. Future getDevice(String deviceId) async { final requestUri = - Uri(path: '_matrix/client/r0/devices/${Uri.encodeComponent(deviceId)}'); + Uri(path: '_matrix/client/v3/devices/${Uri.encodeComponent(deviceId)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -950,7 +1022,7 @@ class Api { /// display name is unchanged. Future updateDevice(String deviceId, {String? displayName}) async { final requestUri = - Uri(path: '_matrix/client/r0/devices/${Uri.encodeComponent(deviceId)}'); + Uri(path: '_matrix/client/v3/devices/${Uri.encodeComponent(deviceId)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -987,15 +1059,12 @@ class Api { String networkId, String roomId, Visibility visibility) async { final requestUri = Uri( path: - '_matrix/client/r0/directory/list/appservice/${Uri.encodeComponent(networkId)}/${Uri.encodeComponent(roomId)}'); + '_matrix/client/v3/directory/list/appservice/${Uri.encodeComponent(networkId)}/${Uri.encodeComponent(roomId)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ - 'visibility': { - Visibility.public: 'public', - Visibility.private: 'private' - }[visibility]!, + 'visibility': visibility.name, })); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -1014,16 +1083,15 @@ class Api { Future getRoomVisibilityOnDirectory(String roomId) async { final requestUri = Uri( path: - '_matrix/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}'); + '_matrix/client/v3/directory/list/room/${Uri.encodeComponent(roomId)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return ((v) => v != null - ? {'public': Visibility.public, 'private': Visibility.private}[v]! - : null)(json['visibility']); + return ((v) => v != null ? Visibility.values.fromString(v)! : null)( + json['visibility']); } /// Sets the visibility of a given room in the server's public room @@ -1041,16 +1109,12 @@ class Api { {Visibility? visibility}) async { final requestUri = Uri( path: - '_matrix/client/r0/directory/list/room/${Uri.encodeComponent(roomId)}'); + '_matrix/client/v3/directory/list/room/${Uri.encodeComponent(roomId)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ - if (visibility != null) - 'visibility': { - Visibility.public: 'public', - Visibility.private: 'private' - }[visibility]!, + if (visibility != null) 'visibility': visibility.name, })); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -1076,7 +1140,7 @@ class Api { Future deleteRoomAlias(String roomAlias) async { final requestUri = Uri( path: - '_matrix/client/r0/directory/room/${Uri.encodeComponent(roomAlias)}'); + '_matrix/client/v3/directory/room/${Uri.encodeComponent(roomAlias)}'); final request = Request('DELETE', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1097,7 +1161,7 @@ class Api { Future getRoomIdByAlias(String roomAlias) async { final requestUri = Uri( path: - '_matrix/client/r0/directory/room/${Uri.encodeComponent(roomAlias)}'); + '_matrix/client/v3/directory/room/${Uri.encodeComponent(roomAlias)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -1115,7 +1179,7 @@ class Api { Future setRoomAlias(String roomAlias, String roomId) async { final requestUri = Uri( path: - '_matrix/client/r0/directory/room/${Uri.encodeComponent(roomAlias)}'); + '_matrix/client/v3/directory/room/${Uri.encodeComponent(roomAlias)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -1134,8 +1198,8 @@ class Api { /// block until an event is received, or until the `timeout` is reached. /// /// This endpoint was deprecated in r0 of this specification. Clients - /// should instead call the [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) - /// API with a `since` parameter. See + /// should instead call the [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) + /// endpoint with a `since` parameter. See /// the [migration guide](https://matrix.org/docs/guides/migrating-from-client-server-api-v-1#deprecated-endpoints). /// /// [from] The token to stream from. This token is either from a previous @@ -1143,8 +1207,8 @@ class Api { /// /// [timeout] The maximum time in milliseconds to wait for an event. @deprecated - Future getEvents({String? from, int? timeout}) async { - final requestUri = Uri(path: '_matrix/client/r0/events', queryParameters: { + Future getEvents({String? from, int? timeout}) async { + final requestUri = Uri(path: '_matrix/client/v3/events', queryParameters: { if (from != null) 'from': from, if (timeout != null) 'timeout': timeout.toString(), }); @@ -1155,7 +1219,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return EventsSyncUpdate.fromJson(json); + return GetEventsResponse.fromJson(json); } /// This will listen for new events related to a particular room and return @@ -1175,9 +1239,9 @@ class Api { /// [timeout] The maximum time in milliseconds to wait for an event. /// /// [roomId] The room ID for which events should be returned. - Future peekEvents( + Future peekEvents( {String? from, int? timeout, String? roomId}) async { - final requestUri = Uri(path: '_matrix/client/r0/events', queryParameters: { + final requestUri = Uri(path: '_matrix/client/v3/events', queryParameters: { if (from != null) 'from': from, if (timeout != null) 'timeout': timeout.toString(), if (roomId != null) 'room_id': roomId, @@ -1189,7 +1253,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return EventsSyncUpdate.fromJson(json); + return PeekEventsResponse.fromJson(json); } /// Get a single event based on `event_id`. You must have permission to @@ -1197,14 +1261,14 @@ class Api { /// /// This endpoint was deprecated in r0 of this specification. Clients /// should instead call the - /// [/rooms/{roomId}/event/{eventId}](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0roomsroomideventeventid) API - /// or the [/rooms/{roomId}/context/{eventId](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0roomsroomidcontexteventid) API. + /// [/rooms/{roomId}/event/{eventId}](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomideventeventid) API + /// or the [/rooms/{roomId}/context/{eventId](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidcontexteventid) API. /// /// [eventId] The event ID to get. @deprecated Future getOneEvent(String eventId) async { final requestUri = - Uri(path: '_matrix/client/r0/events/${Uri.encodeComponent(eventId)}'); + Uri(path: '_matrix/client/v3/events/${Uri.encodeComponent(eventId)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1223,8 +1287,8 @@ class Api { /// events associated with the room until the user leaves the room. /// /// After a user has joined a room, the room will appear as an entry in the - /// response of the [`/initialSync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0initialsync) - /// and [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) APIs. + /// response of the [`/initialSync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3initialsync) + /// and [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) APIs. /// /// [roomIdOrAlias] The room identifier or alias to join. /// @@ -1245,7 +1309,7 @@ class Api { String? reason, ThirdPartySigned? thirdPartySigned}) async { final requestUri = Uri( - path: '_matrix/client/r0/join/${Uri.encodeComponent(roomIdOrAlias)}', + path: '_matrix/client/v3/join/${Uri.encodeComponent(roomIdOrAlias)}', queryParameters: { if (serverName != null) 'server_name': serverName.map((v) => v).toList(), @@ -1271,7 +1335,7 @@ class Api { /// returns `joined_rooms`: /// The ID of each room in which the user has `joined` membership. Future> getJoinedRooms() async { - final requestUri = Uri(path: '_matrix/client/r0/joined_rooms'); + final requestUri = Uri(path: '_matrix/client/v3/joined_rooms'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1293,18 +1357,18 @@ class Api { /// identity keys, between `from` and `to`. /// /// [from] The desired start point of the list. Should be the `next_batch` field - /// from a response to an earlier call to [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync). Users who have not + /// from a response to an earlier call to [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync). Users who have not /// uploaded new device identity keys since this point, nor deleted /// existing devices with identity keys since then, will be excluded /// from the results. /// /// [to] The desired end point of the list. Should be the `next_batch` - /// field from a recent call to [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) - typically the most recent + /// field from a recent call to [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) - typically the most recent /// such call. This may be used by the server as a hint to check its /// caches are up to date. Future getKeysChanges(String from, String to) async { final requestUri = - Uri(path: '_matrix/client/r0/keys/changes', queryParameters: { + Uri(path: '_matrix/client/v3/keys/changes', queryParameters: { 'from': from, 'to': to, }); @@ -1328,7 +1392,7 @@ class Api { Future claimKeys( Map> oneTimeKeys, {int? timeout}) async { - final requestUri = Uri(path: '_matrix/client/r0/keys/claim'); + final requestUri = Uri(path: '_matrix/client/v3/keys/claim'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -1369,7 +1433,7 @@ class Api { MatrixCrossSigningKey? selfSigningKey, MatrixCrossSigningKey? userSigningKey}) async { final requestUri = - Uri(path: '_matrix/client/unstable/keys/device_signing/upload'); + Uri(path: '_matrix/client/v3/keys/device_signing/upload'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -1402,7 +1466,7 @@ class Api { /// contains the keys advertised by the notification in that sync. Future queryKeys(Map> deviceKeys, {int? timeout, String? token}) async { - final requestUri = Uri(path: '_matrix/client/r0/keys/query'); + final requestUri = Uri(path: '_matrix/client/v3/keys/query'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -1432,7 +1496,7 @@ class Api { Future>>?> uploadCrossSigningSignatures( Map>> signatures) async { - final requestUri = Uri(path: '_matrix/client/r0/keys/signatures/upload'); + final requestUri = Uri(path: '_matrix/client/v3/keys/signatures/upload'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -1465,7 +1529,7 @@ class Api { /// history visibility to the user. /// /// The knock will appear as an entry in the response of the - /// [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) API. + /// [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) API. /// /// [roomIdOrAlias] The room identifier or alias to knock upon. /// @@ -1480,7 +1544,7 @@ class Api { Future knockRoom(String roomIdOrAlias, {List? serverName, String? reason}) async { final requestUri = Uri( - path: '_matrix/client/r0/knock/${Uri.encodeComponent(roomIdOrAlias)}', + path: '_matrix/client/v3/knock/${Uri.encodeComponent(roomIdOrAlias)}', queryParameters: { if (serverName != null) 'server_name': serverName.map((v) => v).toList(), @@ -1505,7 +1569,7 @@ class Api { /// returns `flows`: /// The homeserver's supported login types Future?> getLoginFlows() async { - final requestUri = Uri(path: '_matrix/client/r0/login'); + final requestUri = Uri(path: '_matrix/client/v3/login'); final request = Request('GET', baseUri!.resolveUri(requestUri)); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -1561,7 +1625,7 @@ class Api { String? password, String? token, String? user}) async { - final requestUri = Uri(path: '_matrix/client/r0/login'); + final requestUri = Uri(path: '_matrix/client/v3/login'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ @@ -1573,10 +1637,7 @@ class Api { if (medium != null) 'medium': medium, if (password != null) 'password': password, if (token != null) 'token': token, - 'type': { - LoginType.mLoginPassword: 'm.login.password', - LoginType.mLoginToken: 'm.login.token' - }[type]!, + 'type': type.name, if (user != null) 'user': user, })); final response = await httpClient.send(request); @@ -1591,7 +1652,7 @@ class Api { /// authorization. The device associated with the access token is also deleted. /// [Device keys](https://spec.matrix.org/unstable/client-server-api/#device-keys) for the device are deleted alongside the device. Future logout() async { - final requestUri = Uri(path: '_matrix/client/r0/logout'); + final requestUri = Uri(path: '_matrix/client/v3/logout'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1614,7 +1675,7 @@ class Api { /// the request, and therefore the attacker is unable to take over the account in /// this way. Future logoutAll() async { - final requestUri = Uri(path: '_matrix/client/r0/logout/all'); + final requestUri = Uri(path: '_matrix/client/v3/logout/all'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1628,7 +1689,8 @@ class Api { /// This API is used to paginate through the list of events that the /// user has been, or would have been notified about. /// - /// [from] Pagination token given to retrieve the next set of events. + /// [from] Pagination token to continue from. This should be the `next_token` + /// returned from an earlier call to this endpoint. /// /// [limit] Limit on the number of events to return in this request. /// @@ -1638,7 +1700,7 @@ class Api { Future getNotifications( {String? from, int? limit, String? only}) async { final requestUri = - Uri(path: '_matrix/client/r0/notifications', queryParameters: { + Uri(path: '_matrix/client/v3/notifications', queryParameters: { if (from != null) 'from': from, if (limit != null) 'limit': limit.toString(), if (only != null) 'only': only, @@ -1659,7 +1721,7 @@ class Api { Future getPresence(String userId) async { final requestUri = Uri( path: - '_matrix/client/r0/presence/${Uri.encodeComponent(userId)}/status'); + '_matrix/client/v3/presence/${Uri.encodeComponent(userId)}/status'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1684,16 +1746,12 @@ class Api { {String? statusMsg}) async { final requestUri = Uri( path: - '_matrix/client/r0/presence/${Uri.encodeComponent(userId)}/status'); + '_matrix/client/v3/presence/${Uri.encodeComponent(userId)}/status'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ - 'presence': { - PresenceType.online: 'online', - PresenceType.offline: 'offline', - PresenceType.unavailable: 'unavailable' - }[presence]!, + 'presence': presence.name, if (statusMsg != null) 'status_msg': statusMsg, })); final response = await httpClient.send(request); @@ -1712,7 +1770,7 @@ class Api { /// [userId] The user whose profile information to get. Future getUserProfile(String userId) async { final requestUri = - Uri(path: '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}'); + Uri(path: '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -1733,7 +1791,7 @@ class Api { Future getAvatarUrl(String userId) async { final requestUri = Uri( path: - '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url'); + '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}/avatar_url'); final request = Request('GET', baseUri!.resolveUri(requestUri)); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -1752,7 +1810,7 @@ class Api { Future setAvatarUrl(String userId, Uri? avatarUrl) async { final requestUri = Uri( path: - '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}/avatar_url'); + '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}/avatar_url'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -1778,7 +1836,7 @@ class Api { Future getDisplayName(String userId) async { final requestUri = Uri( path: - '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}/displayname'); + '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}/displayname'); final request = Request('GET', baseUri!.resolveUri(requestUri)); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -1797,7 +1855,7 @@ class Api { Future setDisplayName(String userId, String? displayname) async { final requestUri = Uri( path: - '_matrix/client/r0/profile/${Uri.encodeComponent(userId)}/displayname'); + '_matrix/client/v3/profile/${Uri.encodeComponent(userId)}/displayname'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -1829,7 +1887,7 @@ class Api { Future getPublicRooms( {int? limit, String? since, String? server}) async { final requestUri = - Uri(path: '_matrix/client/r0/publicRooms', queryParameters: { + Uri(path: '_matrix/client/v3/publicRooms', queryParameters: { if (limit != null) 'limit': limit.toString(), if (since != null) 'since': since, if (server != null) 'server': server, @@ -1873,7 +1931,7 @@ class Api { String? since, String? thirdPartyInstanceId}) async { final requestUri = - Uri(path: '_matrix/client/r0/publicRooms', queryParameters: { + Uri(path: '_matrix/client/v3/publicRooms', queryParameters: { if (server != null) 'server': server, }); final request = Request('POST', baseUri!.resolveUri(requestUri)); @@ -1901,7 +1959,7 @@ class Api { /// returns `pushers`: /// An array containing the current pushers for the user Future?> getPushers() async { - final requestUri = Uri(path: '_matrix/client/r0/pushers'); + final requestUri = Uri(path: '_matrix/client/v3/pushers'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1922,7 +1980,7 @@ class Api { /// returns `global`: /// The global ruleset. Future getPushRules() async { - final requestUri = Uri(path: '_matrix/client/r0/pushrules'); + final requestUri = Uri(path: '_matrix/client/v3/pushrules'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1946,13 +2004,7 @@ class Api { String scope, PushRuleKind kind, String ruleId) async { final requestUri = Uri( path: - '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ - PushRuleKind.override: 'override', - PushRuleKind.underride: 'underride', - PushRuleKind.sender: 'sender', - PushRuleKind.room: 'room', - PushRuleKind.content: 'content' - }[kind]!)}/${Uri.encodeComponent(ruleId)}'); + '_matrix/client/v3/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}'); final request = Request('DELETE', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -1976,13 +2028,7 @@ class Api { String scope, PushRuleKind kind, String ruleId) async { final requestUri = Uri( path: - '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ - PushRuleKind.override: 'override', - PushRuleKind.underride: 'underride', - PushRuleKind.sender: 'sender', - PushRuleKind.room: 'room', - PushRuleKind.content: 'content' - }[kind]!)}/${Uri.encodeComponent(ruleId)}'); + '_matrix/client/v3/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2030,13 +2076,7 @@ class Api { String? pattern}) async { final requestUri = Uri( path: - '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ - PushRuleKind.override: 'override', - PushRuleKind.underride: 'underride', - PushRuleKind.sender: 'sender', - PushRuleKind.room: 'room', - PushRuleKind.content: 'content' - }[kind]!)}/${Uri.encodeComponent(ruleId)}', + '_matrix/client/v3/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}', queryParameters: { if (before != null) 'before': before, if (after != null) 'after': after, @@ -2075,13 +2115,7 @@ class Api { String scope, PushRuleKind kind, String ruleId) async { final requestUri = Uri( path: - '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ - PushRuleKind.override: 'override', - PushRuleKind.underride: 'underride', - PushRuleKind.sender: 'sender', - PushRuleKind.room: 'room', - PushRuleKind.content: 'content' - }[kind]!)}/${Uri.encodeComponent(ruleId)}/actions'); + '_matrix/client/v3/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/actions'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2108,13 +2142,7 @@ class Api { String ruleId, List actions) async { final requestUri = Uri( path: - '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ - PushRuleKind.override: 'override', - PushRuleKind.underride: 'underride', - PushRuleKind.sender: 'sender', - PushRuleKind.room: 'room', - PushRuleKind.content: 'content' - }[kind]!)}/${Uri.encodeComponent(ruleId)}/actions'); + '_matrix/client/v3/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/actions'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -2146,13 +2174,7 @@ class Api { String scope, PushRuleKind kind, String ruleId) async { final requestUri = Uri( path: - '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ - PushRuleKind.override: 'override', - PushRuleKind.underride: 'underride', - PushRuleKind.sender: 'sender', - PushRuleKind.room: 'room', - PushRuleKind.content: 'content' - }[kind]!)}/${Uri.encodeComponent(ruleId)}/enabled'); + '_matrix/client/v3/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/enabled'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2178,13 +2200,7 @@ class Api { String scope, PushRuleKind kind, String ruleId, bool enabled) async { final requestUri = Uri( path: - '_matrix/client/r0/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent({ - PushRuleKind.override: 'override', - PushRuleKind.underride: 'underride', - PushRuleKind.sender: 'sender', - PushRuleKind.room: 'room', - PushRuleKind.content: 'content' - }[kind]!)}/${Uri.encodeComponent(ruleId)}/enabled'); + '_matrix/client/v3/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/enabled'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -2271,9 +2287,8 @@ class Api { String? password, String? username}) async { final requestUri = - Uri(path: '_matrix/client/r0/register', queryParameters: { - if (kind != null) - 'kind': {AccountKind.guest: 'guest', AccountKind.user: 'user'}[kind]!, + Uri(path: '_matrix/client/v3/register', queryParameters: { + if (kind != null) 'kind': kind.name, }); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['content-type'] = 'application/json'; @@ -2314,7 +2329,7 @@ class Api { /// be `true` when the server replies with 200 OK. Future checkUsernameAvailability(String username) async { final requestUri = - Uri(path: '_matrix/client/r0/register/available', queryParameters: { + Uri(path: '_matrix/client/v3/register/available', queryParameters: { 'username': username, }); final request = Request('GET', baseUri!.resolveUri(requestUri)); @@ -2368,7 +2383,7 @@ class Api { String clientSecret, String email, int sendAttempt, {String? nextLink, String? idAccessToken, String? idServer}) async { final requestUri = - Uri(path: '_matrix/client/r0/register/email/requestToken'); + Uri(path: '_matrix/client/v3/register/email/requestToken'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ @@ -2431,7 +2446,7 @@ class Api { String clientSecret, String country, String phoneNumber, int sendAttempt, {String? nextLink, String? idAccessToken, String? idServer}) async { final requestUri = - Uri(path: '_matrix/client/r0/register/msisdn/requestToken'); + Uri(path: '_matrix/client/v3/register/msisdn/requestToken'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ @@ -2456,7 +2471,7 @@ class Api { /// [version] The backup from which to delete the key Future deleteRoomKeys(String version) async { final requestUri = - Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { + Uri(path: '_matrix/client/v3/room_keys/keys', queryParameters: { 'version': version, }); final request = Request('DELETE', baseUri!.resolveUri(requestUri)); @@ -2474,7 +2489,7 @@ class Api { /// [version] The backup from which to retrieve the keys. Future getRoomKeys(String version) async { final requestUri = - Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { + Uri(path: '_matrix/client/v3/room_keys/keys', queryParameters: { 'version': version, }); final request = Request('GET', baseUri!.resolveUri(requestUri)); @@ -2495,7 +2510,7 @@ class Api { Future putRoomKeys( String version, RoomKeys backupData) async { final requestUri = - Uri(path: '_matrix/client/unstable/room_keys/keys', queryParameters: { + Uri(path: '_matrix/client/v3/room_keys/keys', queryParameters: { 'version': version, }); final request = Request('PUT', baseUri!.resolveUri(requestUri)); @@ -2518,8 +2533,7 @@ class Api { Future deleteRoomKeysByRoomId( String roomId, String version) async { final requestUri = Uri( - path: - '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + path: '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}', queryParameters: { 'version': version, }); @@ -2541,8 +2555,7 @@ class Api { Future getRoomKeysByRoomId( String roomId, String version) async { final requestUri = Uri( - path: - '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + path: '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}', queryParameters: { 'version': version, }); @@ -2566,8 +2579,7 @@ class Api { Future putRoomKeysByRoomId( String roomId, String version, RoomKeyBackup backupData) async { final requestUri = Uri( - path: - '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}', + path: '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}', queryParameters: { 'version': version, }); @@ -2590,11 +2602,11 @@ class Api { /// [sessionId] The ID of the megolm session whose key is to be deleted. /// /// [version] The backup from which to delete the key - Future deleteRoomKeysBySessionId( + Future deleteRoomKeyBySessionId( String roomId, String sessionId, String version) async { final requestUri = Uri( path: - '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', queryParameters: { 'version': version, }); @@ -2615,11 +2627,11 @@ class Api { /// [sessionId] The ID of the megolm session whose key is requested. /// /// [version] The backup from which to retrieve the key. - Future getRoomKeysBySessionId( + Future getRoomKeyBySessionId( String roomId, String sessionId, String version) async { final requestUri = Uri( path: - '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', queryParameters: { 'version': version, }); @@ -2642,11 +2654,11 @@ class Api { /// [version] The backup in which to store the key. Must be the current backup. /// /// [data] The key data. - Future putRoomKeysBySessionId(String roomId, + Future putRoomKeyBySessionId(String roomId, String sessionId, String version, KeyBackupData data) async { final requestUri = Uri( path: - '_matrix/client/unstable/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', + '_matrix/client/v3/room_keys/keys/${Uri.encodeComponent(roomId)}/${Uri.encodeComponent(sessionId)}', queryParameters: { 'version': version, }); @@ -2664,7 +2676,7 @@ class Api { /// Get information about the latest backup version. Future getRoomKeysVersionCurrent() async { - final requestUri = Uri(path: '_matrix/client/unstable/room_keys/version'); + final requestUri = Uri(path: '_matrix/client/v3/room_keys/version'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2687,15 +2699,12 @@ class Api { /// The backup version. This is an opaque string. Future postRoomKeysVersion( BackupAlgorithm algorithm, Map authData) async { - final requestUri = Uri(path: '_matrix/client/unstable/room_keys/version'); + final requestUri = Uri(path: '_matrix/client/v3/room_keys/version'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ - 'algorithm': { - BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: - 'm.megolm_backup.v1.curve25519-aes-sha2' - }[algorithm]!, + 'algorithm': algorithm.name, 'auth_data': authData, })); final response = await httpClient.send(request); @@ -2711,12 +2720,12 @@ class Api { /// /// [version] The backup version to delete, as returned in the `version` /// parameter in the response of - /// [`POST /_matrix/client/r0/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0room_keysversion) - /// or [`GET /_matrix/client/r0/room_keys/version/{version}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0room_keysversionversion). + /// [`POST /_matrix/client/v3/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3room_keysversion) + /// or [`GET /_matrix/client/v3/room_keys/version/{version}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3room_keysversionversion). Future deleteRoomKeysVersion(String version) async { final requestUri = Uri( path: - '_matrix/client/unstable/room_keys/version/${Uri.encodeComponent(version)}'); + '_matrix/client/v3/room_keys/version/${Uri.encodeComponent(version)}'); final request = Request('DELETE', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2731,12 +2740,12 @@ class Api { /// /// [version] The backup version to get, as returned in the `version` parameter /// of the response in - /// [`POST /_matrix/client/r0/room_keys/version`](https://spec.matrix.org/unstable/client-server/#post_matrixclientr0room_keysversion) + /// [`POST /_matrix/client/v3/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3room_keysversion) /// or this endpoint. Future getRoomKeysVersion(String version) async { final requestUri = Uri( path: - '_matrix/client/unstable/room_keys/version/${Uri.encodeComponent(version)}'); + '_matrix/client/v3/room_keys/version/${Uri.encodeComponent(version)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2751,8 +2760,8 @@ class Api { /// /// [version] The backup version to update, as returned in the `version` /// parameter in the response of - /// [`POST /_matrix/client/r0/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0room_keysversion) - /// or [`GET /_matrix/client/r0/room_keys/version/{version}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0room_keysversionversion). + /// [`POST /_matrix/client/v3/room_keys/version`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3room_keysversion) + /// or [`GET /_matrix/client/v3/room_keys/version/{version}`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3room_keysversionversion). /// /// [algorithm] The algorithm used for storing backups. Must be the same as /// the algorithm currently used by the backup. @@ -2760,19 +2769,16 @@ class Api { /// [authData] Algorithm-dependent data. See the documentation for the backup /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the /// expected format of the data. - Future putRoomKeysVersion(String version, BackupAlgorithm algorithm, - Map authData) async { + Future> putRoomKeysVersion(String version, + BackupAlgorithm algorithm, Map authData) async { final requestUri = Uri( path: - '_matrix/client/unstable/room_keys/version/${Uri.encodeComponent(version)}'); + '_matrix/client/v3/room_keys/version/${Uri.encodeComponent(version)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ - 'algorithm': { - BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: - 'm.megolm_backup.v1.curve25519-aes-sha2' - }[algorithm]!, + 'algorithm': algorithm.name, 'auth_data': authData, })); final response = await httpClient.send(request); @@ -2780,7 +2786,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return ignore(json); + return json as Map; } /// Get a list of aliases maintained by the local server for the @@ -2806,7 +2812,7 @@ class Api { /// The server's local aliases on the room. Can be empty. Future> getLocalAliases(String roomId) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/aliases'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/aliases'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2830,7 +2836,7 @@ class Api { /// [userId] The fully qualified user ID of the user being banned. Future ban(String roomId, String userId, {String? reason}) async { final requestUri = - Uri(path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/ban'); + Uri(path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/ban'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -2870,7 +2876,7 @@ class Api { {int? limit, String? filter}) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/context/${Uri.encodeComponent(eventId)}', + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/context/${Uri.encodeComponent(eventId)}', queryParameters: { if (limit != null) 'limit': limit.toString(), if (filter != null) 'filter': filter, @@ -2894,7 +2900,7 @@ class Api { Future getOneRoomEvent(String roomId, String eventId) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/event/${Uri.encodeComponent(eventId)}'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/event/${Uri.encodeComponent(eventId)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2918,7 +2924,7 @@ class Api { /// [roomId] The room identifier to forget. Future forgetRoom(String roomId) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/forget'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/forget'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -2934,7 +2940,7 @@ class Api { /// identifier of the invitee, and instead relies on third party identifiers. /// The homeserver uses an identity server to perform the mapping from /// third party identifier to a Matrix identifier. The other is documented in the* - /// [joining rooms section](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0roomsroomidinvite). + /// [joining rooms section](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3roomsroomidinvite). /// /// This API invites a user to participate in a particular room. /// They do not start participating in the room until they actually join the @@ -2984,7 +2990,7 @@ class Api { Future inviteBy3PID(String roomId, String address, String idAccessToken, String idServer, String medium) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/invite'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/invite'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3005,7 +3011,7 @@ class Api { /// *Note that there are two forms of this API, which are documented separately. /// This version of the API requires that the inviter knows the Matrix /// identifier of the invitee. The other is documented in the* - /// [third party invites section](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientr0roomsroomidinvite-1). + /// [third party invites section](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3roomsroomidinvite-1). /// /// This API invites a user to participate in a particular room. /// They do not start participating in the room until they actually join the @@ -3026,7 +3032,7 @@ class Api { Future inviteUser(String roomId, String userId, {String? reason}) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/invite'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/invite'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3051,8 +3057,8 @@ class Api { /// events associated with the room until the user leaves the room. /// /// After a user has joined a room, the room will appear as an entry in the - /// response of the [`/initialSync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0initialsync) - /// and [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientr0sync) APIs. + /// response of the [`/initialSync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3initialsync) + /// and [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync) APIs. /// /// [roomId] The room identifier (not alias) to join. /// @@ -3068,7 +3074,7 @@ class Api { Future joinRoomById(String roomId, {String? reason, ThirdPartySigned? thirdPartySigned}) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/join'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/join'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3094,7 +3100,7 @@ class Api { Future?> getJoinedMembersByRoom(String roomId) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/joined_members'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/joined_members'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -3124,7 +3130,7 @@ class Api { /// [userId] The fully qualified user ID of the user being kicked. Future kick(String roomId, String userId, {String? reason}) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/kick'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/kick'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3158,7 +3164,7 @@ class Api { /// membership event. Future leaveRoom(String roomId, {String? reason}) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/leave'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/leave'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3194,25 +3200,11 @@ class Api { Future?> getMembersByRoom(String roomId, {String? at, Membership? membership, Membership? notMembership}) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/members', + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/members', queryParameters: { if (at != null) 'at': at, - if (membership != null) - 'membership': { - Membership.invite: 'invite', - Membership.join: 'join', - Membership.knock: 'knock', - Membership.leave: 'leave', - Membership.ban: 'ban' - }[membership]!, - if (notMembership != null) - 'not_membership': { - Membership.invite: 'invite', - Membership.join: 'join', - Membership.knock: 'knock', - Membership.leave: 'leave', - Membership.ban: 'ban' - }[notMembership]!, + if (membership != null) 'membership': membership.name, + if (notMembership != null) 'not_membership': notMembership.name, }); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; @@ -3235,16 +3227,21 @@ class Api { /// [roomId] The room to get events from. /// /// [from] 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. + /// from a `prev_batch` or `next_batch` token returned by the `/sync` endpoint, + /// or from an `end` token returned by a previous request to this endpoint. + /// + /// This endpoint can also accept a value returned as a `start` token + /// by a previous request to this endpoint, though servers are not + /// required to support this. Clients should not rely on the behaviour. /// /// [to] 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. + /// a `prev_batch` or `next_batch` token returned by the `/sync` endpoint, + /// or from an `end` token returned by a previous request to this endpoint. /// - /// [dir] The direction to return events from. + /// [dir] The direction to return events from. If this is set to `f`, events + /// will be returned in chronological order starting at `from`. If it + /// is set to `b`, events will be returned in *reverse* chronological + /// order, again starting at `from`. /// /// [limit] The maximum number of events to return. Default: 10. /// @@ -3253,11 +3250,11 @@ class Api { String roomId, String from, Direction dir, {String? to, int? limit, String? filter}) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/messages', + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/messages', queryParameters: { 'from': from, if (to != null) 'to': to, - 'dir': {Direction.b: 'b', Direction.f: 'f'}[dir]!, + 'dir': dir.name, if (limit != null) 'limit': limit.toString(), if (filter != null) 'filter': filter, }); @@ -3286,7 +3283,7 @@ class Api { {String? mRead}) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/read_markers'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/read_markers'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3317,9 +3314,7 @@ class Api { String eventId, Map receipt) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/receipt/${Uri.encodeComponent({ - ReceiptType.mRead: 'm.read' - }[receiptType]!)}/${Uri.encodeComponent(eventId)}'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/receipt/${Uri.encodeComponent(receiptType.name)}/${Uri.encodeComponent(eventId)}'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3359,7 +3354,7 @@ class Api { {String? reason}) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/redact/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(txnId)}'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/redact/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(txnId)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3389,7 +3384,7 @@ class Api { {String? reason, int? score}) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/report/${Uri.encodeComponent(eventId)}'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/report/${Uri.encodeComponent(eventId)}'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3427,7 +3422,7 @@ class Api { Map body) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/send/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/send/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3445,7 +3440,7 @@ class Api { /// [roomId] The room to look up the state for. Future> getRoomState(String roomId) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/state'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/state'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -3471,7 +3466,7 @@ class Api { String roomId, String eventType, String stateKey) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -3514,7 +3509,7 @@ class Api { String stateKey, Map body) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3544,7 +3539,7 @@ class Api { {int? timeout}) async { final requestUri = Uri( path: - '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/typing/${Uri.encodeComponent(userId)}'); + '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/typing/${Uri.encodeComponent(userId)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3573,7 +3568,7 @@ class Api { /// [userId] The fully qualified user ID of the user being unbanned. Future unban(String roomId, String userId, {String? reason}) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/unban'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/unban'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3599,7 +3594,7 @@ class Api { /// The ID of the new room. Future upgradeRoom(String roomId, String newVersion) async { final requestUri = Uri( - path: '_matrix/client/r0/rooms/${Uri.encodeComponent(roomId)}/upgrade'); + path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/upgrade'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3622,7 +3617,7 @@ class Api { /// [searchCategories] Describes which categories to search in and their criteria. Future search(Categories searchCategories, {String? nextBatch}) async { - final requestUri = Uri(path: '_matrix/client/r0/search', queryParameters: { + final requestUri = Uri(path: '_matrix/client/v3/search', queryParameters: { if (nextBatch != null) 'next_batch': nextBatch, }); final request = Request('POST', baseUri!.resolveUri(requestUri)); @@ -3655,7 +3650,7 @@ class Api { Map>> messages) async { final requestUri = Uri( path: - '_matrix/client/r0/sendToDevice/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}'); + '_matrix/client/v3/sendToDevice/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3703,7 +3698,8 @@ class Api { /// /// See [Filtering](https://spec.matrix.org/unstable/client-server-api/#filtering) for more information. /// - /// [since] A point in time to continue a sync from. + /// [since] A point in time to continue a sync from. This should be the + /// `next_batch` token returned by an earlier call to this endpoint. /// /// [fullState] Controls whether to include the full state for all rooms the user /// is a member of. @@ -3738,16 +3734,11 @@ class Api { bool? fullState, PresenceType? setPresence, int? timeout}) async { - final requestUri = Uri(path: '_matrix/client/r0/sync', queryParameters: { + final requestUri = Uri(path: '_matrix/client/v3/sync', queryParameters: { if (filter != null) 'filter': filter, if (since != null) 'since': since, if (fullState != null) 'full_state': fullState.toString(), - if (setPresence != null) - 'set_presence': { - PresenceType.online: 'online', - PresenceType.offline: 'offline', - PresenceType.unavailable: 'unavailable' - }[setPresence]!, + if (setPresence != null) 'set_presence': setPresence.name, if (timeout != null) 'timeout': timeout.toString(), }); final request = Request('GET', baseUri!.resolveUri(requestUri)); @@ -3766,7 +3757,7 @@ class Api { /// [alias] The Matrix room alias to look up. Future> queryLocationByAlias(String alias) async { final requestUri = - Uri(path: '_matrix/client/r0/thirdparty/location', queryParameters: { + Uri(path: '_matrix/client/v3/thirdparty/location', queryParameters: { 'alias': alias, }); final request = Request('GET', baseUri!.resolveUri(requestUri)); @@ -3796,7 +3787,7 @@ class Api { {String? searchFields}) async { final requestUri = Uri( path: - '_matrix/client/r0/thirdparty/location/${Uri.encodeComponent(protocol)}', + '_matrix/client/v3/thirdparty/location/${Uri.encodeComponent(protocol)}', queryParameters: { if (searchFields != null) 'searchFields': searchFields, }); @@ -3816,7 +3807,7 @@ class Api { Future getProtocolMetadata(String protocol) async { final requestUri = Uri( path: - '_matrix/client/r0/thirdparty/protocol/${Uri.encodeComponent(protocol)}'); + '_matrix/client/v3/thirdparty/protocol/${Uri.encodeComponent(protocol)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -3831,7 +3822,7 @@ class Api { /// homeserver. Includes both the available protocols and all fields /// required for queries against each protocol. Future> getProtocols() async { - final requestUri = Uri(path: '_matrix/client/r0/thirdparty/protocols'); + final requestUri = Uri(path: '_matrix/client/v3/thirdparty/protocols'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -3848,7 +3839,7 @@ class Api { /// [userid] The Matrix User ID to look up. Future> queryUserByID(String userid) async { final requestUri = - Uri(path: '_matrix/client/r0/thirdparty/user', queryParameters: { + Uri(path: '_matrix/client/v3/thirdparty/user', queryParameters: { 'userid': userid, }); final request = Request('GET', baseUri!.resolveUri(requestUri)); @@ -3871,7 +3862,7 @@ class Api { {String? fields}) async { final requestUri = Uri( path: - '_matrix/client/r0/thirdparty/user/${Uri.encodeComponent(protocol)}', + '_matrix/client/v3/thirdparty/user/${Uri.encodeComponent(protocol)}', queryParameters: { if (fields != null) 'fields...': fields, }); @@ -3897,7 +3888,7 @@ class Api { String userId, String type) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -3923,7 +3914,7 @@ class Api { String userId, String type, Map content) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3951,7 +3942,7 @@ class Api { /// declared filter by homeservers on some APIs. Future defineFilter(String userId, Filter filter) async { final requestUri = Uri( - path: '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/filter'); + path: '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/filter'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -3972,7 +3963,7 @@ class Api { Future getFilter(String userId, String filterId) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/filter/${Uri.encodeComponent(filterId)}'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/filter/${Uri.encodeComponent(filterId)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -4000,7 +3991,7 @@ class Api { String userId, Map body) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/openid/request_token'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/openid/request_token'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -4027,7 +4018,7 @@ class Api { String userId, String roomId, String type) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -4055,7 +4046,7 @@ class Api { Map content) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -4079,7 +4070,7 @@ class Api { Future?> getRoomTags(String userId, String roomId) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -4104,7 +4095,7 @@ class Api { Future deleteRoomTag(String userId, String roomId, String tag) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}'); final request = Request('DELETE', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -4131,7 +4122,7 @@ class Api { Map additionalProperties = const {}}) async { final requestUri = Uri( path: - '_matrix/client/r0/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}'); + '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}'); final request = Request('PUT', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -4163,7 +4154,7 @@ class Api { /// [searchTerm] The term to search for Future searchUserDirectory(String searchTerm, {int? limit}) async { - final requestUri = Uri(path: '_matrix/client/r0/user_directory/search'); + final requestUri = Uri(path: '_matrix/client/v3/user_directory/search'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; @@ -4182,7 +4173,7 @@ class Api { /// This API provides credentials for the client to use when initiating /// calls. Future getTurnServer() async { - final requestUri = Uri(path: '_matrix/client/r0/voip/turnServer'); + final requestUri = Uri(path: '_matrix/client/v3/voip/turnServer'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -4195,10 +4186,9 @@ class Api { /// Gets the versions of the specification supported by the server. /// - /// Values will take the form `rX.Y.Z`. - /// - /// Only the latest `Z` value will be reported for each supported `X.Y` value. - /// i.e. if the server implements `r0.0.0`, `r0.0.1`, and `r1.2.0`, it will report `r0.0.1` and `r1.2.0`. + /// Values will take the form `vX.Y` or `rX.Y.Z` in historical cases. See + /// [the Specification Versioning](../#specification-versions) for more + /// information. /// /// The server may additionally advertise experimental features it supports /// through `unstable_features`. These features should be namespaced and @@ -4234,7 +4224,7 @@ class Api { /// repository APIs, for example, proxies may enforce a lower upload size limit /// than is advertised by the server on this endpoint. Future getConfig() async { - final requestUri = Uri(path: '_matrix/media/r0/config'); + final requestUri = Uri(path: '_matrix/media/v3/config'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); @@ -4261,7 +4251,7 @@ class Api { {bool? allowRemote}) async { final requestUri = Uri( path: - '_matrix/media/r0/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}', + '_matrix/media/v3/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}', queryParameters: { if (allowRemote != null) 'allow_remote': allowRemote.toString(), }); @@ -4294,7 +4284,7 @@ class Api { {bool? allowRemote}) async { final requestUri = Uri( path: - '_matrix/media/r0/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}/${Uri.encodeComponent(fileName)}', + '_matrix/media/v3/download/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}/${Uri.encodeComponent(fileName)}', queryParameters: { if (allowRemote != null) 'allow_remote': allowRemote.toString(), }); @@ -4322,7 +4312,7 @@ class Api { /// available. Future getUrlPreview(Uri url, {int? ts}) async { final requestUri = - Uri(path: '_matrix/media/r0/preview_url', queryParameters: { + Uri(path: '_matrix/media/v3/preview_url', queryParameters: { 'url': url.toString(), if (ts != null) 'ts': ts.toString(), }); @@ -4362,12 +4352,11 @@ class Api { {Method? method, bool? allowRemote}) async { final requestUri = Uri( path: - '_matrix/media/r0/thumbnail/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}', + '_matrix/media/v3/thumbnail/${Uri.encodeComponent(serverName)}/${Uri.encodeComponent(mediaId)}', queryParameters: { 'width': width.toString(), 'height': height.toString(), - if (method != null) - 'method': {Method.crop: 'crop', Method.scale: 'scale'}[method]!, + if (method != null) 'method': method.name, if (allowRemote != null) 'allow_remote': allowRemote.toString(), }); final request = Request('GET', baseUri!.resolveUri(requestUri)); @@ -4390,7 +4379,7 @@ class Api { /// The [MXC URI](https://spec.matrix.org/unstable/client-server-api/#matrix-content-mxc-uris) to the uploaded content. Future uploadContent(Uint8List content, {String? filename, String? contentType}) async { - final requestUri = Uri(path: '_matrix/media/r0/upload', queryParameters: { + final requestUri = Uri(path: '_matrix/media/v3/upload', queryParameters: { if (filename != null) 'filename': filename, }); final request = Request('POST', baseUri!.resolveUri(requestUri)); diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index edc8d356..db8cb054 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -6,6 +6,8 @@ import '../model/sync_update.dart'; import '../model/matrix_event.dart'; import 'internal.dart'; +import 'package:enhanced_enum/enhanced_enum.dart'; +part 'model.g.dart'; class _NameSource { final String source; @@ -82,8 +84,238 @@ class DiscoveryInformation { Map> additionalProperties; } +@_NameSource('spec') +class PublicRoomsChunk { + PublicRoomsChunk({ + this.avatarUrl, + this.canonicalAlias, + required this.guestCanJoin, + this.joinRule, + this.name, + required this.numJoinedMembers, + required this.roomId, + this.topic, + required this.worldReadable, + }); + + PublicRoomsChunk.fromJson(Map json) + : avatarUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + canonicalAlias = + ((v) => v != null ? v as String : null)(json['canonical_alias']), + guestCanJoin = json['guest_can_join'] as bool, + joinRule = ((v) => v != null ? v as String : null)(json['join_rule']), + name = ((v) => v != null ? v as String : null)(json['name']), + numJoinedMembers = json['num_joined_members'] as int, + roomId = json['room_id'] as String, + topic = ((v) => v != null ? v as String : null)(json['topic']), + worldReadable = json['world_readable'] as bool; + Map toJson() { + final avatarUrl = this.avatarUrl; + final canonicalAlias = this.canonicalAlias; + final joinRule = this.joinRule; + final name = this.name; + final topic = this.topic; + return { + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + if (canonicalAlias != null) 'canonical_alias': canonicalAlias, + 'guest_can_join': guestCanJoin, + if (joinRule != null) 'join_rule': joinRule, + if (name != null) 'name': name, + 'num_joined_members': numJoinedMembers, + 'room_id': roomId, + if (topic != null) 'topic': topic, + 'world_readable': worldReadable, + }; + } + + /// The URL for the room's avatar, if one is set. + Uri? avatarUrl; + + /// The canonical alias of the room, if any. + String? canonicalAlias; + + /// 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. + bool guestCanJoin; + + /// The room's join rule. When not present, the room is assumed to + /// be `public`. + String? joinRule; + + /// The name of the room, if any. + String? name; + + /// The number of members joined to the room. + int numJoinedMembers; + + /// The ID of the room. + String roomId; + + /// The topic of the room, if any. + String? topic; + + /// Whether the room may be viewed by guest users without joining. + bool worldReadable; +} + @_NameSource('rule override generated') -enum ThirdPartyIdentifierMedium { email, msisdn } +class SpaceRoomsChunkBase { + SpaceRoomsChunkBase({ + required this.childrenState, + required this.roomType, + }); + + SpaceRoomsChunkBase.fromJson(Map json) + : childrenState = (json['children_state'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(), + roomType = json['room_type'] as String; + Map toJson() => { + 'children_state': childrenState.map((v) => v.toJson()).toList(), + 'room_type': roomType, + }; + + /// The [`m.space.child`](#mspacechild) events of the space-room, represented + /// as [Stripped State Events](#stripped-state) with an added `origin_server_ts` key. + /// + /// If the room is not a space-room, this should be empty. + List childrenState; + + /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. + String roomType; +} + +@_NameSource('rule override generated') +class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { + SpaceRoomsChunk({ + this.avatarUrl, + this.canonicalAlias, + required this.guestCanJoin, + this.joinRule, + this.name, + required this.numJoinedMembers, + required this.roomId, + this.topic, + required this.worldReadable, + required this.childrenState, + required this.roomType, + }); + + SpaceRoomsChunk.fromJson(Map json) + : avatarUrl = + ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + canonicalAlias = + ((v) => v != null ? v as String : null)(json['canonical_alias']), + guestCanJoin = json['guest_can_join'] as bool, + joinRule = ((v) => v != null ? v as String : null)(json['join_rule']), + name = ((v) => v != null ? v as String : null)(json['name']), + numJoinedMembers = json['num_joined_members'] as int, + roomId = json['room_id'] as String, + topic = ((v) => v != null ? v as String : null)(json['topic']), + worldReadable = json['world_readable'] as bool, + childrenState = (json['children_state'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(), + roomType = json['room_type'] as String; + Map toJson() { + final avatarUrl = this.avatarUrl; + final canonicalAlias = this.canonicalAlias; + final joinRule = this.joinRule; + final name = this.name; + final topic = this.topic; + return { + if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), + if (canonicalAlias != null) 'canonical_alias': canonicalAlias, + 'guest_can_join': guestCanJoin, + if (joinRule != null) 'join_rule': joinRule, + if (name != null) 'name': name, + 'num_joined_members': numJoinedMembers, + 'room_id': roomId, + if (topic != null) 'topic': topic, + 'world_readable': worldReadable, + 'children_state': childrenState.map((v) => v.toJson()).toList(), + 'room_type': roomType, + }; + } + + /// The URL for the room's avatar, if one is set. + Uri? avatarUrl; + + /// The canonical alias of the room, if any. + String? canonicalAlias; + + /// 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. + bool guestCanJoin; + + /// The room's join rule. When not present, the room is assumed to + /// be `public`. + String? joinRule; + + /// The name of the room, if any. + String? name; + + /// The number of members joined to the room. + int numJoinedMembers; + + /// The ID of the room. + String roomId; + + /// The topic of the room, if any. + String? topic; + + /// Whether the room may be viewed by guest users without joining. + bool worldReadable; + + /// The [`m.space.child`](#mspacechild) events of the space-room, represented + /// as [Stripped State Events](#stripped-state) with an added `origin_server_ts` key. + /// + /// If the room is not a space-room, this should be empty. + List childrenState; + + /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. + String roomType; +} + +@_NameSource('generated') +class GetSpaceHierarchyResponse { + GetSpaceHierarchyResponse({ + this.nextBatch, + required this.rooms, + }); + + GetSpaceHierarchyResponse.fromJson(Map json) + : nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), + rooms = (json['rooms'] as List) + .map((v) => SpaceRoomsChunk.fromJson(v)) + .toList(); + Map toJson() { + final nextBatch = this.nextBatch; + return { + if (nextBatch != null) 'next_batch': nextBatch, + 'rooms': rooms.map((v) => v.toJson()).toList(), + }; + } + + /// A token to supply to `from` to keep paginating the responses. Not present when there are + /// no further results. + String? nextBatch; + + /// The rooms for the current page, with the current filters. + List rooms; +} + +@_NameSource('rule override generated') +@EnhancedEnum() +enum ThirdPartyIdentifierMedium { + @EnhancedEnumValue(name: 'email') + email, + @EnhancedEnumValue(name: 'msisdn') + msisdn +} @_NameSource('spec') class ThirdPartyIdentifier { @@ -97,18 +329,12 @@ class ThirdPartyIdentifier { ThirdPartyIdentifier.fromJson(Map json) : addedAt = json['added_at'] as int, address = json['address'] as String, - medium = { - 'email': ThirdPartyIdentifierMedium.email, - 'msisdn': ThirdPartyIdentifierMedium.msisdn - }[json['medium']]!, + medium = ThirdPartyIdentifierMedium.values.fromString(json['medium'])!, validatedAt = json['validated_at'] as int; Map toJson() => { 'added_at': addedAt, 'address': address, - 'medium': { - ThirdPartyIdentifierMedium.email: 'email', - ThirdPartyIdentifierMedium.msisdn: 'msisdn' - }[medium]!, + 'medium': medium.name, 'validated_at': validatedAt, }; @@ -163,7 +389,13 @@ class ThreePidCredentials { } @_NameSource('generated') -enum IdServerUnbindResult { noSupport, success } +@EnhancedEnum() +enum IdServerUnbindResult { + @EnhancedEnumValue(name: 'no-support') + noSupport, + @EnhancedEnumValue(name: 'success') + success +} @_NameSource('spec') class RequestTokenResponse { @@ -206,16 +438,20 @@ class RequestTokenResponse { class TokenOwnerInfo { TokenOwnerInfo({ this.deviceId, + this.isGuest, required this.userId, }); TokenOwnerInfo.fromJson(Map json) : deviceId = ((v) => v != null ? v as String : null)(json['device_id']), + isGuest = ((v) => v != null ? v as bool : null)(json['is_guest']), userId = json['user_id'] as String; Map toJson() { final deviceId = this.deviceId; + final isGuest = this.isGuest; return { if (deviceId != null) 'device_id': deviceId, + if (isGuest != null) 'is_guest': isGuest, 'user_id': userId, }; } @@ -226,6 +462,11 @@ class TokenOwnerInfo { /// Otherwise this is required. String? deviceId; + /// When `true`, the user is a [Guest User](#guest-access). When + /// not present or `false`, the user is presumed to be a non-guest + /// user. + bool? isGuest; + /// The user ID that owns the access token. String userId; } @@ -355,7 +596,13 @@ class ChangePasswordCapability { /// The stability of the room version. @_NameSource('rule override generated') -enum RoomVersionAvailable { stable, unstable } +@EnhancedEnum() +enum RoomVersionAvailable { + @EnhancedEnumValue(name: 'stable') + stable, + @EnhancedEnumValue(name: 'unstable') + unstable +} @_NameSource('spec') class RoomVersionsCapability { @@ -365,21 +612,11 @@ class RoomVersionsCapability { }); RoomVersionsCapability.fromJson(Map json) - : available = (json['available'] as Map).map((k, v) => - MapEntry( - k, - { - 'stable': RoomVersionAvailable.stable, - 'unstable': RoomVersionAvailable.unstable - }[v]!)), + : available = (json['available'] as Map).map( + (k, v) => MapEntry(k, RoomVersionAvailable.values.fromString(v)!)), default$ = json['default'] as String; Map toJson() => { - 'available': available.map((k, v) => MapEntry( - k, - { - RoomVersionAvailable.stable: 'stable', - RoomVersionAvailable.unstable: 'unstable' - }[v]!)), + 'available': available.map((k, v) => MapEntry(k, v.name)), 'default': default$, }; @@ -497,10 +734,24 @@ class Invite3pid { } @_NameSource('rule override generated') -enum CreateRoomPreset { privateChat, publicChat, trustedPrivateChat } +@EnhancedEnum() +enum CreateRoomPreset { + @EnhancedEnumValue(name: 'private_chat') + privateChat, + @EnhancedEnumValue(name: 'public_chat') + publicChat, + @EnhancedEnumValue(name: 'trusted_private_chat') + trustedPrivateChat +} @_NameSource('generated') -enum Visibility { private, public } +@EnhancedEnum() +enum Visibility { + @EnhancedEnumValue(name: 'private') + private, + @EnhancedEnumValue(name: 'public') + public +} /// A client device @_NameSource('spec') @@ -576,15 +827,52 @@ class GetRoomIdByAliasResponse { List? servers; } -@_NameSource('rule override generated') -class EventsSyncUpdate { - EventsSyncUpdate({ +@_NameSource('generated') +class GetEventsResponse { + GetEventsResponse({ this.chunk, this.end, this.start, }); - EventsSyncUpdate.fromJson(Map json) + GetEventsResponse.fromJson(Map json) + : chunk = ((v) => v != null + ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + : null)(json['chunk']), + end = ((v) => v != null ? v as String : null)(json['end']), + start = ((v) => v != null ? v as String : null)(json['start']); + Map toJson() { + final chunk = this.chunk; + final end = this.end; + final start = this.start; + return { + if (chunk != null) 'chunk': chunk.map((v) => v.toJson()).toList(), + if (end != null) 'end': end, + if (start != null) 'start': start, + }; + } + + /// An array of events. + List? chunk; + + /// A token which correlates to the end of `chunk`. This + /// token should be used in the next request to `/events`. + String? end; + + /// A token which correlates to the start of `chunk`. This + /// is usually the same token supplied to `from=`. + String? start; +} + +@_NameSource('generated') +class PeekEventsResponse { + PeekEventsResponse({ + this.chunk, + this.end, + this.start, + }); + + PeekEventsResponse.fromJson(Map json) : chunk = ((v) => v != null ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() : null)(json['chunk']), @@ -727,6 +1015,9 @@ class ClaimKeysResponse { /// /// See the [key algorithms](https://spec.matrix.org/unstable/client-server-api/#key-algorithms) section for information /// on the Key Object format. + /// + /// If necessary, the claimed key might be a fallback key. Fallback + /// keys are re-used by the server until replaced by the device. Map> oneTimeKeys; } @@ -844,7 +1135,13 @@ class LoginFlow { } @_NameSource('rule override generated') -enum LoginType { mLoginPassword, mLoginToken } +@EnhancedEnum() +enum LoginType { + @EnhancedEnumValue(name: 'm.login.password') + mLoginPassword, + @EnhancedEnumValue(name: 'm.login.token') + mLoginToken +} @_NameSource('generated') class LoginResponse { @@ -990,7 +1287,15 @@ class GetNotificationsResponse { } @_NameSource('rule override generated') -enum PresenceType { offline, online, unavailable } +@EnhancedEnum() +enum PresenceType { + @EnhancedEnumValue(name: 'offline') + offline, + @EnhancedEnumValue(name: 'online') + online, + @EnhancedEnumValue(name: 'unavailable') + unavailable +} @_NameSource('generated') class GetPresenceResponse { @@ -1006,11 +1311,7 @@ class GetPresenceResponse { ((v) => v != null ? v as bool : null)(json['currently_active']), lastActiveAgo = ((v) => v != null ? v as int : null)(json['last_active_ago']), - presence = { - 'online': PresenceType.online, - 'offline': PresenceType.offline, - 'unavailable': PresenceType.unavailable - }[json['presence']]!, + presence = PresenceType.values.fromString(json['presence'])!, statusMsg = ((v) => v != null ? v as String : null)(json['status_msg']); Map toJson() { final currentlyActive = this.currentlyActive; @@ -1019,11 +1320,7 @@ class GetPresenceResponse { return { if (currentlyActive != null) 'currently_active': currentlyActive, if (lastActiveAgo != null) 'last_active_ago': lastActiveAgo, - 'presence': { - PresenceType.online: 'online', - PresenceType.offline: 'offline', - PresenceType.unavailable: 'unavailable' - }[presence]!, + 'presence': presence.name, if (statusMsg != null) 'status_msg': statusMsg, }; } @@ -1070,93 +1367,6 @@ class ProfileInformation { String? displayname; } -@_NameSource('spec') -class PublicRoomsChunk { - PublicRoomsChunk({ - this.aliases, - this.avatarUrl, - this.canonicalAlias, - required this.guestCanJoin, - this.joinRule, - this.name, - required this.numJoinedMembers, - required this.roomId, - this.topic, - required this.worldReadable, - }); - - PublicRoomsChunk.fromJson(Map json) - : aliases = ((v) => v != null - ? (v as List).map((v) => v as String).toList() - : null)(json['aliases']), - avatarUrl = - ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), - canonicalAlias = - ((v) => v != null ? v as String : null)(json['canonical_alias']), - guestCanJoin = json['guest_can_join'] as bool, - joinRule = ((v) => v != null ? v as String : null)(json['join_rule']), - name = ((v) => v != null ? v as String : null)(json['name']), - numJoinedMembers = json['num_joined_members'] as int, - roomId = json['room_id'] as String, - topic = ((v) => v != null ? v as String : null)(json['topic']), - worldReadable = json['world_readable'] as bool; - Map toJson() { - final aliases = this.aliases; - final avatarUrl = this.avatarUrl; - final canonicalAlias = this.canonicalAlias; - final joinRule = this.joinRule; - final name = this.name; - final topic = this.topic; - return { - if (aliases != null) 'aliases': aliases.map((v) => v).toList(), - if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), - if (canonicalAlias != null) 'canonical_alias': canonicalAlias, - 'guest_can_join': guestCanJoin, - if (joinRule != null) 'join_rule': joinRule, - if (name != null) 'name': name, - 'num_joined_members': numJoinedMembers, - 'room_id': roomId, - if (topic != null) 'topic': topic, - 'world_readable': worldReadable, - }; - } - - /// Aliases of the room. May be empty. - List? aliases; - - /// The URL for the room's avatar, if one is set. - Uri? avatarUrl; - - /// The canonical alias of the room, if any. - String? canonicalAlias; - - /// 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. - bool guestCanJoin; - - /// The room's join rule. When not present, the room is assumed to - /// be `public`. Note that rooms with `invite` join rules are not - /// expected here, but rooms with `knock` rules are given their - /// near-public nature. - String? joinRule; - - /// The name of the room, if any. - String? name; - - /// The number of members joined to the room. - int numJoinedMembers; - - /// The ID of the room. - String roomId; - - /// The topic of the room, if any. - String? topic; - - /// Whether the room may be viewed by guest users without joining. - bool worldReadable; -} - /// A list of the rooms on the server. @_NameSource('generated') class GetPublicRoomsResponse { @@ -1453,9 +1663,7 @@ class PushCondition { String kind; /// Required for `event_match` conditions. The glob-style pattern to - /// match against. Patterns with no special glob characters should be - /// treated as having asterisks prepended and appended when testing the - /// condition. + /// match against. String? pattern; } @@ -1570,10 +1778,28 @@ class PushRuleSet { } @_NameSource('rule override generated') -enum PushRuleKind { content, override, room, sender, underride } +@EnhancedEnum() +enum PushRuleKind { + @EnhancedEnumValue(name: 'content') + content, + @EnhancedEnumValue(name: 'override') + override, + @EnhancedEnumValue(name: 'room') + room, + @EnhancedEnumValue(name: 'sender') + sender, + @EnhancedEnumValue(name: 'underride') + underride +} @_NameSource('rule override generated') -enum AccountKind { guest, user } +@EnhancedEnum() +enum AccountKind { + @EnhancedEnumValue(name: 'guest') + guest, + @EnhancedEnumValue(name: 'user') + user +} @_NameSource('generated') class RegisterResponse { @@ -1725,7 +1951,11 @@ class RoomKeys { } @_NameSource('rule override generated') -enum BackupAlgorithm { mMegolmBackupV1Curve25519AesSha2 } +@EnhancedEnum() +enum BackupAlgorithm { + @EnhancedEnumValue(name: 'm.megolm_backup.v1.curve25519-aes-sha2') + mMegolmBackupV1Curve25519AesSha2 +} @_NameSource('generated') class GetRoomKeysVersionCurrentResponse { @@ -1738,19 +1968,13 @@ class GetRoomKeysVersionCurrentResponse { }); GetRoomKeysVersionCurrentResponse.fromJson(Map json) - : algorithm = { - 'm.megolm_backup.v1.curve25519-aes-sha2': - BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 - }[json['algorithm']]!, + : algorithm = BackupAlgorithm.values.fromString(json['algorithm'])!, authData = json['auth_data'] as Map, count = json['count'] as int, etag = json['etag'] as String, version = json['version'] as String; Map toJson() => { - 'algorithm': { - BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: - 'm.megolm_backup.v1.curve25519-aes-sha2' - }[algorithm]!, + 'algorithm': algorithm.name, 'auth_data': authData, 'count': count, 'etag': etag, @@ -1789,19 +2013,13 @@ class GetRoomKeysVersionResponse { }); GetRoomKeysVersionResponse.fromJson(Map json) - : algorithm = { - 'm.megolm_backup.v1.curve25519-aes-sha2': - BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 - }[json['algorithm']]!, + : algorithm = BackupAlgorithm.values.fromString(json['algorithm'])!, authData = json['auth_data'] as Map, count = json['count'] as int, etag = json['etag'] as String, version = json['version'] as String; Map toJson() => { - 'algorithm': { - BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: - 'm.megolm_backup.v1.curve25519-aes-sha2' - }[algorithm]!, + 'algorithm': algorithm.name, 'auth_data': authData, 'count': count, 'etag': etag, @@ -1924,56 +2142,81 @@ class RoomMember { } @_NameSource('(generated, rule override generated)') -enum Membership { ban, invite, join, knock, leave } +@EnhancedEnum() +enum Membership { + @EnhancedEnumValue(name: 'ban') + ban, + @EnhancedEnumValue(name: 'invite') + invite, + @EnhancedEnumValue(name: 'join') + join, + @EnhancedEnumValue(name: 'knock') + knock, + @EnhancedEnumValue(name: 'leave') + leave +} @_NameSource('rule override generated') -enum Direction { b, f } +@EnhancedEnum() +enum Direction { + @EnhancedEnumValue(name: 'b') + b, + @EnhancedEnumValue(name: 'f') + f +} /// A list of messages with a new token to request more. @_NameSource('generated') class GetRoomEventsResponse { GetRoomEventsResponse({ - this.chunk, + required this.chunk, this.end, - this.start, + required this.start, this.state, }); GetRoomEventsResponse.fromJson(Map json) - : chunk = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() - : null)(json['chunk']), + : chunk = (json['chunk'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(), end = ((v) => v != null ? v as String : null)(json['end']), - start = ((v) => v != null ? v as String : null)(json['start']), + start = json['start'] as String, state = ((v) => v != null ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() : null)(json['state']); Map toJson() { - final chunk = this.chunk; final end = this.end; - final start = this.start; final state = this.state; return { - if (chunk != null) 'chunk': chunk.map((v) => v.toJson()).toList(), + 'chunk': chunk.map((v) => v.toJson()).toList(), if (end != null) 'end': end, - if (start != null) 'start': start, + 'start': start, if (state != null) 'state': state.map((v) => v.toJson()).toList(), }; } /// A list of room events. The order depends on the `dir` parameter. /// For `dir=b` events will be in reverse-chronological order, - /// for `dir=f` in chronological order, so that events start - /// at the `from` point. - List? chunk; + /// for `dir=f` in chronological order. (The exact definition of `chronological` + /// is dependent on the server implementation.) + /// + /// Note that an empty `chunk` does not *necessarily* imply that no more events + /// are available. Clients should continue to paginate until no `end` property + /// is returned. + List chunk; - /// The token the pagination ends at. If `dir=b` this token should - /// be used again to request even earlier events. + /// A token corresponding to the end of `chunk`. This token can be passed + /// back to this endpoint to request further events. + /// + /// If no further events are available (either because we have + /// reached the start of the timeline, or because the user does + /// not have permission to see any more events), this property + /// is omitted from the response. String? end; - /// The token the pagination starts from. If `dir=b` this will be - /// the token supplied in `from`. - String? start; + /// A token corresponding to the start of `chunk`. This will be the same as + /// the value given in `from`. + String start; /// A list of state events relevant to showing the `chunk`. For example, if /// `lazy_load_members` is enabled in the filter then this may contain @@ -1987,7 +2230,11 @@ class GetRoomEventsResponse { } @_NameSource('generated') -enum ReceiptType { mRead } +@EnhancedEnum() +enum ReceiptType { + @EnhancedEnumValue(name: 'm.read') + mRead +} @_NameSource('spec') class IncludeEventContext { @@ -2250,7 +2497,13 @@ class SearchFilter implements EventFilter, RoomEventFilter { } @_NameSource('rule override generated') -enum GroupKey { roomId, sender } +@EnhancedEnum() +enum GroupKey { + @EnhancedEnumValue(name: 'room_id') + roomId, + @EnhancedEnumValue(name: 'sender') + sender +} /// Configuration for group. @_NameSource('spec') @@ -2260,14 +2513,12 @@ class Group { }); Group.fromJson(Map json) - : key = ((v) => v != null - ? {'room_id': GroupKey.roomId, 'sender': GroupKey.sender}[v]! - : null)(json['key']); + : key = ((v) => + v != null ? GroupKey.values.fromString(v)! : null)(json['key']); Map toJson() { final key = this.key; return { - if (key != null) - 'key': {GroupKey.roomId: 'room_id', GroupKey.sender: 'sender'}[key]!, + if (key != null) 'key': key.name, }; } @@ -2297,10 +2548,24 @@ class Groupings { } @_NameSource('rule override generated') -enum KeyKind { contentBody, contentName, contentTopic } +@EnhancedEnum() +enum KeyKind { + @EnhancedEnumValue(name: 'content.body') + contentBody, + @EnhancedEnumValue(name: 'content.name') + contentName, + @EnhancedEnumValue(name: 'content.topic') + contentTopic +} @_NameSource('rule override generated') -enum SearchOrder { rank, recent } +@EnhancedEnum() +enum SearchOrder { + @EnhancedEnumValue(name: 'rank') + rank, + @EnhancedEnumValue(name: 'recent') + recent +} @_NameSource('spec') class RoomEventsCriteria { @@ -2325,17 +2590,10 @@ class RoomEventsCriteria { includeState = ((v) => v != null ? v as bool : null)(json['include_state']), keys = ((v) => v != null - ? (v as List) - .map((v) => { - 'content.body': KeyKind.contentBody, - 'content.name': KeyKind.contentName, - 'content.topic': KeyKind.contentTopic - }[v]!) - .toList() + ? (v as List).map((v) => KeyKind.values.fromString(v)!).toList() : null)(json['keys']), - orderBy = ((v) => v != null - ? {'recent': SearchOrder.recent, 'rank': SearchOrder.rank}[v]! - : null)(json['order_by']), + orderBy = ((v) => v != null ? SearchOrder.values.fromString(v)! : null)( + json['order_by']), searchTerm = json['search_term'] as String; Map toJson() { final eventContext = this.eventContext; @@ -2349,19 +2607,8 @@ class RoomEventsCriteria { if (filter != null) 'filter': filter.toJson(), if (groupings != null) 'groupings': groupings.toJson(), if (includeState != null) 'include_state': includeState, - if (keys != null) - 'keys': keys - .map((v) => { - KeyKind.contentBody: 'content.body', - KeyKind.contentName: 'content.name', - KeyKind.contentTopic: 'content.topic' - }[v]!) - .toList(), - if (orderBy != null) - 'order_by': { - SearchOrder.recent: 'recent', - SearchOrder.rank: 'rank' - }[orderBy]!, + if (keys != null) 'keys': keys.map((v) => v.name).toList(), + if (orderBy != null) 'order_by': orderBy.name, 'search_term': searchTerm, }; } @@ -2872,7 +3119,13 @@ class ThirdPartyUser { } @_NameSource('generated') -enum EventFormat { client, federation } +@EnhancedEnum() +enum EventFormat { + @EnhancedEnumValue(name: 'client') + client, + @EnhancedEnumValue(name: 'federation') + federation +} @_NameSource('rule override generated') class StateFilter implements EventFilter, RoomEventFilter { @@ -3065,10 +3318,7 @@ class Filter { ? (v as List).map((v) => v as String).toList() : null)(json['event_fields']), eventFormat = ((v) => v != null - ? { - 'client': EventFormat.client, - 'federation': EventFormat.federation - }[v]! + ? EventFormat.values.fromString(v)! : null)(json['event_format']), presence = ((v) => v != null ? EventFilter.fromJson(v) : null)(json['presence']), @@ -3083,11 +3333,7 @@ class Filter { if (accountData != null) 'account_data': accountData.toJson(), if (eventFields != null) 'event_fields': eventFields.map((v) => v).toList(), - if (eventFormat != null) - 'event_format': { - EventFormat.client: 'client', - EventFormat.federation: 'federation' - }[eventFormat]!, + if (eventFormat != null) 'event_format': eventFormat.name, if (presence != null) 'presence': presence.toJson(), if (room != null) 'room': room.toJson(), }; @@ -3346,4 +3592,10 @@ class GetUrlPreviewResponse { } @_NameSource('generated') -enum Method { crop, scale } +@EnhancedEnum() +enum Method { + @EnhancedEnumValue(name: 'crop') + crop, + @EnhancedEnumValue(name: 'scale') + scale +} diff --git a/lib/src/generated/model.g.dart b/lib/src/generated/model.g.dart new file mode 100644 index 00000000..b5f907e3 --- /dev/null +++ b/lib/src/generated/model.g.dart @@ -0,0 +1,802 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'model.dart'; + +// ************************************************************************** +// EnhancedEnumGenerator +// ************************************************************************** + +extension ThirdPartyIdentifierMediumFromStringExtension + on Iterable { + ThirdPartyIdentifierMedium? fromString(String val) { + final override = { + 'email': ThirdPartyIdentifierMedium.email, + 'msisdn': ThirdPartyIdentifierMedium.msisdn, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension ThirdPartyIdentifierMediumEnhancedEnum on ThirdPartyIdentifierMedium { + @override +// ignore: override_on_non_overriding_member + String get name => { + ThirdPartyIdentifierMedium.email: 'email', + ThirdPartyIdentifierMedium.msisdn: 'msisdn', + }[this]!; + bool get isEmail => this == ThirdPartyIdentifierMedium.email; + bool get isMsisdn => this == ThirdPartyIdentifierMedium.msisdn; + T when({ + required T Function() email, + required T Function() msisdn, + }) => + { + ThirdPartyIdentifierMedium.email: email, + ThirdPartyIdentifierMedium.msisdn: msisdn, + }[this]!(); + T maybeWhen({ + T? Function()? email, + T? Function()? msisdn, + required T Function() orElse, + }) => + { + ThirdPartyIdentifierMedium.email: email, + ThirdPartyIdentifierMedium.msisdn: msisdn, + }[this] + ?.call() ?? + orElse(); +} + +extension IdServerUnbindResultFromStringExtension + on Iterable { + IdServerUnbindResult? fromString(String val) { + final override = { + 'no-support': IdServerUnbindResult.noSupport, + 'success': IdServerUnbindResult.success, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension IdServerUnbindResultEnhancedEnum on IdServerUnbindResult { + @override +// ignore: override_on_non_overriding_member + String get name => { + IdServerUnbindResult.noSupport: 'no-support', + IdServerUnbindResult.success: 'success', + }[this]!; + bool get isNoSupport => this == IdServerUnbindResult.noSupport; + bool get isSuccess => this == IdServerUnbindResult.success; + T when({ + required T Function() noSupport, + required T Function() success, + }) => + { + IdServerUnbindResult.noSupport: noSupport, + IdServerUnbindResult.success: success, + }[this]!(); + T maybeWhen({ + T? Function()? noSupport, + T? Function()? success, + required T Function() orElse, + }) => + { + IdServerUnbindResult.noSupport: noSupport, + IdServerUnbindResult.success: success, + }[this] + ?.call() ?? + orElse(); +} + +extension RoomVersionAvailableFromStringExtension + on Iterable { + RoomVersionAvailable? fromString(String val) { + final override = { + 'stable': RoomVersionAvailable.stable, + 'unstable': RoomVersionAvailable.unstable, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension RoomVersionAvailableEnhancedEnum on RoomVersionAvailable { + @override +// ignore: override_on_non_overriding_member + String get name => { + RoomVersionAvailable.stable: 'stable', + RoomVersionAvailable.unstable: 'unstable', + }[this]!; + bool get isStable => this == RoomVersionAvailable.stable; + bool get isUnstable => this == RoomVersionAvailable.unstable; + T when({ + required T Function() stable, + required T Function() unstable, + }) => + { + RoomVersionAvailable.stable: stable, + RoomVersionAvailable.unstable: unstable, + }[this]!(); + T maybeWhen({ + T? Function()? stable, + T? Function()? unstable, + required T Function() orElse, + }) => + { + RoomVersionAvailable.stable: stable, + RoomVersionAvailable.unstable: unstable, + }[this] + ?.call() ?? + orElse(); +} + +extension CreateRoomPresetFromStringExtension on Iterable { + CreateRoomPreset? fromString(String val) { + final override = { + 'private_chat': CreateRoomPreset.privateChat, + 'public_chat': CreateRoomPreset.publicChat, + 'trusted_private_chat': CreateRoomPreset.trustedPrivateChat, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension CreateRoomPresetEnhancedEnum on CreateRoomPreset { + @override +// ignore: override_on_non_overriding_member + String get name => { + CreateRoomPreset.privateChat: 'private_chat', + CreateRoomPreset.publicChat: 'public_chat', + CreateRoomPreset.trustedPrivateChat: 'trusted_private_chat', + }[this]!; + bool get isPrivateChat => this == CreateRoomPreset.privateChat; + bool get isPublicChat => this == CreateRoomPreset.publicChat; + bool get isTrustedPrivateChat => this == CreateRoomPreset.trustedPrivateChat; + T when({ + required T Function() privateChat, + required T Function() publicChat, + required T Function() trustedPrivateChat, + }) => + { + CreateRoomPreset.privateChat: privateChat, + CreateRoomPreset.publicChat: publicChat, + CreateRoomPreset.trustedPrivateChat: trustedPrivateChat, + }[this]!(); + T maybeWhen({ + T? Function()? privateChat, + T? Function()? publicChat, + T? Function()? trustedPrivateChat, + required T Function() orElse, + }) => + { + CreateRoomPreset.privateChat: privateChat, + CreateRoomPreset.publicChat: publicChat, + CreateRoomPreset.trustedPrivateChat: trustedPrivateChat, + }[this] + ?.call() ?? + orElse(); +} + +extension VisibilityFromStringExtension on Iterable { + Visibility? fromString(String val) { + final override = { + 'private': Visibility.private, + 'public': Visibility.public, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension VisibilityEnhancedEnum on Visibility { + @override +// ignore: override_on_non_overriding_member + String get name => { + Visibility.private: 'private', + Visibility.public: 'public', + }[this]!; + bool get isPrivate => this == Visibility.private; + bool get isPublic => this == Visibility.public; + T when({ + required T Function() private, + required T Function() public, + }) => + { + Visibility.private: private, + Visibility.public: public, + }[this]!(); + T maybeWhen({ + T? Function()? private, + T? Function()? public, + required T Function() orElse, + }) => + { + Visibility.private: private, + Visibility.public: public, + }[this] + ?.call() ?? + orElse(); +} + +extension LoginTypeFromStringExtension on Iterable { + LoginType? fromString(String val) { + final override = { + 'm.login.password': LoginType.mLoginPassword, + 'm.login.token': LoginType.mLoginToken, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension LoginTypeEnhancedEnum on LoginType { + @override +// ignore: override_on_non_overriding_member + String get name => { + LoginType.mLoginPassword: 'm.login.password', + LoginType.mLoginToken: 'm.login.token', + }[this]!; + bool get isMLoginPassword => this == LoginType.mLoginPassword; + bool get isMLoginToken => this == LoginType.mLoginToken; + T when({ + required T Function() mLoginPassword, + required T Function() mLoginToken, + }) => + { + LoginType.mLoginPassword: mLoginPassword, + LoginType.mLoginToken: mLoginToken, + }[this]!(); + T maybeWhen({ + T? Function()? mLoginPassword, + T? Function()? mLoginToken, + required T Function() orElse, + }) => + { + LoginType.mLoginPassword: mLoginPassword, + LoginType.mLoginToken: mLoginToken, + }[this] + ?.call() ?? + orElse(); +} + +extension PresenceTypeFromStringExtension on Iterable { + PresenceType? fromString(String val) { + final override = { + 'offline': PresenceType.offline, + 'online': PresenceType.online, + 'unavailable': PresenceType.unavailable, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension PresenceTypeEnhancedEnum on PresenceType { + @override +// ignore: override_on_non_overriding_member + String get name => { + PresenceType.offline: 'offline', + PresenceType.online: 'online', + PresenceType.unavailable: 'unavailable', + }[this]!; + bool get isOffline => this == PresenceType.offline; + bool get isOnline => this == PresenceType.online; + bool get isUnavailable => this == PresenceType.unavailable; + T when({ + required T Function() offline, + required T Function() online, + required T Function() unavailable, + }) => + { + PresenceType.offline: offline, + PresenceType.online: online, + PresenceType.unavailable: unavailable, + }[this]!(); + T maybeWhen({ + T? Function()? offline, + T? Function()? online, + T? Function()? unavailable, + required T Function() orElse, + }) => + { + PresenceType.offline: offline, + PresenceType.online: online, + PresenceType.unavailable: unavailable, + }[this] + ?.call() ?? + orElse(); +} + +extension PushRuleKindFromStringExtension on Iterable { + PushRuleKind? fromString(String val) { + final override = { + 'content': PushRuleKind.content, + 'override': PushRuleKind.override, + 'room': PushRuleKind.room, + 'sender': PushRuleKind.sender, + 'underride': PushRuleKind.underride, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension PushRuleKindEnhancedEnum on PushRuleKind { + @override +// ignore: override_on_non_overriding_member + String get name => { + PushRuleKind.content: 'content', + PushRuleKind.override: 'override', + PushRuleKind.room: 'room', + PushRuleKind.sender: 'sender', + PushRuleKind.underride: 'underride', + }[this]!; + bool get isContent => this == PushRuleKind.content; + bool get isOverride => this == PushRuleKind.override; + bool get isRoom => this == PushRuleKind.room; + bool get isSender => this == PushRuleKind.sender; + bool get isUnderride => this == PushRuleKind.underride; + T when({ + required T Function() content, + required T Function() override, + required T Function() room, + required T Function() sender, + required T Function() underride, + }) => + { + PushRuleKind.content: content, + PushRuleKind.override: override, + PushRuleKind.room: room, + PushRuleKind.sender: sender, + PushRuleKind.underride: underride, + }[this]!(); + T maybeWhen({ + T? Function()? content, + T? Function()? override, + T? Function()? room, + T? Function()? sender, + T? Function()? underride, + required T Function() orElse, + }) => + { + PushRuleKind.content: content, + PushRuleKind.override: override, + PushRuleKind.room: room, + PushRuleKind.sender: sender, + PushRuleKind.underride: underride, + }[this] + ?.call() ?? + orElse(); +} + +extension AccountKindFromStringExtension on Iterable { + AccountKind? fromString(String val) { + final override = { + 'guest': AccountKind.guest, + 'user': AccountKind.user, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension AccountKindEnhancedEnum on AccountKind { + @override +// ignore: override_on_non_overriding_member + String get name => { + AccountKind.guest: 'guest', + AccountKind.user: 'user', + }[this]!; + bool get isGuest => this == AccountKind.guest; + bool get isUser => this == AccountKind.user; + T when({ + required T Function() guest, + required T Function() user, + }) => + { + AccountKind.guest: guest, + AccountKind.user: user, + }[this]!(); + T maybeWhen({ + T? Function()? guest, + T? Function()? user, + required T Function() orElse, + }) => + { + AccountKind.guest: guest, + AccountKind.user: user, + }[this] + ?.call() ?? + orElse(); +} + +extension BackupAlgorithmFromStringExtension on Iterable { + BackupAlgorithm? fromString(String val) { + final override = { + 'm.megolm_backup.v1.curve25519-aes-sha2': + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension BackupAlgorithmEnhancedEnum on BackupAlgorithm { + @override +// ignore: override_on_non_overriding_member + String get name => { + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: + 'm.megolm_backup.v1.curve25519-aes-sha2', + }[this]!; + bool get isMMegolmBackupV1Curve25519AesSha2 => + this == BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; + T when({ + required T Function() mMegolmBackupV1Curve25519AesSha2, + }) => + { + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: + mMegolmBackupV1Curve25519AesSha2, + }[this]!(); + T maybeWhen({ + T? Function()? mMegolmBackupV1Curve25519AesSha2, + required T Function() orElse, + }) => + { + BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2: + mMegolmBackupV1Curve25519AesSha2, + }[this] + ?.call() ?? + orElse(); +} + +extension MembershipFromStringExtension on Iterable { + Membership? fromString(String val) { + final override = { + 'ban': Membership.ban, + 'invite': Membership.invite, + 'join': Membership.join, + 'knock': Membership.knock, + 'leave': Membership.leave, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension MembershipEnhancedEnum on Membership { + @override +// ignore: override_on_non_overriding_member + String get name => { + Membership.ban: 'ban', + Membership.invite: 'invite', + Membership.join: 'join', + Membership.knock: 'knock', + Membership.leave: 'leave', + }[this]!; + bool get isBan => this == Membership.ban; + bool get isInvite => this == Membership.invite; + bool get isJoin => this == Membership.join; + bool get isKnock => this == Membership.knock; + bool get isLeave => this == Membership.leave; + T when({ + required T Function() ban, + required T Function() invite, + required T Function() join, + required T Function() knock, + required T Function() leave, + }) => + { + Membership.ban: ban, + Membership.invite: invite, + Membership.join: join, + Membership.knock: knock, + Membership.leave: leave, + }[this]!(); + T maybeWhen({ + T? Function()? ban, + T? Function()? invite, + T? Function()? join, + T? Function()? knock, + T? Function()? leave, + required T Function() orElse, + }) => + { + Membership.ban: ban, + Membership.invite: invite, + Membership.join: join, + Membership.knock: knock, + Membership.leave: leave, + }[this] + ?.call() ?? + orElse(); +} + +extension DirectionFromStringExtension on Iterable { + Direction? fromString(String val) { + final override = { + 'b': Direction.b, + 'f': Direction.f, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension DirectionEnhancedEnum on Direction { + @override +// ignore: override_on_non_overriding_member + String get name => { + Direction.b: 'b', + Direction.f: 'f', + }[this]!; + bool get isB => this == Direction.b; + bool get isF => this == Direction.f; + T when({ + required T Function() b, + required T Function() f, + }) => + { + Direction.b: b, + Direction.f: f, + }[this]!(); + T maybeWhen({ + T? Function()? b, + T? Function()? f, + required T Function() orElse, + }) => + { + Direction.b: b, + Direction.f: f, + }[this] + ?.call() ?? + orElse(); +} + +extension ReceiptTypeFromStringExtension on Iterable { + ReceiptType? fromString(String val) { + final override = { + 'm.read': ReceiptType.mRead, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension ReceiptTypeEnhancedEnum on ReceiptType { + @override +// ignore: override_on_non_overriding_member + String get name => { + ReceiptType.mRead: 'm.read', + }[this]!; + bool get isMRead => this == ReceiptType.mRead; + T when({ + required T Function() mRead, + }) => + { + ReceiptType.mRead: mRead, + }[this]!(); + T maybeWhen({ + T? Function()? mRead, + required T Function() orElse, + }) => + { + ReceiptType.mRead: mRead, + }[this] + ?.call() ?? + orElse(); +} + +extension GroupKeyFromStringExtension on Iterable { + GroupKey? fromString(String val) { + final override = { + 'room_id': GroupKey.roomId, + 'sender': GroupKey.sender, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension GroupKeyEnhancedEnum on GroupKey { + @override +// ignore: override_on_non_overriding_member + String get name => { + GroupKey.roomId: 'room_id', + GroupKey.sender: 'sender', + }[this]!; + bool get isRoomId => this == GroupKey.roomId; + bool get isSender => this == GroupKey.sender; + T when({ + required T Function() roomId, + required T Function() sender, + }) => + { + GroupKey.roomId: roomId, + GroupKey.sender: sender, + }[this]!(); + T maybeWhen({ + T? Function()? roomId, + T? Function()? sender, + required T Function() orElse, + }) => + { + GroupKey.roomId: roomId, + GroupKey.sender: sender, + }[this] + ?.call() ?? + orElse(); +} + +extension KeyKindFromStringExtension on Iterable { + KeyKind? fromString(String val) { + final override = { + 'content.body': KeyKind.contentBody, + 'content.name': KeyKind.contentName, + 'content.topic': KeyKind.contentTopic, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension KeyKindEnhancedEnum on KeyKind { + @override +// ignore: override_on_non_overriding_member + String get name => { + KeyKind.contentBody: 'content.body', + KeyKind.contentName: 'content.name', + KeyKind.contentTopic: 'content.topic', + }[this]!; + bool get isContentBody => this == KeyKind.contentBody; + bool get isContentName => this == KeyKind.contentName; + bool get isContentTopic => this == KeyKind.contentTopic; + T when({ + required T Function() contentBody, + required T Function() contentName, + required T Function() contentTopic, + }) => + { + KeyKind.contentBody: contentBody, + KeyKind.contentName: contentName, + KeyKind.contentTopic: contentTopic, + }[this]!(); + T maybeWhen({ + T? Function()? contentBody, + T? Function()? contentName, + T? Function()? contentTopic, + required T Function() orElse, + }) => + { + KeyKind.contentBody: contentBody, + KeyKind.contentName: contentName, + KeyKind.contentTopic: contentTopic, + }[this] + ?.call() ?? + orElse(); +} + +extension SearchOrderFromStringExtension on Iterable { + SearchOrder? fromString(String val) { + final override = { + 'rank': SearchOrder.rank, + 'recent': SearchOrder.recent, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension SearchOrderEnhancedEnum on SearchOrder { + @override +// ignore: override_on_non_overriding_member + String get name => { + SearchOrder.rank: 'rank', + SearchOrder.recent: 'recent', + }[this]!; + bool get isRank => this == SearchOrder.rank; + bool get isRecent => this == SearchOrder.recent; + T when({ + required T Function() rank, + required T Function() recent, + }) => + { + SearchOrder.rank: rank, + SearchOrder.recent: recent, + }[this]!(); + T maybeWhen({ + T? Function()? rank, + T? Function()? recent, + required T Function() orElse, + }) => + { + SearchOrder.rank: rank, + SearchOrder.recent: recent, + }[this] + ?.call() ?? + orElse(); +} + +extension EventFormatFromStringExtension on Iterable { + EventFormat? fromString(String val) { + final override = { + 'client': EventFormat.client, + 'federation': EventFormat.federation, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension EventFormatEnhancedEnum on EventFormat { + @override +// ignore: override_on_non_overriding_member + String get name => { + EventFormat.client: 'client', + EventFormat.federation: 'federation', + }[this]!; + bool get isClient => this == EventFormat.client; + bool get isFederation => this == EventFormat.federation; + T when({ + required T Function() client, + required T Function() federation, + }) => + { + EventFormat.client: client, + EventFormat.federation: federation, + }[this]!(); + T maybeWhen({ + T? Function()? client, + T? Function()? federation, + required T Function() orElse, + }) => + { + EventFormat.client: client, + EventFormat.federation: federation, + }[this] + ?.call() ?? + orElse(); +} + +extension MethodFromStringExtension on Iterable { + Method? fromString(String val) { + final override = { + 'crop': Method.crop, + 'scale': Method.scale, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension MethodEnhancedEnum on Method { + @override +// ignore: override_on_non_overriding_member + String get name => { + Method.crop: 'crop', + Method.scale: 'scale', + }[this]!; + bool get isCrop => this == Method.crop; + bool get isScale => this == Method.scale; + T when({ + required T Function() crop, + required T Function() scale, + }) => + { + Method.crop: crop, + Method.scale: scale, + }[this]!(); + T maybeWhen({ + T? Function()? crop, + T? Function()? scale, + required T Function() orElse, + }) => + { + Method.crop: crop, + Method.scale: scale, + }[this] + ?.call() ?? + orElse(); +} diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 6eccfbac..b359cdd4 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -91,7 +91,7 @@ class MatrixApi extends Api { } dynamic json; (!(data is String)) ? json = jsonEncode(data) : json = data; - if (data is List || action.startsWith('/media/r0/upload')) json = data; + if (data is List || action.startsWith('/media/v3/upload')) json = data; final url = homeserver! .resolveUri(Uri(path: '_matrix$action', queryParameters: query)); @@ -154,7 +154,7 @@ class MatrixApi extends Api { Map? fallbackKeys}) async { final response = await request( RequestType.POST, - '/client/r0/keys/upload', + '/client/v3/keys/upload', data: { if (deviceKeys != null) 'device_keys': deviceKeys.toJson(), if (oneTimeKeys != null) 'one_time_keys': oneTimeKeys, @@ -181,7 +181,7 @@ class MatrixApi extends Api { } await request( RequestType.POST, - '/client/r0/pushers/set', + '/client/v3/pushers/set', data: data, ); return; @@ -195,7 +195,7 @@ class MatrixApi extends Api { data['kind'] = null; await request( RequestType.POST, - '/client/r0/pushers/set', + '/client/v3/pushers/set', data: data, ); return; @@ -205,7 +205,7 @@ class MatrixApi extends Api { /// calls. @override Future getTurnServer() async { - final json = await request(RequestType.GET, '/client/r0/voip/turnServer'); + final json = await request(RequestType.GET, '/client/v3/voip/turnServer'); // fix invalid responses from synapse // https://github.com/matrix-org/synapse/pull/10922 @@ -213,4 +213,22 @@ class MatrixApi extends Api { return TurnServerCredentials.fromJson(json); } + + @Deprecated('Use [deleteRoomKeyBySessionId] instead') + Future deleteRoomKeysBySessionId( + String roomId, String sessionId, String version) async { + return deleteRoomKeyBySessionId(roomId, sessionId, version); + } + + @Deprecated('Use [deleteRoomKeyBySessionId] instead') + Future putRoomKeysBySessionId(String roomId, + String sessionId, String version, KeyBackupData data) async { + return putRoomKeyBySessionId(roomId, sessionId, version, data); + } + + @Deprecated('Use [getRoomKeyBySessionId] instead') + Future getRoomKeysBySessionId( + String roomId, String sessionId, String version) async { + return getRoomKeyBySessionId(roomId, sessionId, version); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 58d86b0b..ac375342 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,9 +9,12 @@ environment: sdk: ">=2.12.0 <3.0.0" dependencies: + enhanced_enum: ^0.1.1 http: ^0.13.0 mime: ^1.0.0 dev_dependencies: + build_runner: ^2.1.8 + enhanced_enum_generator: ^0.1.1 pedantic: ^1.11.0 test: ^1.14.4 diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index af414dea..0090ddcf 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -146,7 +146,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final loginTypes = await matrixApi.getLoginFlows(); expect(loginTypes?.first.type, 'm.login.password'); - expect(FakeMatrixApi.api['GET']!['/client/r0/login']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/login']({}), {'flows': loginTypes?.map((x) => x.toJson()).toList()}); matrixApi.homeserver = null; }); @@ -156,7 +156,7 @@ void main() { LoginType.mLoginPassword, identifier: AuthenticationUserIdentifier(user: 'username'), ); - expect(FakeMatrixApi.api['POST']!['/client/r0/login']({}), + expect(FakeMatrixApi.api['POST']!['/client/v3/login']({}), loginResponse.toJson()); matrixApi.homeserver = null; }); @@ -176,7 +176,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final registerResponse = await matrixApi.register(kind: AccountKind.guest, username: 'test'); - expect(FakeMatrixApi.api['POST']!['/client/r0/register?kind=guest']({}), + expect(FakeMatrixApi.api['POST']!['/client/v3/register?kind=guest']({}), registerResponse.toJson()); matrixApi.homeserver = null; }); @@ -193,7 +193,7 @@ void main() { ); expect( FakeMatrixApi - .api['POST']!['/client/r0/register/email/requestToken']({}), + .api['POST']!['/client/v3/register/email/requestToken']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -211,7 +211,7 @@ void main() { ); expect( FakeMatrixApi - .api['POST']!['/client/r0/register/email/requestToken']({}), + .api['POST']!['/client/v3/register/email/requestToken']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -280,7 +280,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getAccount3PIDs(); - expect(FakeMatrixApi.api['GET']!['/client/r0/account/3pid']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/account/3pid']({}), {'threepids': response?.map((t) => t.toJson()).toList()}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -362,7 +362,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getCapabilities(); - expect(FakeMatrixApi.api['GET']!['/client/r0/capabilities']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/capabilities']({}), {'capabilities': response.toJson()}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -497,7 +497,7 @@ void main() { ); expect( FakeMatrixApi.api['GET']![ - '/client/r0/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15']( + '/client/v3/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15']( {}) as Map?, response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -575,7 +575,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ - '/client/r0/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']( + '/client/v3/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']( {}) as Map?, timelineHistoryResponse.toJson()); @@ -666,7 +666,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ - '/client/r0/directory/room/%23testalias%3Aexample.com']({}), + '/client/v3/directory/room/%23testalias%3Aexample.com']({}), roomAliasInformation.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -828,7 +828,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ - '/client/r0/publicRooms?limit=10&since=1234&server=example.com']({}), + '/client/v3/publicRooms?limit=10&since=1234&server=example.com']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -850,7 +850,7 @@ void main() { expect( FakeMatrixApi - .api['POST']!['/client/r0/publicRooms?server=example.com']({}), + .api['POST']!['/client/v3/publicRooms?server=example.com']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -864,7 +864,7 @@ void main() { limit: 10, ); - expect(FakeMatrixApi.api['POST']!['/client/r0/user_directory/search']({}), + expect(FakeMatrixApi.api['POST']!['/client/v3/user_directory/search']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -912,7 +912,7 @@ void main() { final response = await matrixApi.getUserProfile('@alice:example.com'); expect( FakeMatrixApi - .api['GET']!['/client/r0/profile/%40alice%3Aexample.com']({}), + .api['GET']!['/client/v3/profile/%40alice%3Aexample.com']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -922,7 +922,7 @@ void main() { matrixApi.accessToken = '1234'; final response = await matrixApi.getTurnServer(); - expect(FakeMatrixApi.api['GET']!['/client/r0/voip/turnServer']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/voip/turnServer']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -986,7 +986,7 @@ void main() { ); expect( FakeMatrixApi.api['GET']![ - '/client/r0/presence/${Uri.encodeComponent('@alice:example.com')}/status']({}), + '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status']({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1016,7 +1016,7 @@ void main() { ); expect( FakeMatrixApi.api['GET']![ - '/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']({}), + '/media/v3/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']({}), openGraphData.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1047,7 +1047,7 @@ void main() { matrixApi.accessToken = '1234'; final devices = await matrixApi.getDevices(); - expect(FakeMatrixApi.api['GET']!['/client/r0/devices']({})['devices'], + expect(FakeMatrixApi.api['GET']!['/client/v3/devices']({})['devices'], devices?.map((i) => i.toJson()).toList()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1118,7 +1118,7 @@ void main() { 'Alices mobile phone'); expect( FakeMatrixApi - .api['POST']!['/client/r0/keys/query']({'device_keys': {}}), + .api['POST']!['/client/v3/keys/query']({'device_keys': {}}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1134,7 +1134,7 @@ void main() { timeout: 10, ); expect( - FakeMatrixApi.api['POST']!['/client/r0/keys/claim']({ + FakeMatrixApi.api['POST']!['/client/v3/keys/claim']({ 'one_time_keys': { '@alice:example.com': {'JLAFKJWSCS': 'signed_curve25519'} } @@ -1193,7 +1193,7 @@ void main() { final response = await matrixApi.getPushers(); expect( - FakeMatrixApi.api['GET']!['/client/r0/pushers']({}), + FakeMatrixApi.api['GET']!['/client/v3/pushers']({}), {'pushers': response?.map((i) => i.toJson()).toList()}, ); @@ -1231,7 +1231,7 @@ void main() { ); expect( FakeMatrixApi.api['GET']![ - '/client/r0/notifications?from=1234&limit=10&only=1234']({}), + '/client/v3/notifications?from=1234&limit=10&only=1234']({}), response.toJson(), ); @@ -1243,7 +1243,7 @@ void main() { final response = await matrixApi.getPushRules(); expect( - FakeMatrixApi.api['GET']!['/client/r0/pushrules']({}), + FakeMatrixApi.api['GET']!['/client/v3/pushrules']({}), {'global': response.toJson()}, ); @@ -1257,7 +1257,7 @@ void main() { await matrixApi.getPushRule('global', PushRuleKind.content, 'nocake'); expect( FakeMatrixApi - .api['GET']!['/client/r0/pushrules/global/content/nocake']({}), + .api['GET']!['/client/v3/pushrules/global/content/nocake']({}), response.toJson(), ); @@ -1357,7 +1357,7 @@ void main() { from: '1234', roomId: '!1234', timeout: 10); expect( FakeMatrixApi.api['GET']![ - '/client/r0/events?from=1234&timeout=10&room_id=%211234']({}), + '/client/v3/events?from=1234&timeout=10&room_id=%211234']({}), response.toJson(), ); @@ -1371,7 +1371,7 @@ void main() { '@alice:example.com', '!localpart:example.com'); expect( FakeMatrixApi.api['GET']![ - '/client/r0/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']({}), + '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']({}), {'tags': response?.map((k, v) => MapEntry(k, v.toJson()))}, ); @@ -1457,7 +1457,7 @@ void main() { final response = await matrixApi.getWhoIs('@alice:example.com'); expect( FakeMatrixApi - .api['GET']!['/client/r0/admin/whois/%40alice%3Aexample.com']({}), + .api['GET']!['/client/v3/admin/whois/%40alice%3Aexample.com']({}), response.toJson(), ); @@ -1471,7 +1471,7 @@ void main() { limit: 10, filter: '{}'); expect( FakeMatrixApi.api['GET']![ - '/client/r0/rooms/1234/context/1234?limit=10&filter=%7B%7D']({}), + '/client/v3/rooms/1234/context/1234?limit=10&filter=%7B%7D']({}), response.toJson(), ); @@ -1496,7 +1496,7 @@ void main() { final response = await matrixApi.getProtocols(); expect( - FakeMatrixApi.api['GET']!['/client/r0/thirdparty/protocols']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocols']({}), response.map((k, v) => MapEntry(k, v.toJson())), ); @@ -1508,7 +1508,7 @@ void main() { final response = await matrixApi.getProtocolMetadata('irc'); expect( - FakeMatrixApi.api['GET']!['/client/r0/thirdparty/protocol/irc']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocol/irc']({}), response.toJson(), ); @@ -1520,7 +1520,7 @@ void main() { final response = await matrixApi.queryLocationByProtocol('irc'); expect( - FakeMatrixApi.api['GET']!['/client/r0/thirdparty/location/irc']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/location/irc']({}), response.map((i) => i.toJson()).toList(), ); @@ -1532,7 +1532,7 @@ void main() { final response = await matrixApi.queryUserByProtocol('irc'); expect( - FakeMatrixApi.api['GET']!['/client/r0/thirdparty/user/irc']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user/irc']({}), response.map((i) => i.toJson()).toList(), ); @@ -1545,7 +1545,7 @@ void main() { final response = await matrixApi.queryLocationByAlias('1234'); expect( FakeMatrixApi - .api['GET']!['/client/r0/thirdparty/location?alias=1234']({}), + .api['GET']!['/client/v3/thirdparty/location?alias=1234']({}), response.map((i) => i.toJson()).toList(), ); @@ -1557,7 +1557,7 @@ void main() { final response = await matrixApi.queryUserByID('1234'); expect( - FakeMatrixApi.api['GET']!['/client/r0/thirdparty/user?userid=1234']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user?userid=1234']({}), response.map((i) => i.toJson()).toList(), ); @@ -1570,7 +1570,7 @@ void main() { final response = await matrixApi.requestOpenIdToken('1234', {}); expect( FakeMatrixApi - .api['POST']!['/client/r0/user/1234/openid/request_token']({}), + .api['POST']!['/client/v3/user/1234/openid/request_token']({}), response.toJson(), ); @@ -1595,8 +1595,8 @@ void main() { }; final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); expect( - FakeMatrixApi.api['POST']!['/client/unstable/room_keys/version']( - {})['version'], + FakeMatrixApi + .api['POST']!['/client/v3/room_keys/version']({})['version'], ret); }); test('getRoomKeysVersionCurrent', () async { @@ -1604,8 +1604,7 @@ void main() { matrixApi.accessToken = '1234'; final ret = await matrixApi.getRoomKeysVersionCurrent(); - expect( - FakeMatrixApi.api['GET']!['/client/unstable/room_keys/version']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/room_keys/version']({}), ret.toJson()); }); test('putRoomKeysVersion', () async { @@ -1625,7 +1624,7 @@ void main() { await matrixApi.deleteRoomKeys('5'); }); - test('putRoomKeysBySessionId', () async { + test('putRoomKeyBySessionId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; @@ -1642,37 +1641,36 @@ void main() { 'mac': 'QzKV/fgAs4U', }, }); - final ret = await matrixApi.putRoomKeysBySessionId( + final ret = await matrixApi.putRoomKeyBySessionId( roomId, sessionId, '5', session); expect( FakeMatrixApi.api['PUT']![ - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); - test('getRoomKeysBySessionId', () async { + test('getRoomKeyBySessionId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final ret = - await matrixApi.getRoomKeysBySessionId(roomId, sessionId, '5'); + final ret = await matrixApi.getRoomKeyBySessionId(roomId, sessionId, '5'); expect( FakeMatrixApi.api['GET']![ - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); - test('deleteRoomKeysBySessionId', () async { + test('deleteRoomKeyBySessionId', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final roomId = '!726s6s6q:example.com'; final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; final ret = - await matrixApi.deleteRoomKeysBySessionId(roomId, sessionId, '5'); + await matrixApi.deleteRoomKeyBySessionId(roomId, sessionId, '5'); expect( FakeMatrixApi.api['DELETE']![ - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), ret.toJson()); }); test('putRoomKeysByRoomId', () async { @@ -1699,7 +1697,7 @@ void main() { final ret = await matrixApi.putRoomKeysByRoomId(roomId, '5', session); expect( FakeMatrixApi.api['PUT']![ - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); test('getRoomKeysByRoomId', () async { @@ -1710,7 +1708,7 @@ void main() { final ret = await matrixApi.getRoomKeysByRoomId(roomId, '5'); expect( FakeMatrixApi.api['GET']![ - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); test('deleteRoomKeysByRoomId', () async { @@ -1721,7 +1719,7 @@ void main() { final ret = await matrixApi.deleteRoomKeysByRoomId(roomId, '5'); expect( FakeMatrixApi.api['DELETE']![ - '/client/unstable/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), ret.toJson()); }); test('putRoomKeys', () async { @@ -1751,8 +1749,7 @@ void main() { }); final ret = await matrixApi.putRoomKeys('5', session); expect( - FakeMatrixApi - .api['PUT']!['/client/unstable/room_keys/keys?version=5']({}), + FakeMatrixApi.api['PUT']!['/client/v3/room_keys/keys?version=5']({}), ret.toJson()); }); test('getRoomKeys', () async { @@ -1761,8 +1758,7 @@ void main() { final ret = await matrixApi.getRoomKeys('5'); expect( - FakeMatrixApi - .api['GET']!['/client/unstable/room_keys/keys?version=5']({}), + FakeMatrixApi.api['GET']!['/client/v3/room_keys/keys?version=5']({}), ret.toJson()); }); test('deleteRoomKeys', () async { @@ -1772,7 +1768,7 @@ void main() { final ret = await matrixApi.deleteRoomKeys('5'); expect( FakeMatrixApi - .api['DELETE']!['/client/unstable/room_keys/keys?version=5']({}), + .api['DELETE']!['/client/v3/room_keys/keys?version=5']({}), ret.toJson()); }); test('AuthenticationData', () { From 8866131652e6a8636d9b5cafeab52fc5b00dd376 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 5 Apr 2022 13:38:40 +0200 Subject: [PATCH 114/174] docs: Update spec link in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3fabe921..c2710d87 100644 --- a/README.md +++ b/README.md @@ -22,5 +22,5 @@ void main() async { ## Generated code -The files in `lib/src/generated` are generated by [dart_openapi_codegen](https://gitlab.com/famedly/company/frontend/dart_openapi_codegen) -from [matrix-doc](https://github.com/matrix-org/matrix-doc/). See the README.md in dart_openapi_codegen for more information. +The files in `lib/src/generated` are generated by [dart_openapi_codegen](https://gitlab.com/famedly/company/frontend/dart_openapi_codegen/) +from [matrix-spec](https://github.com/matrix-org/matrix-spec/). See the README.md in dart_openapi_codegen for more information. From a9d644cf9352b99448d24d2439ca94dea2831181 Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Mon, 9 May 2022 08:25:25 +0000 Subject: [PATCH 115/174] chore: Bump version --- CHANGELOG.md | 8 ++++++++ pubspec.yaml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbcde4db..ec498c82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.2.0 +This introduces a new versioning system where the first two numbers refer to +the matrix spec version (currently v1.2) and the last to the iteration of +this spec version. + +- feat: Migrate to Matrix v1.2 spec +- feat: Add GroupCallPrefix/GroupCallMemberPrefix to EventTypes. + ## 0.5.3 - chore: Add missing matrix error types as per spec - feat: add additionalProperties in PusherData diff --git a/pubspec.yaml b/pubspec.yaml index ac375342..1cdb8463 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 0.5.3 +version: 1.0.0 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 13b4598c83e7cbb65480dbe74f431c207407ebe3 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 16 May 2022 08:14:48 +0200 Subject: [PATCH 116/174] feat: Authenticate media downloads This is not strictly required by the spec, but it improves security to require auth for media downloads on your homeserver. I enabled that on my servers now and plan to MSC that soon. This is required for people on my servers to see images and other content now. --- lib/src/generated/api.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 66df959e..72d386f9 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -4256,6 +4256,7 @@ class Api { if (allowRemote != null) 'allow_remote': allowRemote.toString(), }); final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); @@ -4289,6 +4290,7 @@ class Api { if (allowRemote != null) 'allow_remote': allowRemote.toString(), }); final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); @@ -4360,6 +4362,7 @@ class Api { if (allowRemote != null) 'allow_remote': allowRemote.toString(), }); final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); From fc4f004312aa8f2cfe010e660bce82d2f3dd8aac Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Fri, 3 Jun 2022 11:05:30 +0000 Subject: [PATCH 117/174] fix: Add missing versions to fake matrix api This makes it easier to use the FakeMatrixApi in other packages for unit tests. --- lib/fake_matrix_api.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 37e02927..b00b917b 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1278,7 +1278,9 @@ class FakeMatrixApi extends MockClient { 'r0.2.0', 'r0.3.0', 'r0.4.0', - 'r0.5.0' + 'r0.5.0', + 'v1.1', + 'v1.2', ], 'unstable_features': {'m.lazy_load_members': true}, }, From 3dd7ef3444dc3e553ff198b02bbafb64cd58233d Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Tue, 7 Jun 2022 16:26:09 +0200 Subject: [PATCH 118/174] fix: wrong types in spaces hierarchy API BREAKING CHANGE (because from is now optional, so it can't be specified conditionally) See also: - https://github.com/matrix-org/matrix-spec/pull/1110 - https://github.com/matrix-org/matrix-spec/pull/1097 --- lib/src/generated/api.dart | 16 ++++++++-------- lib/src/generated/model.dart | 26 +++++++++++++++----------- test/matrix_api_test.dart | 2 +- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 72d386f9..059101ab 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -98,10 +98,7 @@ class Api { /// [from] A pagination token from a previous result. If specified, `max_depth` and `suggested_only` cannot /// be changed from the first request. Future getSpaceHierarchy(String roomId, - {bool? suggestedOnly, - double? limit, - double? maxDepth, - String? from}) async { + {bool? suggestedOnly, int? limit, int? maxDepth, String? from}) async { final requestUri = Uri( path: '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/hierarchy', @@ -3234,6 +3231,10 @@ class Api { /// by a previous request to this endpoint, though servers are not /// required to support this. Clients should not rely on the behaviour. /// + /// If it is not provided, the homeserver shall return a list of messages + /// from the first or last (per the value of the `dir` parameter) visible + /// event in the room history for the requesting user. + /// /// [to] The token to stop returning events at. This token can be obtained from /// a `prev_batch` or `next_batch` token returned by the `/sync` endpoint, /// or from an `end` token returned by a previous request to this endpoint. @@ -3246,13 +3247,12 @@ class Api { /// [limit] The maximum number of events to return. Default: 10. /// /// [filter] A JSON RoomEventFilter to filter returned events with. - Future getRoomEvents( - String roomId, String from, Direction dir, - {String? to, int? limit, String? filter}) async { + Future getRoomEvents(String roomId, Direction dir, + {String? from, String? to, int? limit, String? filter}) async { final requestUri = Uri( path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/messages', queryParameters: { - 'from': from, + if (from != null) 'from': from, if (to != null) 'to': to, 'dir': dir.name, if (limit != null) 'limit': limit.toString(), diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index db8cb054..1ccbebd9 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -164,18 +164,21 @@ class PublicRoomsChunk { class SpaceRoomsChunkBase { SpaceRoomsChunkBase({ required this.childrenState, - required this.roomType, + this.roomType, }); SpaceRoomsChunkBase.fromJson(Map json) : childrenState = (json['children_state'] as List) .map((v) => MatrixEvent.fromJson(v)) .toList(), - roomType = json['room_type'] as String; - Map toJson() => { - 'children_state': childrenState.map((v) => v.toJson()).toList(), - 'room_type': roomType, - }; + roomType = ((v) => v != null ? v as String : null)(json['room_type']); + Map toJson() { + final roomType = this.roomType; + return { + 'children_state': childrenState.map((v) => v.toJson()).toList(), + if (roomType != null) 'room_type': roomType, + }; + } /// The [`m.space.child`](#mspacechild) events of the space-room, represented /// as [Stripped State Events](#stripped-state) with an added `origin_server_ts` key. @@ -184,7 +187,7 @@ class SpaceRoomsChunkBase { List childrenState; /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. - String roomType; + String? roomType; } @_NameSource('rule override generated') @@ -200,7 +203,7 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { this.topic, required this.worldReadable, required this.childrenState, - required this.roomType, + this.roomType, }); SpaceRoomsChunk.fromJson(Map json) @@ -218,13 +221,14 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { childrenState = (json['children_state'] as List) .map((v) => MatrixEvent.fromJson(v)) .toList(), - roomType = json['room_type'] as String; + roomType = ((v) => v != null ? v as String : null)(json['room_type']); Map toJson() { final avatarUrl = this.avatarUrl; final canonicalAlias = this.canonicalAlias; final joinRule = this.joinRule; final name = this.name; final topic = this.topic; + final roomType = this.roomType; return { if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), if (canonicalAlias != null) 'canonical_alias': canonicalAlias, @@ -236,7 +240,7 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { if (topic != null) 'topic': topic, 'world_readable': worldReadable, 'children_state': childrenState.map((v) => v.toJson()).toList(), - 'room_type': roomType, + if (roomType != null) 'room_type': roomType, }; } @@ -277,7 +281,7 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { List childrenState; /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. - String roomType; + String? roomType; } @_NameSource('generated') diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 0090ddcf..15a4999a 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -566,8 +566,8 @@ void main() { final timelineHistoryResponse = await matrixApi.getRoomEvents( '!localpart:server.abc', - '1234', Direction.b, + from: '1234', limit: 10, filter: '{"lazy_load_members":true}', to: '1234', From cc509671f66ce655cd6bfaaadee6706c0877e6c5 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 8 Jun 2022 12:25:41 +0200 Subject: [PATCH 119/174] chore: bump version --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++---- pubspec.yaml | 2 +- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec498c82..a9248356 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,76 +1,101 @@ -## 1.2.0 -This introduces a new versioning system where the first two numbers refer to -the matrix spec version (currently v1.2) and the last to the iteration of -this spec version. +## 1.1.0 + +- fix: wrong types in spaces hierarchy API +- fix: Add missing versions to fake matrix api +- feat: Authenticate media downloads + +## 1.0.0 + +This release should be compatible with version 1.2 of the Matrix specification. - feat: Migrate to Matrix v1.2 spec - feat: Add GroupCallPrefix/GroupCallMemberPrefix to EventTypes. ## 0.5.3 + - chore: Add missing matrix error types as per spec - feat: add additionalProperties in PusherData - feat: deletePusher ## 0.5.2 + - feat: Colored logs on native and web - chore: Make some tryGet errors verbose and display line ## 0.5.1 + - feat: Add constructors to SyncUpdate classes ## 0.5.0 + - fix: threepidCreds should be threepid_creds and an object ## 0.4.4 + - chore: workaround for invalid getTurnServer responses from synapse ## 0.4.3 + - fix: Make type in AuthenticationData nullable - refactor: remove uploadKeySignatures (use uploadCrossSigningSignatures) ## 0.4.2 + - feat: Add more call event for improve voip. ## 0.4.1 + - fix: change tryGet default loglevel to Optional ## 0.4.0 + - refactor: Migrate to null safety - refactor: Use openAPI code generation to create most of the methods - refactor: remove timeouts in matrix_api_lite ## 0.3.5 + - feat: Add image pack event content models ## 0.3.3 + - fix: Log filter in wrong direction ## 0.3.2 + - fix: Logs should only printed if loglevel is high enough ## 0.3.1 + - change: Remove logger package ## 0.3.0 + - feat: operation names from OpenAPI spec ## 0.2.6 + - fix: Missing RoomCreationTypes ## 0.2.5 + - fix: Request aliases ## 0.2.3 + - feat: Add room and event types for spaces ## 0.2.2 + - chore: upgrade logger to 1.0.0 - refactor: upgrade to http 0.13 ## 0.2.1 + - fix: Update dependency mime ## 0.2.0 + - refactor: login method AuthenticationIdentifier This is a breaking change for the login method to use the correct format. @@ -81,6 +106,7 @@ allow curly braces in Strings where not needed anymore. ## 0.1.9 + - feat: Add support for fallback keys ## 0.1.8 diff --git a/pubspec.yaml b/pubspec.yaml index 1cdb8463..b07dd67e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.0.0 +version: 1.1.0 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 80a4498ba9bcb3c9cca4d10b72f3ca61e2cf400b Mon Sep 17 00:00:00 2001 From: Henri Carnot Date: Wed, 8 Jun 2022 15:54:26 +0000 Subject: [PATCH 120/174] fix: use ChildrenState for children_state in the room hierarchy response --- lib/src/generated/api.dart | 3 +- lib/src/generated/model.dart | 9 +++--- lib/src/model/children_state.dart | 52 +++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 lib/src/model/children_state.dart diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 059101ab..7a495b1c 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -4,6 +4,7 @@ import '../model/auth/authentication_identifier.dart'; import '../model/matrix_keys.dart'; import '../model/sync_update.dart'; import '../model/matrix_event.dart'; +import '../model/children_state.dart'; import 'model.dart'; import 'fixed_model.dart'; @@ -1977,7 +1978,7 @@ class Api { /// returns `global`: /// The global ruleset. Future getPushRules() async { - final requestUri = Uri(path: '_matrix/client/v3/pushrules'); + final requestUri = Uri(path: '_matrix/client/v3/pushrules/'); final request = Request('GET', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; final response = await httpClient.send(request); diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index 1ccbebd9..37e3e477 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -4,6 +4,7 @@ import '../model/auth/authentication_identifier.dart'; import '../model/matrix_keys.dart'; import '../model/sync_update.dart'; import '../model/matrix_event.dart'; +import '../model/children_state.dart'; import 'internal.dart'; import 'package:enhanced_enum/enhanced_enum.dart'; @@ -169,7 +170,7 @@ class SpaceRoomsChunkBase { SpaceRoomsChunkBase.fromJson(Map json) : childrenState = (json['children_state'] as List) - .map((v) => MatrixEvent.fromJson(v)) + .map((v) => ChildrenState.fromJson(v)) .toList(), roomType = ((v) => v != null ? v as String : null)(json['room_type']); Map toJson() { @@ -184,7 +185,7 @@ class SpaceRoomsChunkBase { /// as [Stripped State Events](#stripped-state) with an added `origin_server_ts` key. /// /// If the room is not a space-room, this should be empty. - List childrenState; + List childrenState; /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. String? roomType; @@ -219,7 +220,7 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { topic = ((v) => v != null ? v as String : null)(json['topic']), worldReadable = json['world_readable'] as bool, childrenState = (json['children_state'] as List) - .map((v) => MatrixEvent.fromJson(v)) + .map((v) => ChildrenState.fromJson(v)) .toList(), roomType = ((v) => v != null ? v as String : null)(json['room_type']); Map toJson() { @@ -278,7 +279,7 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { /// as [Stripped State Events](#stripped-state) with an added `origin_server_ts` key. /// /// If the room is not a space-room, this should be empty. - List childrenState; + List childrenState; /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. String? roomType; diff --git a/lib/src/model/children_state.dart b/lib/src/model/children_state.dart new file mode 100644 index 00000000..ed0d6c26 --- /dev/null +++ b/lib/src/model/children_state.dart @@ -0,0 +1,52 @@ +/* MIT License +* +* Copyright (C) 2022 Famedly GmbH +* +* 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. +*/ + +import 'stripped_state_event.dart'; + +class ChildrenState extends StrippedStateEvent { + DateTime originServerTs; + + ChildrenState({ + required String type, + required Map content, + required String senderId, + required String stateKey, + required this.originServerTs, + }) : super( + type: type, + content: content, + senderId: senderId, + stateKey: stateKey); + + ChildrenState.fromJson(Map json) + : originServerTs = + DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']), + super.fromJson(json); + + @override + Map toJson() { + final data = super.toJson(); + data['origin_server_ts'] = originServerTs.millisecondsSinceEpoch; + return data; + } +} From 24a3369520046c0ae7a40dbad84385cd2b443a84 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 8 Jun 2022 17:16:39 +0200 Subject: [PATCH 121/174] tests: Add basic test for space hierarchy api --- lib/fake_matrix_api.dart | 210 ++++++++++++++++++++++++++++++++++++++ test/matrix_api_test.dart | 14 +++ 2 files changed, 224 insertions(+) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index b00b917b..e1e69596 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -746,6 +746,214 @@ class FakeMatrixApi extends MockClient { } }; + static Map spaceHierarchyResponse = { + 'rooms': [ + { + 'room_id': '!gPxZhKUssFZKZcoCKY:neko.dev', + 'name': 'Gentoo Community', + 'topic': + 'Unofficial Gentoo community rooms. Please keep chatter to the chatter room and have Gentoo discussions and questions in the actual Gentoo rooms. Also listen to the mods and try to keep nasty stuff to yourself. Thank you!', + 'canonical_alias': '#gentoo-community:matrix.org', + 'num_joined_members': 71, + 'avatar_url': 'mxc://neko.dev/YShzHcuHenkxaxostDrlMEYL', + 'join_rule': 'public', + 'world_readable': true, + 'guest_can_join': true, + 'room_type': 'm.space', + 'children_state': [ + { + 'type': 'm.space.child', + 'state_key': '!UpbiadsgRndwvYKPLK:neko.dev', + 'content': { + 'via': ['neko.dev'], + 'suggested': true, + 'auto_join': false + }, + 'sender': '@deepbluev7:neko.dev', + 'origin_server_ts': 1636376075316 + }, + { + 'type': 'm.space.child', + 'state_key': '!aZUzMIEZvEwnDquxLf:neko.dev', + 'content': { + 'via': ['neko.dev', 'matrix.org', 'privacytools.io'], + 'suggested': true, + 'auto_join': false + }, + 'sender': '@deepbluev7:neko.dev', + 'origin_server_ts': 1636378043231 + }, + { + 'type': 'm.space.child', + 'state_key': '!aRzRZBvOAkHMcEjAPS:libera.chat', + 'content': { + 'via': ['libera.chat', 'kde.org', 'neko.dev'], + 'suggested': false, + 'auto_join': false + }, + 'sender': '@deepbluev7:neko.dev', + 'origin_server_ts': 1637612945217 + }, + { + 'type': 'm.space.child', + 'state_key': '!DXsRRxkqqDhDkAyXfL:matrix.org', + 'content': { + 'via': ['matrix.org', 'libera.chat', 'neko.dev'], + 'suggested': false, + 'auto_join': false + }, + 'sender': '@deepbluev7:neko.dev', + 'origin_server_ts': 1637612945334 + }, + { + 'type': 'm.space.child', + 'state_key': '!tbCRpmsMiwMBlIThOd:matrix.org', + 'content': { + 'via': ['kde.org', 'matrix.org', 'server.matrix4ulm.de'], + 'suggested': false, + 'auto_join': false + }, + 'sender': '@deepbluev7:neko.dev', + 'origin_server_ts': 1637612945491 + }, + { + 'type': 'm.space.child', + 'state_key': '!LPpmvMsEgDwuSuHSpM:matrix.org', + 'content': { + 'via': ['matrix.org', 'anontier.nl', 't2bot.io'], + 'suggested': false, + 'auto_join': false + }, + 'sender': '@deepbluev7:neko.dev', + 'origin_server_ts': 1638720840346 + }, + { + 'type': 'm.space.child', + 'state_key': '!prlZxmnmAGuCYHUNSw:neko.dev', + 'content': { + 'auto_join': false, + 'suggested': true, + 'via': ['neko.dev', 'matrix.org'] + }, + 'sender': '@mo-the-alias-manager:matrix.org', + 'origin_server_ts': 1645661824176 + }, + { + 'type': 'm.space.child', + 'state_key': '!ooHixUOgoLVUjCSMZC:matrix.org', + 'content': { + 'via': ['neko.dev'], + 'suggested': false, + 'auto_join': false + }, + 'sender': '@deepbluev7:neko.dev', + 'origin_server_ts': 1647825979776 + } + ] + }, + { + 'room_id': '!UpbiadsgRndwvYKPLK:neko.dev', + 'name': 'Gentoo Chatter', + 'topic': + 'Offtopic discussions, distractions while emerge is running and banter. Keep attacks, politics and illegal stuff out of here, but otherwise most topics can end up here.', + 'canonical_alias': '#gentoo-chatter:matrix.org', + 'num_joined_members': 109, + 'avatar_url': 'mxc://neko.dev/kGMWPCWawJbKGEtEGwCETSrM', + 'join_rule': 'public', + 'world_readable': true, + 'guest_can_join': true, + 'children_state': [] + }, + { + 'room_id': '!aZUzMIEZvEwnDquxLf:neko.dev', + 'name': 'Gentoo', + 'topic': + "Unofficial. Talk about Gentoo stuff. Lightly moderated, i.e. try to keep topics Gentoo related and listen to the mods. Don't talk about politics, stuff like that never stays civil. (There are other rooms for that.) Checkout #gentoo-community:matrix.org and #gentoo-chatter:matrix.org. Also we love cats :3", + 'canonical_alias': '#gentoo:matrix.org', + 'num_joined_members': 1044, + 'avatar_url': 'mxc://neko.dev/dESQaOugYSkcFgLJYPNlWiNg', + 'join_rule': 'public', + 'world_readable': true, + 'guest_can_join': true, + 'children_state': [] + }, + { + 'room_id': '!aRzRZBvOAkHMcEjAPS:libera.chat', + 'name': '#gentoo-qt', + 'topic': + 'Gentoo Qt Project | Project page: https://qt.gentoo.org/ | Bugz: https://tinyurl.com/genqtbugs | FAQ: https://bit.ly/1jz8EhK | Latest Qt Stable: 5.15.3 / Unstable 5.15.4 | LXQt Stable: 1.0.0 / Unstable: 1.1.0 | Overlay: qt (Qt 6.3.0 Masked for Testing and 9999s for All)', + 'canonical_alias': '#gentoo-qt:libera.chat', + 'num_joined_members': 72, + 'join_rule': 'public', + 'world_readable': false, + 'guest_can_join': false, + 'children_state': [] + }, + { + 'room_id': '!DXsRRxkqqDhDkAyXfL:matrix.org', + 'name': 'Gentoo - de', + 'topic': + 'Deutschsprachiger Raum rund um die GNU/Linux Distribution Gentoo.', + 'canonical_alias': '#german-gentoo:matrix.org', + 'num_joined_members': 15, + 'avatar_url': 'mxc://matrix.org/UDJIpOEsVDGbgAliaxjqmhlf', + 'join_rule': 'public', + 'world_readable': false, + 'guest_can_join': false, + 'children_state': [] + }, + { + 'room_id': '!tbCRpmsMiwMBlIThOd:matrix.org', + 'name': '#gentoo-kde', + 'topic': + "Gentoo KDE | Guide: http://xrl.us/kdeguide | KF5 5.54.0 stable, 5.56.0 testing | Plasma 5.14.5 stable, 5.15.3 testing | Applications 18.08.3 stable, 18.12.3 testing | Bugs: http://xrl.us/kdebugs | Statistics: https://tinyurl.com/gkdestats | Please report bugs with pastebin'd build.log", + 'canonical_alias': '#freenode_#gentoo-kde:matrix.org', + 'num_joined_members': 86, + 'join_rule': 'public', + 'world_readable': false, + 'guest_can_join': false, + 'children_state': [] + }, + { + 'room_id': '!LPpmvMsEgDwuSuHSpM:matrix.org', + 'name': 'Gentoo-rus (Русский/Russian)', + 'topic': 'Вопросы по Gentoo', + 'canonical_alias': '#gentoo-rus:matrix.org', + 'num_joined_members': 68, + 'avatar_url': 'mxc://matrix.org/KuRHZNSQttAmQekputXpXmeQ', + 'join_rule': 'public', + 'world_readable': true, + 'guest_can_join': true, + 'children_state': [] + }, + { + 'room_id': '!prlZxmnmAGuCYHUNSw:neko.dev', + 'name': 'Gentoo Hardening', + 'topic': + 'If you care too much about security and Gentoo, this is your place to talk about it. Bring your hard hats, it sometimes gets heated (please behave). (Unofficial)', + 'canonical_alias': '#gentoo-hardening:matrix.org', + 'num_joined_members': 47, + 'avatar_url': 'mxc://neko.dev/MMDsJENimfwQlHshSkdFlDaU', + 'join_rule': 'public', + 'world_readable': true, + 'guest_can_join': false, + 'children_state': [] + }, + { + 'room_id': '!ooHixUOgoLVUjCSMZC:matrix.org', + 'name': 'Gentoo Brasil', + 'topic': 'Usuários brasileiros do Gentoo Linux', + 'canonical_alias': '#gentoobr:matrix.org', + 'num_joined_members': 35, + 'avatar_url': 'mxc://matrix.org/vXqGcGnyUbIjhXAalSxfDxJD', + 'join_rule': 'public', + 'world_readable': true, + 'guest_can_join': true, + 'children_state': [] + } + ] + }; + static final Map> api = { 'GET': { '/path/to/auth/error': (var req) => { @@ -1626,6 +1834,8 @@ class FakeMatrixApi extends MockClient { }, }, }, + '/client/v1/rooms/${Uri.encodeComponent('!gPxZhKUssFZKZcoCKY:neko.dev')}/hierarchy': + (var req) => spaceHierarchyResponse, }, 'POST': { '/client/v3/delete_devices': (var req) => {}, diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 15a4999a..962050b6 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -855,6 +855,20 @@ void main() { matrixApi.homeserver = matrixApi.accessToken = null; }); + test('getSpaceHierarchy', () async { + matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); + matrixApi.accessToken = '1234'; + + final response = + await matrixApi.getSpaceHierarchy('!gPxZhKUssFZKZcoCKY:neko.dev'); + + expect( + FakeMatrixApi.api['GET']![ + '/client/v1/rooms/${Uri.encodeComponent('!gPxZhKUssFZKZcoCKY:neko.dev')}/hierarchy']({}), + response.toJson()); + + matrixApi.homeserver = matrixApi.accessToken = null; + }); test('searchUser', () async { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; From f64d9050dec3e6f47efc64cda3ddd3b9e562dedc Mon Sep 17 00:00:00 2001 From: "h.carnot" Date: Wed, 8 Jun 2022 18:02:30 +0200 Subject: [PATCH 122/174] chore: bump version --- CHANGELOG.md | 6 ++++++ pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9248356..a46151ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.1.1 + +- fix: wrong type for children_state in spaces hierarchy API +- fix: Missing trailing slash on pushrules endpoint +- tests: added tests for spaces hierarchy + ## 1.1.0 - fix: wrong types in spaces hierarchy API diff --git a/pubspec.yaml b/pubspec.yaml index b07dd67e..a808bc98 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.0 +version: 1.1.1 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 04e9ae522da4cd21b3894f736b66704fea0c99b7 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 1 Aug 2022 15:24:21 +0200 Subject: [PATCH 123/174] feat: Add a flag to disable colors in logs --- lib/src/utils/logs.dart | 1 + lib/src/utils/print_logs_native.dart | 38 +++++++++++++++------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index f9ae4394..8c509899 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -40,6 +40,7 @@ class Logs { } Level level = Level.info; + bool nativeColors = true; final List outputEvents = []; diff --git a/lib/src/utils/print_logs_native.dart b/lib/src/utils/print_logs_native.dart index b6790e4e..00dae586 100644 --- a/lib/src/utils/print_logs_native.dart +++ b/lib/src/utils/print_logs_native.dart @@ -9,24 +9,26 @@ extension PrintLogs on LogEvent { if (stackTrace != null) { logsStr += '\n${stackTrace.toString()}'; } - switch (level) { - case Level.wtf: - logsStr = '\x1B[31m!!!CRITICAL!!! $logsStr\x1B[0m'; - break; - case Level.error: - logsStr = '\x1B[31m$logsStr\x1B[0m'; - break; - case Level.warning: - logsStr = '\x1B[33m$logsStr\x1B[0m'; - break; - case Level.info: - logsStr = '\x1B[32m$logsStr\x1B[0m'; - break; - case Level.debug: - logsStr = '\x1B[34m$logsStr\x1B[0m'; - break; - case Level.verbose: - break; + if (Logs().nativeColors) { + switch (level) { + case Level.wtf: + logsStr = '\x1B[31m!!!CRITICAL!!! $logsStr\x1B[0m'; + break; + case Level.error: + logsStr = '\x1B[31m$logsStr\x1B[0m'; + break; + case Level.warning: + logsStr = '\x1B[33m$logsStr\x1B[0m'; + break; + case Level.info: + logsStr = '\x1B[32m$logsStr\x1B[0m'; + break; + case Level.debug: + logsStr = '\x1B[34m$logsStr\x1B[0m'; + break; + case Level.verbose: + break; + } } // ignore: avoid_print print('[Matrix] $logsStr'); From df2f210e831c65366370ffae618e31cf9a957cf2 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 2 Aug 2022 08:31:40 +0200 Subject: [PATCH 124/174] chore: Bump version --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a46151ba..3375f715 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [1.1.2] - 2nd Aug 2022 +- feat: Add a flag to disable colors in logs + ## 1.1.1 - fix: wrong type for children_state in spaces hierarchy API diff --git a/pubspec.yaml b/pubspec.yaml index a808bc98..c0707675 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.1 +version: 1.1.2 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From f7003933e684ddb39e7c5bcc405559403032b88c Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 8 Aug 2022 16:47:08 +0200 Subject: [PATCH 125/174] chore: export filter map extension --- lib/matrix_api_lite.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/matrix_api_lite.dart b/lib/matrix_api_lite.dart index 096b476d..77a4e4e0 100644 --- a/lib/matrix_api_lite.dart +++ b/lib/matrix_api_lite.dart @@ -61,6 +61,7 @@ export 'src/model/room_creation_types.dart'; export 'src/model/room_summary.dart'; export 'src/model/stripped_state_event.dart'; export 'src/model/sync_update.dart'; +export 'src/utils/filter_map_extension.dart'; export 'src/utils/logs.dart'; export 'src/utils/map_copy_extension.dart'; export 'src/utils/try_get_map_extension.dart'; From 2f944292ba3d940464975cb8d80ad8ca994222b4 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 12 Aug 2022 09:06:51 +0200 Subject: [PATCH 126/174] fix: Secret storage keys are used as account data but are not uri encoded This always encodes the storage key so it can be used as account data. Before the app has waited failed to use this key at all so we do not need a migration. --- lib/src/model/event_types.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index b948c8a2..3878cb7a 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -81,7 +81,9 @@ abstract class EventTypes { static const String MegolmBackup = 'm.megolm_backup.v1'; static const String SecretStorageDefaultKey = 'm.secret_storage.default_key'; - static String secretStorageKey(String keyId) => 'm.secret_storage.key.$keyId'; + // Also used as account data type so it needs to be uri encoded + static String secretStorageKey(String keyId) => + Uri.encodeComponent('m.secret_storage.key.$keyId'); // Spaces static const String spaceParent = 'm.space.parent'; From cb743e8df04b801c06cf1222335d01f6bdc7cccb Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 12 Aug 2022 09:08:16 +0200 Subject: [PATCH 127/174] chore: Bump version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3375f715..b56a5030 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [1.1.3] - 2nd Aug 2022 +- fix: Secret storage keys are used as account data but are not uri encoded +- chore: export filter map extension + ## [1.1.2] - 2nd Aug 2022 - feat: Add a flag to disable colors in logs diff --git a/pubspec.yaml b/pubspec.yaml index c0707675..4a834ffc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.2 +version: 1.1.3 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From ff66e1c208b0b47b440b88ce5d71e41bbbb98fb1 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 19 Aug 2022 11:37:22 +0200 Subject: [PATCH 128/174] chore: upgrade from pedantic to lints --- analysis_options.yaml | 11 ++++++----- lib/fake_matrix_api.dart | 5 ++--- lib/src/matrix_api.dart | 10 +++++----- lib/src/model/matrix_exception.dart | 2 +- lib/src/utils/print_logs_native.dart | 2 +- lib/src/utils/print_logs_web.dart | 2 +- pubspec.yaml | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 8e8f9513..6e0d5c78 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,11 +1,12 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml linter: rules: - - camel_case_types - - avoid_print - - prefer_final_locals - - prefer_final_in_for_each + camel_case_types: true + avoid_print: true + constant_identifier_names: false + prefer_final_locals: true + prefer_final_in_for_each: true analyzer: errors: diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index e1e69596..5b8d94f0 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -49,9 +49,8 @@ class FakeMatrixApi extends MockClient { // Collect data from Request var action = request.url.path; if (request.url.path.contains('/_matrix')) { - action = request.url.path.split('/_matrix').last + - '?' + - request.url.query; + action = + '${request.url.path.split('/_matrix').last}?${request.url.query}'; } if (action.endsWith('?')) { diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index b359cdd4..cb628958 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -45,11 +45,11 @@ class MatrixApi extends Api { set accessToken(String? token) => bearerToken = token; @override - Never unexpectedResponse(http.BaseResponse response, Uint8List responseBody) { + Never unexpectedResponse(http.BaseResponse response, Uint8List body) { if (response.statusCode >= 400 && response.statusCode < 500) { - throw MatrixException.fromJson(json.decode(utf8.decode(responseBody))); + throw MatrixException.fromJson(json.decode(utf8.decode(body))); } - super.unexpectedResponse(response, responseBody); + super.unexpectedResponse(response, body); } MatrixApi({ @@ -90,7 +90,7 @@ class MatrixApi extends Api { throw ('No homeserver specified.'); } dynamic json; - (!(data is String)) ? json = jsonEncode(data) : json = data; + (data is! String) ? json = jsonEncode(data) : json = data; if (data is List || action.startsWith('/media/v3/upload')) json = data; final url = homeserver! @@ -132,7 +132,7 @@ class MatrixApi extends Api { } var jsonString = String.fromCharCodes(respBody.runes); if (jsonString.startsWith('[') && jsonString.endsWith(']')) { - jsonString = '\{"chunk":$jsonString\}'; + jsonString = '{"chunk":$jsonString}'; } jsonResp = jsonDecode(jsonString) as Map?; // May throw FormatException diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 822d9845..1555dfeb 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -106,7 +106,7 @@ class MatrixException implements Exception { /// to authenticate itself. Each flow comprises a series of stages. If this request /// doesn't need additional authentication, then this is null. List? get authenticationFlows { - if (!raw.containsKey('flows') || !(raw['flows'] is List)) return null; + if (!raw.containsKey('flows') || raw['flows'] is! List) return null; return (raw['flows'] as List) .map((flow) => flow['stages']) .whereType() diff --git a/lib/src/utils/print_logs_native.dart b/lib/src/utils/print_logs_native.dart index 00dae586..7b8f5314 100644 --- a/lib/src/utils/print_logs_native.dart +++ b/lib/src/utils/print_logs_native.dart @@ -4,7 +4,7 @@ extension PrintLogs on LogEvent { void printOut() { var logsStr = title; if (exception != null) { - logsStr += ' - ' + exception.toString(); + logsStr += ' - ${exception.toString()}'; } if (stackTrace != null) { logsStr += '\n${stackTrace.toString()}'; diff --git a/lib/src/utils/print_logs_web.dart b/lib/src/utils/print_logs_web.dart index ea67b71d..aa7c6e0f 100644 --- a/lib/src/utils/print_logs_web.dart +++ b/lib/src/utils/print_logs_web.dart @@ -5,7 +5,7 @@ extension PrintLogs on LogEvent { void printOut() { var logsStr = '[Matrix] $title'; if (exception != null) { - logsStr += ' - ' + exception.toString(); + logsStr += ' - ${exception.toString()}'; } if (stackTrace != null) { logsStr += '\n${stackTrace.toString()}'; diff --git a/pubspec.yaml b/pubspec.yaml index 4a834ffc..77c4a4aa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lit issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.17.0 <3.0.0" dependencies: enhanced_enum: ^0.1.1 @@ -16,5 +16,5 @@ dependencies: dev_dependencies: build_runner: ^2.1.8 enhanced_enum_generator: ^0.1.1 - pedantic: ^1.11.0 + lints: ^2.0.0 test: ^1.14.4 From 57ec5014d9f36ed94cb4ea383b307442533ae5c7 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Fri, 19 Aug 2022 12:15:30 +0200 Subject: [PATCH 129/174] chore: use updated dart image --- .gitlab-ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e6636750..cef66890 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,10 +8,10 @@ test: tags: - linux stage: coverage - image: google/dart + image: dart script: - - pub get - - pub run test + - dart pub get + - dart pub run test code_analyze: tags: @@ -53,7 +53,7 @@ pages: dry-run: stage: publish - image: google/dart + image: dart script: - rm -rf ./docs - dart pub get @@ -61,7 +61,7 @@ dry-run: pub-dev: stage: publish - image: google/dart + image: dart script: - rm -rf ./docs - | From 7471743be38110b9d0d1cdb878b79bca2253b681 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 20 Aug 2022 11:28:43 +0200 Subject: [PATCH 130/174] chore: disable dynamic calls --- analysis_options.yaml | 1 + lib/fake_matrix_api.dart | 76 ++++++++------- lib/src/matrix_api.dart | 5 +- lib/src/model/matrix_exception.dart | 14 +-- lib/src/model/matrix_keys.dart | 2 +- lib/src/model/sync_update.dart | 110 ++++++++------------- test/map_copy_extension_test.dart | 17 ++-- test/matrix_api_test.dart | 146 +++++++++++++++++----------- 8 files changed, 194 insertions(+), 177 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 6e0d5c78..24559023 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -7,6 +7,7 @@ linter: constant_identifier_names: false prefer_final_locals: true prefer_final_in_for_each: true + avoid_dynamic_calls: true analyzer: errors: diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 5b8d94f0..bc4e5fe2 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -33,12 +33,14 @@ Map decodeJson(dynamic data) { if (data is String) { return json.decode(data); } - if (data.isEmpty) { + if (data is Map && data.isEmpty) { return {}; } return data; } +T? tryCast(dynamic object) => object is T ? object : null; + /// A mock http client for testing purposes. class FakeMatrixApi extends MockClient { static final calledEndpoints = >{}; @@ -83,7 +85,7 @@ class FakeMatrixApi extends MockClient { } calledEndpoints[action]!.add(data); if (api.containsKey(method) && api[method]!.containsKey(action)) { - res = api[method]![action](data); + res = api[method]![action]?.call(data); if (res is Map && res.containsKey('errcode')) { statusCode = 405; } @@ -953,7 +955,7 @@ class FakeMatrixApi extends MockClient { ] }; - static final Map> api = { + static final Map> api = { 'GET': { '/path/to/auth/error': (var req) => { 'errcode': 'M_FORBIDDEN', @@ -1942,42 +1944,45 @@ class FakeMatrixApi extends MockClient { 'prev_batch': 'p1902', 'total_room_count_estimate': 115 }, - '/client/v3/keys/claim': (var req) => { - 'failures': {}, - 'one_time_keys': { - if (decodeJson(req)['one_time_keys']['@alice:example.com'] != - null) - '@alice:example.com': { - 'JLAFKJWSCS': { - 'signed_curve25519:AAAAAQ': { - 'key': 'ikMXajRlkS7Xi9CROrAh3jXnbygk8mLBdSaY9/al0X0', - 'signatures': { - '@alice:example.com': { - 'ed25519:JLAFKJWSCS': - 'XdboCa0Ljoh0Y0i/IVnmMqy/+T1hJyu8BA/nRYniJMQ7QWh/pGS5AsWswdARD+MAX+r4u98Qzk0y27HUddZXDA' - } + '/client/v3/keys/claim': (dynamic req) { + final request = decodeJson(req)["one_time_keys"]; + final keys = (request is Map) + ? request["one_time_keys"] as Map? + : null; + return { + 'failures': {}, + 'one_time_keys': { + if (keys?['@alice:example.com'] != null) + '@alice:example.com': { + 'JLAFKJWSCS': { + 'signed_curve25519:AAAAAQ': { + 'key': 'ikMXajRlkS7Xi9CROrAh3jXnbygk8mLBdSaY9/al0X0', + 'signatures': { + '@alice:example.com': { + 'ed25519:JLAFKJWSCS': + 'XdboCa0Ljoh0Y0i/IVnmMqy/+T1hJyu8BA/nRYniJMQ7QWh/pGS5AsWswdARD+MAX+r4u98Qzk0y27HUddZXDA' } } } - }, - if (decodeJson(req)['one_time_keys'] - ['@test:fakeServer.notExisting'] != - null) - '@test:fakeServer.notExisting': { - 'GHTYAJCE': { - 'signed_curve25519:AAAAAQ': { - 'key': 'qc72ve94cA28iuE0fXa98QO3uls39DHWdQlYyvvhGh0', - 'signatures': { - '@test:fakeServer.notExisting': { - 'ed25519:GHTYAJCE': - 'dFwffr5kTKefO7sjnWLMhTzw7oV31nkPIDRxFy5OQT2OP5++Ao0KRbaBZ6qfuT7lW1owKK0Xk3s7QTBvc/eNDA', - }, + } + }, + if (keys?['@test:fakeServer.notExisting'] != null) + '@test:fakeServer.notExisting': { + 'GHTYAJCE': { + 'signed_curve25519:AAAAAQ': { + 'key': 'qc72ve94cA28iuE0fXa98QO3uls39DHWdQlYyvvhGh0', + 'signatures': { + '@test:fakeServer.notExisting': { + 'ed25519:GHTYAJCE': + 'dFwffr5kTKefO7sjnWLMhTzw7oV31nkPIDRxFy5OQT2OP5++Ao0KRbaBZ6qfuT7lW1owKK0Xk3s7QTBvc/eNDA', }, }, }, }, - } - }, + }, + } + }; + }, '/client/v3/rooms/!localpart%3Aexample.com/invite': (var req) => {}, '/client/v3/rooms/!localpart%3Aexample.com/leave': (var req) => {}, '/client/v3/rooms/!localpart%3Aexample.com/forget': (var req) => {}, @@ -1992,8 +1997,11 @@ class FakeMatrixApi extends MockClient { '/client/v3/keys/upload': (var req) => { 'one_time_key_counts': { 'curve25519': 10, - 'signed_curve25519': - decodeJson(req)['one_time_keys']?.keys?.length ?? 0, + 'signed_curve25519': tryCast>>( + decodeJson(req))?['one_time_keys'] + ?.keys + .length ?? + 0, } }, '/client/v3/keys/query': (var req) => { diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index cb628958..e768c4d5 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -209,7 +209,10 @@ class MatrixApi extends Api { // fix invalid responses from synapse // https://github.com/matrix-org/synapse/pull/10922 - json['ttl'] = json['ttl'].toInt(); + final ttl = json['ttl']; + if (ttl is double) { + json['ttl'] = ttl.toInt(); + } return TurnServerCredentials.fromJson(json); } diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 1555dfeb..94257427 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -106,12 +106,14 @@ class MatrixException implements Exception { /// to authenticate itself. Each flow comprises a series of stages. If this request /// doesn't need additional authentication, then this is null. List? get authenticationFlows { - if (!raw.containsKey('flows') || raw['flows'] is! List) return null; - return (raw['flows'] as List) - .map((flow) => flow['stages']) - .whereType() - .map((stages) => AuthenticationFlow(List.from(stages))) - .toList(); + final flows = raw['flows']; + return (flows is List>>) + ? flows + .map((flow) => flow['stages']) + .whereType>() + .map((stages) => AuthenticationFlow(List.from(stages))) + .toList() + : null; } /// This section contains any information that the client will need to know in order to use a given type diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index 01c0538a..65f47368 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -113,7 +113,7 @@ class MatrixDeviceKeys extends MatrixSignableKey { @override MatrixDeviceKeys.fromJson(Map json) - : algorithms = json['algorithms'].cast(), + : algorithms = (json['algorithms'] as List).cast(), deviceId = json['device_id'], super.fromJson(json); diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index 95aaf3e5..e1e7da52 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -54,24 +54,15 @@ class SyncUpdate { : nextBatch = json['next_batch'], rooms = json['rooms'] != null ? RoomsUpdate.fromJson(json['rooms']) : null, - presence = - (json['presence'] != null && json['presence']['events'] != null) - ? (json['presence']['events'] as List) - .map((i) => Presence.fromJson(i)) - .toList() - : null, - accountData = (json['account_data'] != null && - json['account_data']['events'] != null) - ? (json['account_data']['events'] as List) - .map((i) => BasicEvent.fromJson(i)) - .toList() - : null, - toDevice = - (json['to_device'] != null && json['to_device']['events'] != null) - ? (json['to_device']['events'] as List) - .map((i) => BasicEventWithSender.fromJson(i)) - .toList() - : null, + presence = ((json['presence'] as Map?)?['events'] as List?) + ?.map((i) => Presence.fromJson(i)) + .toList(), + accountData = ((json['account_data'] as Map?)?['events'] as List?) + ?.map((i) => BasicEvent.fromJson(i)) + .toList(), + toDevice = ((json['to_device'] as Map?)?['events'] as List?) + ?.map((i) => BasicEventWithSender.fromJson(i)) + .toList(), deviceLists = json['device_lists'] != null ? DeviceListsUpdate.fromJson(json['device_lists']) : null, @@ -183,34 +174,25 @@ class JoinedRoomUpdate extends SyncRoomUpdate { this.unreadNotifications, }); - JoinedRoomUpdate.fromJson(Map json) { - summary = - json['summary'] != null ? RoomSummary.fromJson(json['summary']) : null; - state = (json['state'] != null && json['state']['events'] != null) - ? (json['state']['events'] as List) - .map((i) => MatrixEvent.fromJson(i)) - .toList() - : null; - timeline = json['timeline'] != null - ? TimelineUpdate.fromJson(json['timeline']) - : null; - - ephemeral = - (json['ephemeral'] != null && json['ephemeral']['events'] != null) - ? (json['ephemeral']['events'] as List) - .map((i) => BasicRoomEvent.fromJson(i)) - .toList() + JoinedRoomUpdate.fromJson(Map json) + : summary = json['summary'] != null + ? RoomSummary.fromJson(json['summary']) + : null, + state = ((json['state'] as Map?)?['events'] as List?) + ?.map((i) => MatrixEvent.fromJson(i)) + .toList(), + timeline = json['timeline'] != null + ? TimelineUpdate.fromJson(json['timeline']) + : null, + ephemeral = ((json['ephemeral'] as Map?)?['events'] as List?) + ?.map((i) => BasicRoomEvent.fromJson(i)) + .toList(), + accountData = ((json['account_data'] as Map?)?['events'] as List?) + ?.map((i) => BasicRoomEvent.fromJson(i)) + .toList(), + unreadNotifications = json['unread_notifications'] != null + ? UnreadNotificationCounts.fromJson(json['unread_notifications']) : null; - accountData = - (json['account_data'] != null && json['account_data']['events'] != null) - ? (json['account_data']['events'] as List) - .map((i) => BasicRoomEvent.fromJson(i)) - .toList() - : null; - unreadNotifications = json['unread_notifications'] != null - ? UnreadNotificationCounts.fromJson(json['unread_notifications']) - : null; - } Map toJson() { final data = {}; @@ -247,14 +229,10 @@ class InvitedRoomUpdate extends SyncRoomUpdate { InvitedRoomUpdate({this.inviteState}); - InvitedRoomUpdate.fromJson(Map json) { - inviteState = - (json['invite_state'] != null && json['invite_state']['events'] != null) - ? (json['invite_state']['events'] as List) - .map((i) => StrippedStateEvent.fromJson(i)) - .toList() - : null; - } + InvitedRoomUpdate.fromJson(Map json) + : inviteState = ((json['invite_state'] as Map?)?['events'] as List?) + ?.map((i) => StrippedStateEvent.fromJson(i)) + .toList(); Map toJson() { final data = {}; @@ -278,22 +256,16 @@ class LeftRoomUpdate extends SyncRoomUpdate { this.accountData, }); - LeftRoomUpdate.fromJson(Map json) { - state = (json['state'] != null && json['state']['events'] != null) - ? (json['state']['events'] as List) - .map((i) => MatrixEvent.fromJson(i)) - .toList() - : null; - timeline = json['timeline'] != null - ? TimelineUpdate.fromJson(json['timeline']) - : null; - accountData = - (json['account_data'] != null && json['account_data']['events'] != null) - ? (json['account_data']['events'] as List) - .map((i) => BasicRoomEvent.fromJson(i)) - .toList() - : null; - } + LeftRoomUpdate.fromJson(Map json) + : state = ((json['state'] as Map?)?['events'] as List?) + ?.map((i) => MatrixEvent.fromJson(i)) + .toList(), + timeline = json['timeline'] != null + ? TimelineUpdate.fromJson(json['timeline']) + : null, + accountData = ((json['account_data'] as Map?)?['events'] as List?) + ?.map((i) => BasicRoomEvent.fromJson(i)) + .toList(); Map toJson() { final data = {}; diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart index 329771d9..3578c624 100644 --- a/test/map_copy_extension_test.dart +++ b/test/map_copy_extension_test.dart @@ -35,10 +35,10 @@ void main() { }, }; final copy = original.copy(); - original['child']['attr'] = 'raccoon'; - expect(copy['child']['attr'], 'bunny'); - original['child']['list'].add(3); - expect(copy['child']['list'], [1, 2]); + (original['child'] as Map)['attr'] = 'raccoon'; + expect((copy['child'] as Map)['attr'], 'bunny'); + ((original['child'] as Map)['list'] as List).add(3); + expect((copy['child'] as Map)['list'], [1, 2]); }); test('should do arrays', () { final original = { @@ -48,10 +48,11 @@ void main() { ], }; final copy = original.copy(); - original['arr'][0].add(3); - expect(copy['arr'][0], [1, 2]); - original['arr'][1]['beep'] = 'blargh'; - expect(copy['arr'][1]['beep'], 'boop'); + ((original['arr'] as List)[0] as List).add(3); + expect((copy['arr'] as List)[0], [1, 2]); + ((original['arr'] as List)[1] as Map)['beep'] = 'blargh'; + expect( + ((copy['arr'] as List)[1] as Map)['beep'], 'boop'); }); }); } diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 962050b6..af7de7c6 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -123,7 +123,7 @@ void main() { final supportedVersions = await matrixApi.getVersions(); expect(supportedVersions.versions.contains('r0.5.0'), true); expect(supportedVersions.unstableFeatures!['m.lazy_load_members'], true); - expect(FakeMatrixApi.api['GET']!['/client/versions']({}), + expect(FakeMatrixApi.api['GET']!['/client/versions']!.call({}), supportedVersions.toJson()); matrixApi.homeserver = null; }); @@ -146,7 +146,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final loginTypes = await matrixApi.getLoginFlows(); expect(loginTypes?.first.type, 'm.login.password'); - expect(FakeMatrixApi.api['GET']!['/client/v3/login']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/login']!.call({}), {'flows': loginTypes?.map((x) => x.toJson()).toList()}); matrixApi.homeserver = null; }); @@ -156,7 +156,7 @@ void main() { LoginType.mLoginPassword, identifier: AuthenticationUserIdentifier(user: 'username'), ); - expect(FakeMatrixApi.api['POST']!['/client/v3/login']({}), + expect(FakeMatrixApi.api['POST']!['/client/v3/login']!.call({}), loginResponse.toJson()); matrixApi.homeserver = null; }); @@ -176,7 +176,9 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final registerResponse = await matrixApi.register(kind: AccountKind.guest, username: 'test'); - expect(FakeMatrixApi.api['POST']!['/client/v3/register?kind=guest']({}), + expect( + FakeMatrixApi.api['POST']!['/client/v3/register?kind=guest']! + .call({}), registerResponse.toJson()); matrixApi.homeserver = null; }); @@ -192,8 +194,8 @@ void main() { idAccessToken: '1234', ); expect( - FakeMatrixApi - .api['POST']!['/client/v3/register/email/requestToken']({}), + FakeMatrixApi.api['POST']!['/client/v3/register/email/requestToken']! + .call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -210,8 +212,8 @@ void main() { idAccessToken: '1234', ); expect( - FakeMatrixApi - .api['POST']!['/client/v3/register/email/requestToken']({}), + FakeMatrixApi.api['POST']!['/client/v3/register/email/requestToken']! + .call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -280,7 +282,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getAccount3PIDs(); - expect(FakeMatrixApi.api['GET']!['/client/v3/account/3pid']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/account/3pid']!.call({}), {'threepids': response?.map((t) => t.toJson()).toList()}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -362,7 +364,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getCapabilities(); - expect(FakeMatrixApi.api['GET']!['/client/v3/capabilities']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/capabilities']!.call({}), {'capabilities': response.toJson()}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -497,8 +499,8 @@ void main() { ); expect( FakeMatrixApi.api['GET']![ - '/client/v3/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15']( - {}) as Map?, + '/client/v3/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15']! + .call({}) as Map?, response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -575,8 +577,8 @@ void main() { expect( FakeMatrixApi.api['GET']![ - '/client/v3/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']( - {}) as Map?, + '/client/v3/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']! + .call({}) as Map?, timelineHistoryResponse.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -666,7 +668,8 @@ void main() { expect( FakeMatrixApi.api['GET']![ - '/client/v3/directory/room/%23testalias%3Aexample.com']({}), + '/client/v3/directory/room/%23testalias%3Aexample.com']! + .call({}), roomAliasInformation.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -828,7 +831,8 @@ void main() { expect( FakeMatrixApi.api['GET']![ - '/client/v3/publicRooms?limit=10&since=1234&server=example.com']({}), + '/client/v3/publicRooms?limit=10&since=1234&server=example.com']! + .call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -850,7 +854,8 @@ void main() { expect( FakeMatrixApi - .api['POST']!['/client/v3/publicRooms?server=example.com']({}), + .api['POST']!['/client/v3/publicRooms?server=example.com']! + .call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -864,7 +869,8 @@ void main() { expect( FakeMatrixApi.api['GET']![ - '/client/v1/rooms/${Uri.encodeComponent('!gPxZhKUssFZKZcoCKY:neko.dev')}/hierarchy']({}), + '/client/v1/rooms/${Uri.encodeComponent('!gPxZhKUssFZKZcoCKY:neko.dev')}/hierarchy']! + .call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -878,7 +884,9 @@ void main() { limit: 10, ); - expect(FakeMatrixApi.api['POST']!['/client/v3/user_directory/search']({}), + expect( + FakeMatrixApi.api['POST']!['/client/v3/user_directory/search']! + .call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -926,7 +934,8 @@ void main() { final response = await matrixApi.getUserProfile('@alice:example.com'); expect( FakeMatrixApi - .api['GET']!['/client/v3/profile/%40alice%3Aexample.com']({}), + .api['GET']!['/client/v3/profile/%40alice%3Aexample.com']! + .call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -936,7 +945,7 @@ void main() { matrixApi.accessToken = '1234'; final response = await matrixApi.getTurnServer(); - expect(FakeMatrixApi.api['GET']!['/client/v3/voip/turnServer']({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/voip/turnServer']!.call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1000,7 +1009,8 @@ void main() { ); expect( FakeMatrixApi.api['GET']![ - '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status']({}), + '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status']! + .call({}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1030,7 +1040,8 @@ void main() { ); expect( FakeMatrixApi.api['GET']![ - '/media/v3/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']({}), + '/media/v3/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']! + .call({}), openGraphData.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1061,7 +1072,9 @@ void main() { matrixApi.accessToken = '1234'; final devices = await matrixApi.getDevices(); - expect(FakeMatrixApi.api['GET']!['/client/v3/devices']({})['devices'], + expect( + (FakeMatrixApi.api['GET']!['/client/v3/devices']!.call({}) + as Map?)?['devices'], devices?.map((i) => i.toJson()).toList()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1131,8 +1144,8 @@ void main() { .deviceDisplayName, 'Alices mobile phone'); expect( - FakeMatrixApi - .api['POST']!['/client/v3/keys/query']({'device_keys': {}}), + FakeMatrixApi.api['POST']!['/client/v3/keys/query']! + .call({'device_keys': {}}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1148,7 +1161,7 @@ void main() { timeout: 10, ); expect( - FakeMatrixApi.api['POST']!['/client/v3/keys/claim']({ + FakeMatrixApi.api['POST']!['/client/v3/keys/claim']!.call({ 'one_time_keys': { '@alice:example.com': {'JLAFKJWSCS': 'signed_curve25519'} } @@ -1207,7 +1220,7 @@ void main() { final response = await matrixApi.getPushers(); expect( - FakeMatrixApi.api['GET']!['/client/v3/pushers']({}), + FakeMatrixApi.api['GET']!['/client/v3/pushers']!.call({}), {'pushers': response?.map((i) => i.toJson()).toList()}, ); @@ -1245,7 +1258,8 @@ void main() { ); expect( FakeMatrixApi.api['GET']![ - '/client/v3/notifications?from=1234&limit=10&only=1234']({}), + '/client/v3/notifications?from=1234&limit=10&only=1234']! + .call({}), response.toJson(), ); @@ -1257,7 +1271,7 @@ void main() { final response = await matrixApi.getPushRules(); expect( - FakeMatrixApi.api['GET']!['/client/v3/pushrules']({}), + FakeMatrixApi.api['GET']!['/client/v3/pushrules']!.call({}), {'global': response.toJson()}, ); @@ -1270,8 +1284,8 @@ void main() { final response = await matrixApi.getPushRule('global', PushRuleKind.content, 'nocake'); expect( - FakeMatrixApi - .api['GET']!['/client/v3/pushrules/global/content/nocake']({}), + FakeMatrixApi.api['GET']!['/client/v3/pushrules/global/content/nocake']! + .call({}), response.toJson(), ); @@ -1371,7 +1385,8 @@ void main() { from: '1234', roomId: '!1234', timeout: 10); expect( FakeMatrixApi.api['GET']![ - '/client/v3/events?from=1234&timeout=10&room_id=%211234']({}), + '/client/v3/events?from=1234&timeout=10&room_id=%211234']! + .call({}), response.toJson(), ); @@ -1385,7 +1400,8 @@ void main() { '@alice:example.com', '!localpart:example.com'); expect( FakeMatrixApi.api['GET']![ - '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']({}), + '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']! + .call({}), {'tags': response?.map((k, v) => MapEntry(k, v.toJson()))}, ); @@ -1471,7 +1487,8 @@ void main() { final response = await matrixApi.getWhoIs('@alice:example.com'); expect( FakeMatrixApi - .api['GET']!['/client/v3/admin/whois/%40alice%3Aexample.com']({}), + .api['GET']!['/client/v3/admin/whois/%40alice%3Aexample.com']! + .call({}), response.toJson(), ); @@ -1485,7 +1502,8 @@ void main() { limit: 10, filter: '{}'); expect( FakeMatrixApi.api['GET']![ - '/client/v3/rooms/1234/context/1234?limit=10&filter=%7B%7D']({}), + '/client/v3/rooms/1234/context/1234?limit=10&filter=%7B%7D']! + .call({}), response.toJson(), ); @@ -1510,7 +1528,7 @@ void main() { final response = await matrixApi.getProtocols(); expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocols']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocols']!.call({}), response.map((k, v) => MapEntry(k, v.toJson())), ); @@ -1522,7 +1540,8 @@ void main() { final response = await matrixApi.getProtocolMetadata('irc'); expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocol/irc']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocol/irc']! + .call({}), response.toJson(), ); @@ -1534,7 +1553,8 @@ void main() { final response = await matrixApi.queryLocationByProtocol('irc'); expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/location/irc']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/location/irc']! + .call({}), response.map((i) => i.toJson()).toList(), ); @@ -1546,7 +1566,7 @@ void main() { final response = await matrixApi.queryUserByProtocol('irc'); expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user/irc']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user/irc']!.call({}), response.map((i) => i.toJson()).toList(), ); @@ -1558,8 +1578,8 @@ void main() { final response = await matrixApi.queryLocationByAlias('1234'); expect( - FakeMatrixApi - .api['GET']!['/client/v3/thirdparty/location?alias=1234']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/location?alias=1234']! + .call({}), response.map((i) => i.toJson()).toList(), ); @@ -1571,7 +1591,8 @@ void main() { final response = await matrixApi.queryUserByID('1234'); expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user?userid=1234']({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user?userid=1234']! + .call({}), response.map((i) => i.toJson()).toList(), ); @@ -1583,8 +1604,8 @@ void main() { final response = await matrixApi.requestOpenIdToken('1234', {}); expect( - FakeMatrixApi - .api['POST']!['/client/v3/user/1234/openid/request_token']({}), + FakeMatrixApi.api['POST']!['/client/v3/user/1234/openid/request_token']! + .call({}), response.toJson(), ); @@ -1609,8 +1630,8 @@ void main() { }; final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); expect( - FakeMatrixApi - .api['POST']!['/client/v3/room_keys/version']({})['version'], + (FakeMatrixApi.api['POST']!['/client/v3/room_keys/version']!.call({}) + as Map)['version'], ret); }); test('getRoomKeysVersionCurrent', () async { @@ -1618,7 +1639,8 @@ void main() { matrixApi.accessToken = '1234'; final ret = await matrixApi.getRoomKeysVersionCurrent(); - expect(FakeMatrixApi.api['GET']!['/client/v3/room_keys/version']({}), + expect( + FakeMatrixApi.api['GET']!['/client/v3/room_keys/version']!.call({}), ret.toJson()); }); test('putRoomKeysVersion', () async { @@ -1659,7 +1681,8 @@ void main() { roomId, sessionId, '5', session); expect( FakeMatrixApi.api['PUT']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! + .call({}), ret.toJson()); }); test('getRoomKeyBySessionId', () async { @@ -1671,7 +1694,8 @@ void main() { final ret = await matrixApi.getRoomKeyBySessionId(roomId, sessionId, '5'); expect( FakeMatrixApi.api['GET']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! + .call({}), ret.toJson()); }); test('deleteRoomKeyBySessionId', () async { @@ -1684,7 +1708,8 @@ void main() { await matrixApi.deleteRoomKeyBySessionId(roomId, sessionId, '5'); expect( FakeMatrixApi.api['DELETE']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! + .call({}), ret.toJson()); }); test('putRoomKeysByRoomId', () async { @@ -1711,7 +1736,8 @@ void main() { final ret = await matrixApi.putRoomKeysByRoomId(roomId, '5', session); expect( FakeMatrixApi.api['PUT']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! + .call({}), ret.toJson()); }); test('getRoomKeysByRoomId', () async { @@ -1722,7 +1748,8 @@ void main() { final ret = await matrixApi.getRoomKeysByRoomId(roomId, '5'); expect( FakeMatrixApi.api['GET']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! + .call({}), ret.toJson()); }); test('deleteRoomKeysByRoomId', () async { @@ -1733,7 +1760,8 @@ void main() { final ret = await matrixApi.deleteRoomKeysByRoomId(roomId, '5'); expect( FakeMatrixApi.api['DELETE']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']({}), + '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! + .call({}), ret.toJson()); }); test('putRoomKeys', () async { @@ -1763,7 +1791,8 @@ void main() { }); final ret = await matrixApi.putRoomKeys('5', session); expect( - FakeMatrixApi.api['PUT']!['/client/v3/room_keys/keys?version=5']({}), + FakeMatrixApi.api['PUT']!['/client/v3/room_keys/keys?version=5']! + .call({}), ret.toJson()); }); test('getRoomKeys', () async { @@ -1772,7 +1801,8 @@ void main() { final ret = await matrixApi.getRoomKeys('5'); expect( - FakeMatrixApi.api['GET']!['/client/v3/room_keys/keys?version=5']({}), + FakeMatrixApi.api['GET']!['/client/v3/room_keys/keys?version=5']! + .call({}), ret.toJson()); }); test('deleteRoomKeys', () async { @@ -1781,8 +1811,8 @@ void main() { final ret = await matrixApi.deleteRoomKeys('5'); expect( - FakeMatrixApi - .api['DELETE']!['/client/v3/room_keys/keys?version=5']({}), + FakeMatrixApi.api['DELETE']!['/client/v3/room_keys/keys?version=5']! + .call({}), ret.toJson()); }); test('AuthenticationData', () { From 5bd934895ddfa3926f8fbb82337ff7a5680f8897 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 20 Aug 2022 11:53:14 +0200 Subject: [PATCH 131/174] chore: strict inference --- analysis_options.yaml | 4 + lib/fake_matrix_api.dart | 207 ++++++++++-------- .../events/room_key_request_content.dart | 5 +- .../events/secret_storage_key_content.dart | 5 +- test/event_content_test.dart | 2 +- test/matrix_api_test.dart | 123 ++++++----- 6 files changed, 193 insertions(+), 153 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 24559023..2de344a5 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -10,6 +10,10 @@ linter: avoid_dynamic_calls: true analyzer: + language: + strict-casts: false + strict-inference: true + strict-raw-types: false errors: todo: ignore exclude: diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index bc4e5fe2..152eb8c4 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -64,14 +64,14 @@ class FakeMatrixApi extends MockClient { final method = request.method; final dynamic data = method == 'GET' ? request.url.queryParameters : request.body; - dynamic res = {}; + dynamic res = {}; var statusCode = 200; //print('\$method request to $action with Data: $data'); // Sync requests with timeout if (data is Map && data['timeout'] is String) { - await Future.delayed(Duration(seconds: 5)); + await Future.delayed(Duration(seconds: 5)); } if (request.url.origin != 'https://fakeserver.notexisting') { @@ -91,7 +91,7 @@ class FakeMatrixApi extends MockClient { } } else if (method == 'PUT' && action.contains('/client/v3/sendToDevice/')) { - res = {}; + res = {}; } else if (method == 'GET' && action.contains('/client/v3/rooms/') && action.contains('/state/m.room.member/')) { @@ -171,7 +171,7 @@ class FakeMatrixApi extends MockClient { 'unsigned': {'age': 1234} } ], - 'state': [], + 'state': [], }; static Map syncResponse = { @@ -393,7 +393,7 @@ class FakeMatrixApi extends MockClient { 'override': [ { 'actions': ['dont_notify'], - 'conditions': [], + 'conditions': [], 'default': true, 'enabled': false, 'rule_id': '.m.rule.master' @@ -427,7 +427,7 @@ class FakeMatrixApi extends MockClient { 'rule_id': '!localpart:server.abc' } ], - 'sender': [], + 'sender': [], 'underride': [ { 'actions': [ @@ -677,12 +677,12 @@ class FakeMatrixApi extends MockClient { static Map archiveSyncResponse = { 'next_batch': Random().nextDouble().toString(), - 'presence': {'events': []}, - 'account_data': {'events': []}, - 'to_device': {'events': []}, + 'presence': {'events': []}, + 'account_data': {'events': []}, + 'to_device': {'events': []}, 'rooms': { - 'join': {}, - 'invite': {}, + 'join': {}, + 'invite': {}, 'leave': { '!5345234234:example.com': { 'timeline': { @@ -727,7 +727,7 @@ class FakeMatrixApi extends MockClient { }, }, '!5345234235:example.com': { - 'timeline': {'events': []}, + 'timeline': {'events': []}, 'state': { 'events': [ { @@ -863,7 +863,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': [] + 'children_state': [] }, { 'room_id': '!aZUzMIEZvEwnDquxLf:neko.dev', @@ -876,7 +876,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': [] + 'children_state': [] }, { 'room_id': '!aRzRZBvOAkHMcEjAPS:libera.chat', @@ -888,7 +888,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': [] + 'children_state': [] }, { 'room_id': '!DXsRRxkqqDhDkAyXfL:matrix.org', @@ -901,7 +901,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': [] + 'children_state': [] }, { 'room_id': '!tbCRpmsMiwMBlIThOd:matrix.org', @@ -913,7 +913,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': [] + 'children_state': [] }, { 'room_id': '!LPpmvMsEgDwuSuHSpM:matrix.org', @@ -925,7 +925,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': [] + 'children_state': [] }, { 'room_id': '!prlZxmnmAGuCYHUNSw:neko.dev', @@ -938,7 +938,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': false, - 'children_state': [] + 'children_state': [] }, { 'room_id': '!ooHixUOgoLVUjCSMZC:matrix.org', @@ -950,7 +950,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': [] + 'children_state': [] } ] }; @@ -982,7 +982,7 @@ class FakeMatrixApi extends MockClient { 'tags': { 'm.favourite': {'order': 0.1}, 'u.Work': {'order': 0.7}, - 'u.Customers': {} + 'u.Customers': {}, } }, '/client/v3/events?from=1234&timeout=10&room_id=%211234': (var req) => { @@ -1092,7 +1092,7 @@ class FakeMatrixApi extends MockClient { 'network_id': 'gitter', 'desc': 'Gitter', 'icon': 'mxc://example.org/zXyWvUt', - 'fields': {} + 'fields': {} } ] } @@ -1610,7 +1610,7 @@ class FakeMatrixApi extends MockClient { 'override': [ { 'actions': ['dont_notify'], - 'conditions': [], + 'conditions': [], 'default': true, 'enabled': false, 'rule_id': '.m.rule.master' @@ -1629,8 +1629,8 @@ class FakeMatrixApi extends MockClient { 'rule_id': '.m.rule.suppress_notices' } ], - 'room': [], - 'sender': [], + 'room': [], + 'sender': [], 'underride': [ { 'actions': [ @@ -1780,7 +1780,7 @@ class FakeMatrixApi extends MockClient { 'algorithm': AlgorithmTypes.megolmBackupV1Curve25519AesSha2, 'auth_data': { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', - 'signatures': {}, + 'signatures': {}, }, 'count': 0, 'etag': '0', @@ -1839,15 +1839,15 @@ class FakeMatrixApi extends MockClient { (var req) => spaceHierarchyResponse, }, 'POST': { - '/client/v3/delete_devices': (var req) => {}, - '/client/v3/account/3pid/add': (var req) => {}, - '/client/v3/account/3pid/bind': (var req) => {}, + '/client/v3/delete_devices': (var req) => {}, + '/client/v3/account/3pid/add': (var req) => {}, + '/client/v3/account/3pid/bind': (var req) => {}, '/client/v3/account/3pid/delete': (var req) => {'id_server_unbind_result': 'success'}, '/client/v3/account/3pid/unbind': (var req) => {'id_server_unbind_result': 'success'}, - '/client/v3/account/password': (var req) => {}, - '/client/v3/rooms/1234/report/1234': (var req) => {}, + '/client/v3/account/password': (var req) => {}, + '/client/v3/rooms/1234/report/1234': (var req) => {}, '/client/v3/search': (var req) => { 'search_categories': { 'room_events': { @@ -1923,8 +1923,9 @@ class FakeMatrixApi extends MockClient { 'submit_url': 'https://example.org/path/to/submitToken' }, '/client/v3/rooms/!localpart%3Aexample.com/receipt/m.read/%241234%3Aexample.com': - (var req) => {}, - '/client/v3/rooms/!localpart%3Aexample.com/read_markers': (var req) => {}, + (var req) => {}, + '/client/v3/rooms/!localpart%3Aexample.com/read_markers': (var req) => + {}, '/client/v3/user/${Uri.encodeComponent('alice@example.com')}/filter': (var req) => {'filter_id': '1234'}, '/client/v3/publicRooms?server=example.com': (var req) => { @@ -1950,7 +1951,7 @@ class FakeMatrixApi extends MockClient { ? request["one_time_keys"] as Map? : null; return { - 'failures': {}, + 'failures': {}, 'one_time_keys': { if (keys?['@alice:example.com'] != null) '@alice:example.com': { @@ -1983,13 +1984,20 @@ class FakeMatrixApi extends MockClient { } }; }, - '/client/v3/rooms/!localpart%3Aexample.com/invite': (var req) => {}, - '/client/v3/rooms/!localpart%3Aexample.com/leave': (var req) => {}, - '/client/v3/rooms/!localpart%3Aexample.com/forget': (var req) => {}, - '/client/v3/rooms/!localpart%3Aserver.abc/kick': (var req) => {}, - '/client/v3/rooms/!localpart%3Aexample.com/kick': (var req) => {}, - '/client/v3/rooms/!localpart%3Aexample.com/ban': (var req) => {}, - '/client/v3/rooms/!localpart%3Aexample.com/unban': (var req) => {}, + '/client/v3/rooms/!localpart%3Aexample.com/invite': (var req) => + {}, + '/client/v3/rooms/!localpart%3Aexample.com/leave': (var req) => + {}, + '/client/v3/rooms/!localpart%3Aexample.com/forget': (var req) => + {}, + '/client/v3/rooms/!localpart%3Aserver.abc/kick': (var req) => + {}, + '/client/v3/rooms/!localpart%3Aexample.com/kick': (var req) => + {}, + '/client/v3/rooms/!localpart%3Aexample.com/ban': (var req) => + {}, + '/client/v3/rooms/!localpart%3Aexample.com/unban': (var req) => + {}, '/client/v3/rooms/!localpart%3Aexample.com/join': (var req) => {'room_id': '!localpart:example.com'}, '/client/v3/join/!localpart%3Aexample.com?server_name=example.com&server_name=example.abc': @@ -2005,7 +2013,7 @@ class FakeMatrixApi extends MockClient { } }, '/client/v3/keys/query': (var req) => { - 'failures': {}, + 'failures': {}, 'device_keys': { '@alice:example.com': { 'JLAFKJWSCS': { @@ -2127,7 +2135,7 @@ class FakeMatrixApi extends MockClient { 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8', }, - 'signatures': {}, + 'signatures': {}, }, '@othertest:fakeServer.notExisting': { 'user_id': '@othertest:fakeServer.notExisting', @@ -2135,7 +2143,7 @@ class FakeMatrixApi extends MockClient { 'keys': { 'ed25519:master': 'master', }, - 'signatures': {}, + 'signatures': {}, }, }, 'self_signing_keys': { @@ -2159,7 +2167,7 @@ class FakeMatrixApi extends MockClient { 'keys': { 'ed25519:self_signing': 'self_signing', }, - 'signatures': {}, + 'signatures': {}, }, }, 'user_signing_keys': { @@ -2183,7 +2191,7 @@ class FakeMatrixApi extends MockClient { 'keys': { 'ed25519:user_signing': 'user_signing', }, - 'signatures': {}, + 'signatures': {}, }, }, }, @@ -2223,55 +2231,64 @@ class FakeMatrixApi extends MockClient { }, '/media/v3/upload?filename=file.jpeg': (var req) => {'content_uri': 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'}, - '/client/v3/logout': (var reqI) => {}, - '/client/v3/pushers/set': (var reqI) => {}, + '/client/v3/logout': (var reqI) => {}, + '/client/v3/pushers/set': (var reqI) => {}, '/client/v3/join/1234': (var reqI) => {'room_id': '1234'}, - '/client/v3/logout/all': (var reqI) => {}, + '/client/v3/logout/all': (var reqI) => {}, '/client/v3/createRoom': (var reqI) => { 'room_id': '!1234:fakeServer.notExisting', }, - '/client/v3/rooms/!localpart%3Aserver.abc/read_markers': (var reqI) => {}, - '/client/v3/rooms/!localpart:server.abc/kick': (var reqI) => {}, - '/client/v3/rooms/!localpart%3Aserver.abc/ban': (var reqI) => {}, - '/client/v3/rooms/!localpart%3Aserver.abc/unban': (var reqI) => {}, - '/client/v3/rooms/!localpart%3Aserver.abc/invite': (var reqI) => {}, + '/client/v3/rooms/!localpart%3Aserver.abc/read_markers': (var reqI) => + {}, + '/client/v3/rooms/!localpart:server.abc/kick': (var reqI) => + {}, + '/client/v3/rooms/!localpart%3Aserver.abc/ban': (var reqI) => + {}, + '/client/v3/rooms/!localpart%3Aserver.abc/unban': (var reqI) => + {}, + '/client/v3/rooms/!localpart%3Aserver.abc/invite': (var reqI) => + {}, '/client/v3/keys/device_signing/upload': (var reqI) { - return {}; + return {}; }, - '/client/v3/keys/signatures/upload': (var reqI) => {'failures': {}}, + '/client/v3/keys/signatures/upload': (var reqI) => + {'failures': {}}, '/client/v3/room_keys/version': (var reqI) => {'version': '5'}, }, 'PUT': { '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/m.ignored_user_list': - (var req) => {}, + (var req) => {}, '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status': - (var req) => {}, - '/client/v3/pushrules/global/content/nocake/enabled': (var req) => {}, - '/client/v3/pushrules/global/content/nocake/actions': (var req) => {}, + (var req) => {}, + '/client/v3/pushrules/global/content/nocake/enabled': (var req) => + {}, + '/client/v3/pushrules/global/content/nocake/actions': (var req) => + {}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.history_visibility': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.join_rules': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.guest_access': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.invite/1234': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.answer/1234': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.candidates/1234': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.hangup/1234': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!1234%3Aexample.com/redact/1143273582443PhrSn%3Aexample.org/1234': (var req) => {'event_id': '1234'}, '/client/v3/pushrules/global/room/!localpart%3Aserver.abc': (var req) => - {}, + {}, '/client/v3/pushrules/global/override/.m.rule.master/enabled': - (var req) => {}, + (var req) => {}, '/client/v3/pushrules/global/content/nocake?before=1&after=2': - (var req) => {}, - '/client/v3/devices/QBUAZIFURK': (var req) => {}, - '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => {}, + (var req) => {}, + '/client/v3/devices/QBUAZIFURK': (var req) => {}, + '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => + {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.room.message/testtxid': (var reqI) => { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', @@ -2281,7 +2298,7 @@ class FakeMatrixApi extends MockClient { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', }, '/client/v3/rooms/!localpart%3Aexample.com/typing/%40alice%3Aexample.com': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!1234%3Aexample.com/send/m.room.message/1234': (var reqI) => { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', @@ -2291,25 +2308,27 @@ class FakeMatrixApi extends MockClient { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', }, '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40alice%3Aexample.com/account_data/test.account.data': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/best%20animal': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/account_data/com.famedly.marked_unread': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/m.direct': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40othertest%3AfakeServer.notExisting/account_data/m.direct': - (var req) => {}, - '/client/v3/profile/%40alice%3Aexample.com/displayname': (var reqI) => {}, - '/client/v3/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => {}, + (var req) => {}, + '/client/v3/profile/%40alice%3Aexample.com/displayname': (var reqI) => + {}, + '/client/v3/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => + {}, '/client/v3/profile/%40test%3AfakeServer.notExisting/avatar_url': - (var reqI) => {}, + (var reqI) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.encryption': (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.avatar': @@ -2335,8 +2354,8 @@ class FakeMatrixApi extends MockClient { 'event_id': '42', }, '/client/v3/directory/list/room/!localpart%3Aexample.com': (var req) => - {}, - '/client/v3/room_keys/version/5': (var req) => {}, + {}, + '/client/v3/room_keys/version/5': (var req) => {}, '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': (var req) => { 'etag': 'asdf', @@ -2354,16 +2373,18 @@ class FakeMatrixApi extends MockClient { }, 'DELETE': { '/unknown/token': (var req) => {'errcode': 'M_UNKNOWN_TOKEN'}, - '/client/v3/devices/QBUAZIFURK': (var req) => {}, - '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => {}, - '/client/v3/pushrules/global/content/nocake': (var req) => {}, + '/client/v3/devices/QBUAZIFURK': (var req) => {}, + '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => + {}, + '/client/v3/pushrules/global/content/nocake': (var req) => + {}, '/client/v3/pushrules/global/override/!localpart%3Aserver.abc': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': - (var req) => {}, - '/client/v3/room_keys/version/5': (var req) => {}, + (var req) => {}, + '/client/v3/room_keys/version/5': (var req) => {}, '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': (var req) => { 'etag': 'asdf', diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index 5599cc03..bddaeff3 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -36,8 +36,9 @@ class RoomKeyRequestContent { String requestId; RoomKeyRequestContent.fromJson(Map json) - : body = ((x) => x != null ? RequestedKeyInfo.fromJson(x) : null)( - json.tryGet('body')), + : body = ((Map? x) => x != null + ? RequestedKeyInfo.fromJson(x) + : null)(json.tryGet('body')), action = json.tryGet('action', TryGet.required) ?? '', requestingDeviceId = json.tryGet('requesting_device_id', TryGet.required) ?? '', diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index d748da34..5f3529e3 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -38,8 +38,9 @@ class SecretStorageKeyContent { SecretStorageKeyContent(); SecretStorageKeyContent.fromJson(Map json) - : passphrase = ((x) => x != null ? PassphraseInfo.fromJson(x) : null)( - json.tryGet('passphrase')), + : passphrase = ((Map? x) => x != null + ? PassphraseInfo.fromJson(x) + : null)(json.tryGet('passphrase')), iv = json.tryGet('iv'), mac = json.tryGet('mac'), algorithm = json.tryGet('algorithm'); diff --git a/test/event_content_test.dart b/test/event_content_test.dart index 67fe9cc9..0c5ede11 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -238,7 +238,7 @@ void main() { 'type': 'some type', 'content': { 'images': { - 'emote': {}, + 'emote': {}, }, }, }; diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index af7de7c6..98331e3c 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -27,6 +27,8 @@ import 'package:matrix_api_lite/fake_matrix_api.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; +const emptyRequest = {}; + void main() { /// All Tests related to device keys group('Matrix API', () { @@ -123,7 +125,7 @@ void main() { final supportedVersions = await matrixApi.getVersions(); expect(supportedVersions.versions.contains('r0.5.0'), true); expect(supportedVersions.unstableFeatures!['m.lazy_load_members'], true); - expect(FakeMatrixApi.api['GET']!['/client/versions']!.call({}), + expect(FakeMatrixApi.api['GET']!['/client/versions']!.call(emptyRequest), supportedVersions.toJson()); matrixApi.homeserver = null; }); @@ -146,7 +148,7 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); final loginTypes = await matrixApi.getLoginFlows(); expect(loginTypes?.first.type, 'm.login.password'); - expect(FakeMatrixApi.api['GET']!['/client/v3/login']!.call({}), + expect(FakeMatrixApi.api['GET']!['/client/v3/login']!.call(emptyRequest), {'flows': loginTypes?.map((x) => x.toJson()).toList()}); matrixApi.homeserver = null; }); @@ -156,7 +158,7 @@ void main() { LoginType.mLoginPassword, identifier: AuthenticationUserIdentifier(user: 'username'), ); - expect(FakeMatrixApi.api['POST']!['/client/v3/login']!.call({}), + expect(FakeMatrixApi.api['POST']!['/client/v3/login']!.call(emptyRequest), loginResponse.toJson()); matrixApi.homeserver = null; }); @@ -178,7 +180,7 @@ void main() { await matrixApi.register(kind: AccountKind.guest, username: 'test'); expect( FakeMatrixApi.api['POST']!['/client/v3/register?kind=guest']! - .call({}), + .call(emptyRequest), registerResponse.toJson()); matrixApi.homeserver = null; }); @@ -195,7 +197,7 @@ void main() { ); expect( FakeMatrixApi.api['POST']!['/client/v3/register/email/requestToken']! - .call({}), + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -213,7 +215,7 @@ void main() { ); expect( FakeMatrixApi.api['POST']!['/client/v3/register/email/requestToken']! - .call({}), + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -282,7 +284,9 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getAccount3PIDs(); - expect(FakeMatrixApi.api['GET']!['/client/v3/account/3pid']!.call({}), + expect( + FakeMatrixApi.api['GET']!['/client/v3/account/3pid']! + .call(emptyRequest), {'threepids': response?.map((t) => t.toJson()).toList()}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -364,7 +368,9 @@ void main() { matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); matrixApi.accessToken = '1234'; final response = await matrixApi.getCapabilities(); - expect(FakeMatrixApi.api['GET']!['/client/v3/capabilities']!.call({}), + expect( + FakeMatrixApi.api['GET']!['/client/v3/capabilities']! + .call(emptyRequest), {'capabilities': response.toJson()}); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -428,8 +434,8 @@ void main() { 'types': ['type1'], }, 'include_leave': true, - 'state': {}, - 'timeline': {}, + 'state': {}, + 'timeline': {}, }, 'presence': { 'limit': 10, @@ -500,7 +506,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15']! - .call({}) as Map?, + .call(emptyRequest) as Map?, response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; }); @@ -578,7 +584,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']! - .call({}) as Map?, + .call(emptyRequest) as Map?, timelineHistoryResponse.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -669,7 +675,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/directory/room/%23testalias%3Aexample.com']! - .call({}), + .call(emptyRequest), roomAliasInformation.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -832,7 +838,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/publicRooms?limit=10&since=1234&server=example.com']! - .call({}), + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -855,7 +861,7 @@ void main() { expect( FakeMatrixApi .api['POST']!['/client/v3/publicRooms?server=example.com']! - .call({}), + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -870,7 +876,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v1/rooms/${Uri.encodeComponent('!gPxZhKUssFZKZcoCKY:neko.dev')}/hierarchy']! - .call({}), + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -886,7 +892,7 @@ void main() { expect( FakeMatrixApi.api['POST']!['/client/v3/user_directory/search']! - .call({}), + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -935,7 +941,7 @@ void main() { expect( FakeMatrixApi .api['GET']!['/client/v3/profile/%40alice%3Aexample.com']! - .call({}), + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -945,7 +951,9 @@ void main() { matrixApi.accessToken = '1234'; final response = await matrixApi.getTurnServer(); - expect(FakeMatrixApi.api['GET']!['/client/v3/voip/turnServer']!.call({}), + expect( + FakeMatrixApi.api['GET']!['/client/v3/voip/turnServer']! + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1010,7 +1018,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status']! - .call({}), + .call(emptyRequest), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1041,7 +1049,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/media/v3/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']! - .call({}), + .call(emptyRequest), openGraphData.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1073,7 +1081,7 @@ void main() { final devices = await matrixApi.getDevices(); expect( - (FakeMatrixApi.api['GET']!['/client/v3/devices']!.call({}) + (FakeMatrixApi.api['GET']!['/client/v3/devices']!.call(emptyRequest) as Map?)?['devices'], devices?.map((i) => i.toJson()).toList()); @@ -1145,7 +1153,7 @@ void main() { 'Alices mobile phone'); expect( FakeMatrixApi.api['POST']!['/client/v3/keys/query']! - .call({'device_keys': {}}), + .call({'device_keys': emptyRequest}), response.toJson()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1189,7 +1197,7 @@ void main() { 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8', }, - 'signatures': {}, + 'signatures': {}, }); final selfSigningKey = MatrixCrossSigningKey.fromJson({ 'user_id': '@test:fakeServer.notExisting', @@ -1198,7 +1206,7 @@ void main() { 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': 'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY', }, - 'signatures': {}, + 'signatures': {}, }); final userSigningKey = MatrixCrossSigningKey.fromJson({ 'user_id': '@test:fakeServer.notExisting', @@ -1207,7 +1215,7 @@ void main() { 'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g': '0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g', }, - 'signatures': {}, + 'signatures': {}, }); await matrixApi.uploadCrossSigningKeys( masterKey: masterKey, @@ -1220,7 +1228,8 @@ void main() { final response = await matrixApi.getPushers(); expect( - FakeMatrixApi.api['GET']!['/client/v3/pushers']!.call({}), + FakeMatrixApi.api['GET']!['/client/v3/pushers']! + .call({}), {'pushers': response?.map((i) => i.toJson()).toList()}, ); @@ -1259,7 +1268,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/notifications?from=1234&limit=10&only=1234']! - .call({}), + .call({}), response.toJson(), ); @@ -1271,7 +1280,8 @@ void main() { final response = await matrixApi.getPushRules(); expect( - FakeMatrixApi.api['GET']!['/client/v3/pushrules']!.call({}), + FakeMatrixApi.api['GET']!['/client/v3/pushrules']! + .call({}), {'global': response.toJson()}, ); @@ -1285,7 +1295,7 @@ void main() { await matrixApi.getPushRule('global', PushRuleKind.content, 'nocake'); expect( FakeMatrixApi.api['GET']!['/client/v3/pushrules/global/content/nocake']! - .call({}), + .call({}), response.toJson(), ); @@ -1386,7 +1396,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/events?from=1234&timeout=10&room_id=%211234']! - .call({}), + .call({}), response.toJson(), ); @@ -1401,7 +1411,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']! - .call({}), + .call({}), {'tags': response?.map((k, v) => MapEntry(k, v.toJson()))}, ); @@ -1488,7 +1498,7 @@ void main() { expect( FakeMatrixApi .api['GET']!['/client/v3/admin/whois/%40alice%3Aexample.com']! - .call({}), + .call(emptyRequest), response.toJson(), ); @@ -1503,7 +1513,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/rooms/1234/context/1234?limit=10&filter=%7B%7D']! - .call({}), + .call(emptyRequest), response.toJson(), ); @@ -1528,7 +1538,8 @@ void main() { final response = await matrixApi.getProtocols(); expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocols']!.call({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocols']! + .call(emptyRequest), response.map((k, v) => MapEntry(k, v.toJson())), ); @@ -1541,7 +1552,7 @@ void main() { final response = await matrixApi.getProtocolMetadata('irc'); expect( FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocol/irc']! - .call({}), + .call(emptyRequest), response.toJson(), ); @@ -1554,7 +1565,7 @@ void main() { final response = await matrixApi.queryLocationByProtocol('irc'); expect( FakeMatrixApi.api['GET']!['/client/v3/thirdparty/location/irc']! - .call({}), + .call(emptyRequest), response.map((i) => i.toJson()).toList(), ); @@ -1566,7 +1577,8 @@ void main() { final response = await matrixApi.queryUserByProtocol('irc'); expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user/irc']!.call({}), + FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user/irc']! + .call(emptyRequest), response.map((i) => i.toJson()).toList(), ); @@ -1579,7 +1591,7 @@ void main() { final response = await matrixApi.queryLocationByAlias('1234'); expect( FakeMatrixApi.api['GET']!['/client/v3/thirdparty/location?alias=1234']! - .call({}), + .call(emptyRequest), response.map((i) => i.toJson()).toList(), ); @@ -1592,7 +1604,7 @@ void main() { final response = await matrixApi.queryUserByID('1234'); expect( FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user?userid=1234']! - .call({}), + .call(emptyRequest), response.map((i) => i.toJson()).toList(), ); @@ -1605,7 +1617,7 @@ void main() { final response = await matrixApi.requestOpenIdToken('1234', {}); expect( FakeMatrixApi.api['POST']!['/client/v3/user/1234/openid/request_token']! - .call({}), + .call(emptyRequest), response.toJson(), ); @@ -1626,12 +1638,12 @@ void main() { final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; final authData = { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', - 'signatures': {}, + 'signatures': {}, }; final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); expect( - (FakeMatrixApi.api['POST']!['/client/v3/room_keys/version']!.call({}) - as Map)['version'], + (FakeMatrixApi.api['POST']!['/client/v3/room_keys/version']! + .call(emptyRequest) as Map)['version'], ret); }); test('getRoomKeysVersionCurrent', () async { @@ -1640,7 +1652,8 @@ void main() { final ret = await matrixApi.getRoomKeysVersionCurrent(); expect( - FakeMatrixApi.api['GET']!['/client/v3/room_keys/version']!.call({}), + FakeMatrixApi.api['GET']!['/client/v3/room_keys/version']! + .call(emptyRequest), ret.toJson()); }); test('putRoomKeysVersion', () async { @@ -1650,7 +1663,7 @@ void main() { final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; final authData = { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', - 'signatures': {}, + 'signatures': {}, }; await matrixApi.putRoomKeysVersion('5', algorithm, authData); }); @@ -1682,7 +1695,7 @@ void main() { expect( FakeMatrixApi.api['PUT']![ '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('getRoomKeyBySessionId', () async { @@ -1695,7 +1708,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('deleteRoomKeyBySessionId', () async { @@ -1709,7 +1722,7 @@ void main() { expect( FakeMatrixApi.api['DELETE']![ '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('putRoomKeysByRoomId', () async { @@ -1737,7 +1750,7 @@ void main() { expect( FakeMatrixApi.api['PUT']![ '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('getRoomKeysByRoomId', () async { @@ -1749,7 +1762,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('deleteRoomKeysByRoomId', () async { @@ -1761,7 +1774,7 @@ void main() { expect( FakeMatrixApi.api['DELETE']![ '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('putRoomKeys', () async { @@ -1792,7 +1805,7 @@ void main() { final ret = await matrixApi.putRoomKeys('5', session); expect( FakeMatrixApi.api['PUT']!['/client/v3/room_keys/keys?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('getRoomKeys', () async { @@ -1802,7 +1815,7 @@ void main() { final ret = await matrixApi.getRoomKeys('5'); expect( FakeMatrixApi.api['GET']!['/client/v3/room_keys/keys?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('deleteRoomKeys', () async { @@ -1812,7 +1825,7 @@ void main() { final ret = await matrixApi.deleteRoomKeys('5'); expect( FakeMatrixApi.api['DELETE']!['/client/v3/room_keys/keys?version=5']! - .call({}), + .call(emptyRequest), ret.toJson()); }); test('AuthenticationData', () { From 6a225e3b8cc120f98b677b317c640d67cb8c53e8 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 20 Aug 2022 11:56:34 +0200 Subject: [PATCH 132/174] chore: strict raw types --- analysis_options.yaml | 2 +- lib/fake_matrix_api.dart | 40 ++++++++++++++-------------- test/try_get_map_extension_test.dart | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 2de344a5..09e9d99d 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -13,7 +13,7 @@ analyzer: language: strict-casts: false strict-inference: true - strict-raw-types: false + strict-raw-types: true errors: todo: ignore exclude: diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 152eb8c4..3d7f420b 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -171,7 +171,7 @@ class FakeMatrixApi extends MockClient { 'unsigned': {'age': 1234} } ], - 'state': [], + 'state': >[], }; static Map syncResponse = { @@ -393,7 +393,7 @@ class FakeMatrixApi extends MockClient { 'override': [ { 'actions': ['dont_notify'], - 'conditions': [], + 'conditions': >[], 'default': true, 'enabled': false, 'rule_id': '.m.rule.master' @@ -427,7 +427,7 @@ class FakeMatrixApi extends MockClient { 'rule_id': '!localpart:server.abc' } ], - 'sender': [], + 'sender': >[], 'underride': [ { 'actions': [ @@ -677,12 +677,12 @@ class FakeMatrixApi extends MockClient { static Map archiveSyncResponse = { 'next_batch': Random().nextDouble().toString(), - 'presence': {'events': []}, - 'account_data': {'events': []}, - 'to_device': {'events': []}, + 'presence': {'events': >[]}, + 'account_data': {'events': >[]}, + 'to_device': {'events': >[]}, 'rooms': { - 'join': {}, - 'invite': {}, + 'join': {}, + 'invite': {}, 'leave': { '!5345234234:example.com': { 'timeline': { @@ -727,7 +727,7 @@ class FakeMatrixApi extends MockClient { }, }, '!5345234235:example.com': { - 'timeline': {'events': []}, + 'timeline': {'events': >[]}, 'state': { 'events': [ { @@ -863,7 +863,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': [] + 'children_state': >[] }, { 'room_id': '!aZUzMIEZvEwnDquxLf:neko.dev', @@ -876,7 +876,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': [] + 'children_state': >[] }, { 'room_id': '!aRzRZBvOAkHMcEjAPS:libera.chat', @@ -888,7 +888,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': [] + 'children_state': >[] }, { 'room_id': '!DXsRRxkqqDhDkAyXfL:matrix.org', @@ -901,7 +901,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': [] + 'children_state': >[] }, { 'room_id': '!tbCRpmsMiwMBlIThOd:matrix.org', @@ -913,7 +913,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': [] + 'children_state': >[] }, { 'room_id': '!LPpmvMsEgDwuSuHSpM:matrix.org', @@ -925,7 +925,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': [] + 'children_state': >[] }, { 'room_id': '!prlZxmnmAGuCYHUNSw:neko.dev', @@ -938,7 +938,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': false, - 'children_state': [] + 'children_state': >[] }, { 'room_id': '!ooHixUOgoLVUjCSMZC:matrix.org', @@ -950,7 +950,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': [] + 'children_state': >[] } ] }; @@ -1610,7 +1610,7 @@ class FakeMatrixApi extends MockClient { 'override': [ { 'actions': ['dont_notify'], - 'conditions': [], + 'conditions': >[], 'default': true, 'enabled': false, 'rule_id': '.m.rule.master' @@ -1629,8 +1629,8 @@ class FakeMatrixApi extends MockClient { 'rule_id': '.m.rule.suppress_notices' } ], - 'room': [], - 'sender': [], + 'room': >[], + 'sender': >[], 'underride': [ { 'actions': [ diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index 7fe70c28..c31e78e4 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -39,7 +39,7 @@ void main() { expect(data.tryGet('str'), 'foxies'); expect(data.tryGet('str'), null); expect(data.tryGet('int'), 42); - expect(data.tryGet('list'), [2, 3, 4]); + expect(data.tryGet>('list'), [2, 3, 4]); expect(data.tryGetMap('map')?.tryGet('beep'), 'boop'); expect( From a525bb120a90a93742520e474efbda2461b9d9d3 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 20 Aug 2022 17:26:16 +0200 Subject: [PATCH 133/174] chore: strict casts --- analysis_options.yaml | 2 +- lib/fake_matrix_api.dart | 4 +- lib/src/matrix_api.dart | 7 +- lib/src/model/auth/authentication_data.dart | 4 +- .../model/auth/authentication_identifier.dart | 2 +- .../model/auth/authentication_password.dart | 5 +- .../auth/authentication_phone_identifier.dart | 4 +- .../model/auth/authentication_recaptcha.dart | 2 +- ...authentication_third_party_identifier.dart | 4 +- .../auth/authentication_three_pid_creds.dart | 8 +- lib/src/model/auth/authentication_token.dart | 4 +- .../auth/authentication_user_identifier.dart | 2 +- lib/src/model/basic_event.dart | 2 +- lib/src/model/basic_event_with_sender.dart | 2 +- lib/src/model/basic_room_event.dart | 2 +- lib/src/model/children_state.dart | 4 +- lib/src/model/events/image_pack_content.dart | 12 +- .../model/events/room_encrypted_content.dart | 7 +- lib/src/model/matrix_event.dart | 10 +- lib/src/model/matrix_exception.dart | 15 +- lib/src/model/matrix_keys.dart | 21 ++- lib/src/model/presence.dart | 3 +- lib/src/model/presence_content.dart | 8 +- lib/src/model/room_keys_keys.dart | 19 ++- lib/src/model/room_summary.dart | 6 +- lib/src/model/stripped_state_event.dart | 4 +- lib/src/model/sync_update.dart | 149 ++++++++---------- lib/src/utils/try_get_map_extension.dart | 7 + test/event_content_test.dart | 24 +-- 29 files changed, 174 insertions(+), 169 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 09e9d99d..58ead17c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -11,7 +11,7 @@ linter: analyzer: language: - strict-casts: false + strict-casts: true strict-inference: true strict-raw-types: true errors: diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 3d7f420b..3a63be40 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -31,12 +31,12 @@ import 'package:matrix_api_lite/matrix_api_lite.dart'; Map decodeJson(dynamic data) { if (data is String) { - return json.decode(data); + return json.decode(data) as Map; } if (data is Map && data.isEmpty) { return {}; } - return data; + return data as Map; } T? tryCast(dynamic object) => object is T ? object : null; diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index e768c4d5..772fc58d 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -47,7 +47,10 @@ class MatrixApi extends Api { @override Never unexpectedResponse(http.BaseResponse response, Uint8List body) { if (response.statusCode >= 400 && response.statusCode < 500) { - throw MatrixException.fromJson(json.decode(utf8.decode(body))); + final resp = json.decode(utf8.decode(body)); + if (resp is Map) { + throw MatrixException.fromJson(resp); + } } super.unexpectedResponse(response, body); } @@ -164,7 +167,7 @@ class MatrixApi extends Api { }, }, ); - return Map.from(response['one_time_key_counts']); + return Map.from(response['one_time_key_counts'] as Map); } /// This endpoint allows the creation, modification and deletion of pushers diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index 02633ca3..a01faafc 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -30,8 +30,8 @@ class AuthenticationData { AuthenticationData({this.type, this.session}); AuthenticationData.fromJson(Map json) - : type = json['type'], - session = json['session']; + : type = json['type'] as String?, + session = json['session'] as String?; Map toJson() { final data = {}; diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index ada4778a..e02cf840 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -32,7 +32,7 @@ class AuthenticationIdentifier { AuthenticationIdentifier({required this.type}); AuthenticationIdentifier.fromJson(Map json) - : type = json['type']; + : type = json['type'] as String; factory AuthenticationIdentifier.subFromJson(Map json) { switch (json['type']) { diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index b47a17be..4135a535 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -41,8 +41,9 @@ class AuthenticationPassword extends AuthenticationData { ); AuthenticationPassword.fromJson(Map json) - : password = json['password'], - identifier = AuthenticationIdentifier.subFromJson(json['identifier']), + : password = json['password'] as String, + identifier = AuthenticationIdentifier.subFromJson( + json['identifier'] as Map), super.fromJson(json); @override diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index e6eb8aa6..0c79d7d3 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -32,8 +32,8 @@ class AuthenticationPhoneIdentifier extends AuthenticationIdentifier { : super(type: AuthenticationIdentifierTypes.phone); AuthenticationPhoneIdentifier.fromJson(Map json) - : country = json['country'], - phone = json['phone'], + : country = json['country'] as String, + phone = json['phone'] as String, super.fromJson(json); @override diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index 20c8d3c2..5244e16d 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -34,7 +34,7 @@ class AuthenticationRecaptcha extends AuthenticationData { ); AuthenticationRecaptcha.fromJson(Map json) - : response = json['response'], + : response = json['response'] as String, super.fromJson(json); @override diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index 2860dfdf..f40fd98b 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -33,8 +33,8 @@ class AuthenticationThirdPartyIdentifier extends AuthenticationIdentifier { : super(type: AuthenticationIdentifierTypes.thirdParty); AuthenticationThirdPartyIdentifier.fromJson(Map json) - : medium = json['medium'], - address = json['address'], + : medium = json['medium'] as String, + address = json['address'] as String, super.fromJson(json); @override diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index b6278160..a1a119de 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -66,10 +66,10 @@ class ThreepidCreds { this.idAccessToken}); ThreepidCreds.fromJson(Map json) - : sid = json['sid'], - clientSecret = json['client_secret'], - idServer = json['id_server'], - idAccessToken = json['id_access_token']; + : sid = json['sid'] as String, + clientSecret = json['client_secret'] as String, + idServer = json['id_server'] as String?, + idAccessToken = json['id_access_token'] as String?; Map toJson() { final data = {}; diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index fd9c18cd..7c86bd45 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -37,8 +37,8 @@ class AuthenticationToken extends AuthenticationData { ); AuthenticationToken.fromJson(Map json) - : token = json['token'], - txnId = json['txn_id'], + : token = json['token'] as String, + txnId = json['txn_id'] as String?, super.fromJson(json); @override diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index 9070dc48..1736c47a 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -31,7 +31,7 @@ class AuthenticationUserIdentifier extends AuthenticationIdentifier { : super(type: AuthenticationIdentifierTypes.userId); AuthenticationUserIdentifier.fromJson(Map json) - : user = json['user'], + : user = json['user'] as String, super.fromJson(json); @override diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index 5ea833f1..e91c2e80 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -33,7 +33,7 @@ class BasicEvent { }); BasicEvent.fromJson(Map json) - : type = json['type'], + : type = json['type'] as String, content = (json['content'] as Map).copy(); Map toJson() { diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index 6618fc5a..cb3a6486 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -33,7 +33,7 @@ class BasicEventWithSender extends BasicEvent { : super(type: type, content: content); BasicEventWithSender.fromJson(Map json) - : senderId = json['sender'], + : senderId = json['sender'] as String, super.fromJson(json); @override diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index 0e416483..1771e2ca 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -36,7 +36,7 @@ class BasicRoomEvent extends BasicEvent { ); BasicRoomEvent.fromJson(Map json) - : roomId = json['room_id'], + : roomId = json['room_id'] as String?, super.fromJson(json); @override diff --git a/lib/src/model/children_state.dart b/lib/src/model/children_state.dart index ed0d6c26..03b0688b 100644 --- a/lib/src/model/children_state.dart +++ b/lib/src/model/children_state.dart @@ -39,8 +39,8 @@ class ChildrenState extends StrippedStateEvent { stateKey: stateKey); ChildrenState.fromJson(Map json) - : originServerTs = - DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']), + : originServerTs = DateTime.fromMillisecondsSinceEpoch( + json['origin_server_ts'] as int), super.fromJson(json); @override diff --git a/lib/src/model/events/image_pack_content.dart b/lib/src/model/events/image_pack_content.dart index 31923917..a7cbdf37 100644 --- a/lib/src/model/events/image_pack_content.dart +++ b/lib/src/model/events/image_pack_content.dart @@ -78,15 +78,19 @@ class ImagePackContent { (e) => !['images', 'pack', 'emoticons', 'short'].contains(e.key))), pack = ImagePackPackContent.fromJson( json.tryGetMap('pack') ?? {}), - images = json.tryGetMap('images')?.catchMap( - (k, v) => MapEntry(k, ImagePackImageContent.fromJson(v))) ?? + images = json.tryGetMap('images')?.catchMap((k, v) => + MapEntry( + k, + ImagePackImageContent.fromJson( + v as Map))) ?? // the "emoticons" key needs a small migration on the key, ":string:" --> "string" json.tryGetMap('emoticons')?.catchMap((k, v) => MapEntry( k.startsWith(':') && k.endsWith(':') ? k.substring(1, k.length - 1) : k, - ImagePackImageContent.fromJson(v))) ?? + ImagePackImageContent.fromJson( + v as Map))) ?? // the "short" key was still just a map from shortcode to mxc uri json.tryGetMap('short')?.catchMap((k, v) => MapEntry( @@ -118,7 +122,7 @@ class ImagePackImageContent { ImagePackImageContent.fromJson(Map json) : _json = Map.fromEntries(json.entries .where((e) => !['url', 'body', 'info'].contains(e.key))), - url = Uri.parse(json['url']), + url = Uri.parse(json['url'] as String), body = json.tryGet('body'), info = json.tryGetMap('info'), usage = imagePackUsageFromJson(json.tryGetList('usage')); diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index a358dc9f..48dc6e24 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -49,7 +49,8 @@ class RoomEncryptedContent { // filter out invalid/incomplete CiphertextInfos ciphertextOlm = json .tryGet>('ciphertext', TryGet.silent) - ?.catchMap((k, v) => MapEntry(k, CiphertextInfo.fromJson(v))); + ?.catchMap((k, v) => MapEntry( + k, CiphertextInfo.fromJson(v as Map))); Map toJson() { final data = {}; @@ -81,8 +82,8 @@ class CiphertextInfo { int type; CiphertextInfo.fromJson(Map json) - : body = json['body'], - type = json['type']; + : body = json['body'] as String, + type = json['type'] as int; Map toJson() { final data = {}; diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index 516f4b35..b0ed6ee7 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -50,13 +50,13 @@ class MatrixEvent extends StrippedStateEvent { stateKey: stateKey); MatrixEvent.fromJson(Map json) - : eventId = json['event_id'], - roomId = json['room_id'], - originServerTs = - DateTime.fromMillisecondsSinceEpoch(json['origin_server_ts']), + : eventId = json['event_id'] as String, + roomId = json['room_id'] as String?, + originServerTs = DateTime.fromMillisecondsSinceEpoch( + json['origin_server_ts'] as int), unsigned = (json['unsigned'] as Map?)?.copy(), prevContent = (json['prev_content'] as Map?)?.copy(), - redacts = json['redacts'], + redacts = json['redacts'] as String?, super.fromJson(json); @override diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 94257427..e04aee1e 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -65,12 +65,12 @@ class MatrixException implements Exception { /// The unique identifier for this error. String get errcode => - raw['errcode'] ?? + raw['errcode'] as String? ?? (requireAdditionalAuthentication ? 'M_FORBIDDEN' : 'M_UNKNOWN'); /// A human readable error description. String get errorMessage => - raw['error'] ?? + raw['error'] as String? ?? (requireAdditionalAuthentication ? 'Require additional authentication' : 'Unknown error'); @@ -79,7 +79,7 @@ class MatrixException implements Exception { http.Response? response; MatrixException(http.Response this.response) - : raw = json.decode(response.body); + : raw = json.decode(response.body) as Map; MatrixException.fromJson(Map content) : raw = content; @@ -91,11 +91,11 @@ class MatrixException implements Exception { (e) => e.toString() == 'MatrixError.${(raw["errcode"] ?? "")}', orElse: () => MatrixError.M_UNKNOWN); - int? get retryAfterMs => raw['retry_after_ms']; + int? get retryAfterMs => raw['retry_after_ms'] as int?; /// This is a session identifier that the client must pass back to the homeserver, if one is provided, /// in subsequent attempts to authenticate in the same API call. - String? get session => raw['session']; + String? get session => raw['session'] as String?; /// Returns true if the server requires additional authentication. bool get requireAdditionalAuthentication => response != null @@ -119,11 +119,12 @@ class MatrixException implements Exception { /// This section contains any information that the client will need to know in order to use a given type /// of authentication. For each authentication type presented, that type may be present as a key in this /// dictionary. For example, the public part of an OAuth client ID could be given here. - Map? get authenticationParams => raw['params']; + Map? get authenticationParams => + raw['params'] as Map?; /// Returns the list of already completed authentication flows from previous requests. List get completedAuthenticationFlows => - List.from(raw['completed'] ?? []); + List.from(raw['completed'] as List? ?? []); } /// For each endpoint, a server offers one or more 'flows' that the client can use diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index 65f47368..432dccfc 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -21,7 +21,7 @@ * SOFTWARE. */ -import '../utils/map_copy_extension.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; abstract class MatrixSignableKey { String userId; @@ -39,14 +39,11 @@ abstract class MatrixSignableKey { MatrixSignableKey.fromJson(Map json) : _json = json, - userId = json['user_id'], - keys = Map.from(json['keys']), + userId = json['user_id'] as String, + keys = Map.from(json['keys'] as Map), // we need to manually copy to ensure that our map is Map> - signatures = json['signatures'] is Map - ? Map>.from((json['signatures'] as Map) - .map((k, v) => MapEntry(k, Map.from(v)))) - : null, - unsigned = (json['unsigned'] as Map?)?.copy(); + signatures = json.tryGetMap>('signatures'), + unsigned = json.tryGetMap('unsigned'); Map toJson() { final data = _json ?? {}; @@ -81,7 +78,7 @@ class MatrixCrossSigningKey extends MatrixSignableKey { @override MatrixCrossSigningKey.fromJson(Map json) - : usage = List.from(json['usage']), + : usage = json.tryGetList('usage') ?? [], super.fromJson(json); @override @@ -97,7 +94,7 @@ class MatrixDeviceKeys extends MatrixSignableKey { List algorithms; String? get deviceDisplayName => - unsigned != null ? unsigned!['device_display_name'] : null; + unsigned?.tryGet('device_display_name'); MatrixDeviceKeys( String userId, @@ -113,8 +110,8 @@ class MatrixDeviceKeys extends MatrixSignableKey { @override MatrixDeviceKeys.fromJson(Map json) - : algorithms = (json['algorithms'] as List).cast(), - deviceId = json['device_id'], + : algorithms = json.tryGetList('algorithms') ?? [], + deviceId = json['device_id'] as String, super.fromJson(json); @override diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index 73848c2e..37b33f3d 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -28,6 +28,7 @@ class Presence extends BasicEventWithSender { PresenceContent presence; Presence.fromJson(Map json) - : presence = PresenceContent.fromJson(json['content']), + : presence = + PresenceContent.fromJson(json['content'] as Map), super.fromJson(json); } diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index edf9a1de..8f80851e 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -21,7 +21,7 @@ * SOFTWARE. */ -import '../generated/model.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; class PresenceContent { PresenceType presence; @@ -32,9 +32,9 @@ class PresenceContent { PresenceContent.fromJson(Map json) : presence = PresenceType.values.firstWhere( (p) => p.toString().split('.').last == json['presence']), - lastActiveAgo = json['last_active_ago'], - statusMsg = json['status_msg'], - currentlyActive = json['currently_active']; + lastActiveAgo = json.tryGet('last_active_ago'), + statusMsg = json.tryGet('status_msg'), + currentlyActive = json.tryGet('currently_active'); Map toJson() { final data = {}; diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart index 39df80b4..ce148bc1 100644 --- a/lib/src/model/room_keys_keys.dart +++ b/lib/src/model/room_keys_keys.dart @@ -21,6 +21,8 @@ * SOFTWARE. */ +import 'package:matrix_api_lite/matrix_api_lite.dart'; + class RoomKeysSingleKey { int firstMessageIndex; int forwardedCount; @@ -34,10 +36,10 @@ class RoomKeysSingleKey { required this.sessionData}); RoomKeysSingleKey.fromJson(Map json) - : firstMessageIndex = json['first_message_index'], - forwardedCount = json['forwarded_count'], - isVerified = json['is_verified'], - sessionData = json['session_data']; + : firstMessageIndex = json['first_message_index'] as int, + forwardedCount = json['forwarded_count'] as int, + isVerified = json['is_verified'] as bool, + sessionData = json['session_data'] as Map; Map toJson() { final data = {}; @@ -55,8 +57,8 @@ class RoomKeysRoom { RoomKeysRoom({required this.sessions}); RoomKeysRoom.fromJson(Map json) - : sessions = (json['sessions'] as Map) - .map((k, v) => MapEntry(k, RoomKeysSingleKey.fromJson(v))); + : sessions = (json['sessions'] as Map).map((k, v) => + MapEntry(k, RoomKeysSingleKey.fromJson(v as Map))); Map toJson() { final data = {}; @@ -70,8 +72,9 @@ class RoomKeysUpdateResponse { int count; RoomKeysUpdateResponse.fromJson(Map json) - : etag = json['etag'], // synapse replies an int but docs say string? - count = json['count']; + : etag = json.tryGet('etag') ?? + '', // synapse replies an int but docs say string? + count = json.tryGet('count') ?? 0; Map toJson() { final data = {}; diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index 1947d829..0f19836d 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -28,10 +28,10 @@ class RoomSummary { RoomSummary.fromJson(Map json) : mHeroes = json['m.heroes'] != null - ? List.from(json['m.heroes']) + ? List.from(json['m.heroes'] as List) : null, - mJoinedMemberCount = json['m.joined_member_count'], - mInvitedMemberCount = json['m.invited_member_count']; + mJoinedMemberCount = json['m.joined_member_count'] as int?, + mInvitedMemberCount = json['m.invited_member_count'] as int?; Map toJson() { final data = {}; diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index 20bd4927..9fbabb37 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -21,7 +21,7 @@ * SOFTWARE. */ -import 'basic_event_with_sender.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; class StrippedStateEvent extends BasicEventWithSender { String? stateKey; @@ -34,7 +34,7 @@ class StrippedStateEvent extends BasicEventWithSender { : super(type: type, content: content, senderId: senderId); StrippedStateEvent.fromJson(Map json) - : stateKey = json['state_key'], + : stateKey = json.tryGet('state_key'), super.fromJson(json); @override diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index e1e7da52..a435894a 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -21,13 +21,7 @@ * SOFTWARE. */ -import 'basic_event.dart'; -import 'basic_event_with_sender.dart'; -import 'basic_room_event.dart'; -import 'matrix_event.dart'; -import 'presence.dart'; -import 'room_summary.dart'; -import 'stripped_state_event.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; class SyncUpdate { String nextBatch; @@ -51,32 +45,34 @@ class SyncUpdate { }); SyncUpdate.fromJson(Map json) - : nextBatch = json['next_batch'], - rooms = - json['rooms'] != null ? RoomsUpdate.fromJson(json['rooms']) : null, - presence = ((json['presence'] as Map?)?['events'] as List?) - ?.map((i) => Presence.fromJson(i)) + : nextBatch = json['next_batch'] as String, + rooms = (() { + final temp = json.tryGetMap('rooms'); + return temp != null ? RoomsUpdate.fromJson(temp) : null; + }()), + presence = json + .tryGetMap>('presence')?['events'] + ?.map((i) => Presence.fromJson(i as Map)) .toList(), - accountData = ((json['account_data'] as Map?)?['events'] as List?) - ?.map((i) => BasicEvent.fromJson(i)) + accountData = json + .tryGetMap>('account_data')?['events'] + ?.map((i) => BasicEvent.fromJson(i as Map)) .toList(), - toDevice = ((json['to_device'] as Map?)?['events'] as List?) - ?.map((i) => BasicEventWithSender.fromJson(i)) + toDevice = json + .tryGetMap>('to_device')?['events'] + ?.map( + (i) => BasicEventWithSender.fromJson(i as Map)) .toList(), - deviceLists = json['device_lists'] != null - ? DeviceListsUpdate.fromJson(json['device_lists']) - : null, - deviceOneTimeKeysCount = json['device_one_time_keys_count'] != null - ? Map.from(json['device_one_time_keys_count']) - : null, - deviceUnusedFallbackKeyTypes = (json[ - 'device_unused_fallback_key_types'] ?? - json[ - 'org.matrix.msc2732.device_unused_fallback_key_types']) != - null - ? List.from(json['device_unused_fallback_key_types'] ?? - json['org.matrix.msc2732.device_unused_fallback_key_types']) - : null; + deviceLists = (() { + final temp = json.tryGetMap('device_lists'); + return temp != null ? DeviceListsUpdate.fromJson(temp) : null; + }()), + deviceOneTimeKeysCount = + json.tryGetMap('device_one_time_keys_count'), + deviceUnusedFallbackKeyTypes = + json.tryGetList('device_unused_fallback_key_types') ?? + json.tryGetList( + 'org.matrix.msc2732.device_unused_fallback_key_types'); Map toJson() { final data = {}; @@ -126,18 +122,12 @@ class RoomsUpdate { }); RoomsUpdate.fromJson(Map json) { - join = json['join'] != null - ? (json['join'] as Map) - .map((k, v) => MapEntry(k, JoinedRoomUpdate.fromJson(v))) - : null; - invite = json['invite'] != null - ? (json['invite'] as Map) - .map((k, v) => MapEntry(k, InvitedRoomUpdate.fromJson(v))) - : null; - leave = json['leave'] != null - ? (json['leave'] as Map) - .map((k, v) => MapEntry(k, LeftRoomUpdate.fromJson(v))) - : null; + join = json.tryGetMap('join')?.catchMap((k, v) => + MapEntry(k, JoinedRoomUpdate.fromJson(v as Map))); + invite = json.tryGetMap('invite')?.catchMap((k, v) => + MapEntry(k, InvitedRoomUpdate.fromJson(v as Map))); + leave = json.tryGetMap('leave')?.catchMap((k, v) => + MapEntry(k, LeftRoomUpdate.fromJson(v as Map))); } Map toJson() { @@ -175,24 +165,22 @@ class JoinedRoomUpdate extends SyncRoomUpdate { }); JoinedRoomUpdate.fromJson(Map json) - : summary = json['summary'] != null - ? RoomSummary.fromJson(json['summary']) - : null, - state = ((json['state'] as Map?)?['events'] as List?) - ?.map((i) => MatrixEvent.fromJson(i)) + : summary = json.tryGetFromJson('summary', RoomSummary.fromJson), + state = json + .tryGetMap>('state')?['events'] + ?.map((i) => MatrixEvent.fromJson(i as Map)) .toList(), - timeline = json['timeline'] != null - ? TimelineUpdate.fromJson(json['timeline']) - : null, - ephemeral = ((json['ephemeral'] as Map?)?['events'] as List?) - ?.map((i) => BasicRoomEvent.fromJson(i)) + timeline = json.tryGetFromJson('timeline', TimelineUpdate.fromJson), + ephemeral = json + .tryGetMap>('ephemeral')?['events'] + ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(), - accountData = ((json['account_data'] as Map?)?['events'] as List?) - ?.map((i) => BasicRoomEvent.fromJson(i)) + accountData = json + .tryGetMap>('account_data')?['events'] + ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(), - unreadNotifications = json['unread_notifications'] != null - ? UnreadNotificationCounts.fromJson(json['unread_notifications']) - : null; + unreadNotifications = json.tryGetFromJson( + 'unread_notifications', UnreadNotificationCounts.fromJson); Map toJson() { final data = {}; @@ -230,8 +218,9 @@ class InvitedRoomUpdate extends SyncRoomUpdate { InvitedRoomUpdate({this.inviteState}); InvitedRoomUpdate.fromJson(Map json) - : inviteState = ((json['invite_state'] as Map?)?['events'] as List?) - ?.map((i) => StrippedStateEvent.fromJson(i)) + : inviteState = json + .tryGetMap>('invite_state')?['events'] + ?.map((i) => StrippedStateEvent.fromJson(i as Map)) .toList(); Map toJson() { @@ -257,14 +246,14 @@ class LeftRoomUpdate extends SyncRoomUpdate { }); LeftRoomUpdate.fromJson(Map json) - : state = ((json['state'] as Map?)?['events'] as List?) - ?.map((i) => MatrixEvent.fromJson(i)) + : state = json + .tryGetMap>('state')?['events'] + ?.map((i) => MatrixEvent.fromJson(i as Map)) .toList(), - timeline = json['timeline'] != null - ? TimelineUpdate.fromJson(json['timeline']) - : null, - accountData = ((json['account_data'] as Map?)?['events'] as List?) - ?.map((i) => BasicRoomEvent.fromJson(i)) + timeline = json.tryGetFromJson('timeline', TimelineUpdate.fromJson), + accountData = json + .tryGetMap>('account_data')?['events'] + ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(); Map toJson() { @@ -297,13 +286,13 @@ class TimelineUpdate { this.prevBatch, }); - TimelineUpdate.fromJson(Map json) { - events = json['events'] != null - ? (json['events'] as List).map((i) => MatrixEvent.fromJson(i)).toList() - : null; - limited = json['limited']; - prevBatch = json['prev_batch']; - } + TimelineUpdate.fromJson(Map json) + : events = json + .tryGetList>('events') + ?.map((v) => MatrixEvent.fromJson(v)) + .toList(), + limited = json.tryGet('limited'), + prevBatch = json.tryGet('prev_batch'); Map toJson() { final data = {}; @@ -329,10 +318,9 @@ class UnreadNotificationCounts { this.highlightCount, }); - UnreadNotificationCounts.fromJson(Map json) { - highlightCount = json['highlight_count']; - notificationCount = json['notification_count']; - } + UnreadNotificationCounts.fromJson(Map json) + : highlightCount = json.tryGet('highlight_count'), + notificationCount = json.tryGet('notification_count'); Map toJson() { final data = {}; @@ -355,10 +343,9 @@ class DeviceListsUpdate { this.left, }); - DeviceListsUpdate.fromJson(Map json) { - changed = List.from(json['changed'] ?? []); - left = List.from(json['left'] ?? []); - } + DeviceListsUpdate.fromJson(Map json) + : changed = json.tryGetList('changed') ?? [], + left = json.tryGetList('left') ?? []; Map toJson() { final data = {}; diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index fbaa7e11..02dc2743 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -100,6 +100,13 @@ extension TryGetMapExtension on Map { return null; } } + + A? tryGetFromJson(String key, A Function(Map) fromJson, + [TryGet log = TryGet.optional]) { + final value = tryGetMap(key, log); + + return value != null ? fromJson(value) : null; + } } extension on StackTrace { diff --git a/test/event_content_test.dart b/test/event_content_test.dart index 0c5ede11..3b5bf6d4 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -43,7 +43,7 @@ void main() { 'type': 'm.room.encryption', 'unsigned': {'age': 1234} }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map?; expect(MatrixEvent.fromJson(json!).parsedRoomEncryptionContent.toJson(), json['content']); }); @@ -63,7 +63,7 @@ void main() { 'type': 'm.room.encrypted', 'unsigned': {'age': 1234} }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map?; expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), json['content']); json = { @@ -84,7 +84,7 @@ void main() { 'type': 'm.room.encrypted', 'unsigned': {'age': 1234} }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map?; expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), json['content']); }); @@ -98,7 +98,7 @@ void main() { }, 'type': 'm.room_key' }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map?; expect(BasicEvent.fromJson(json!).parsedRoomKeyContent.toJson(), json['content']); }); @@ -111,7 +111,7 @@ void main() { }, 'type': 'm.room_key_request' }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map?; expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), json['content']); json = { @@ -128,7 +128,7 @@ void main() { }, 'type': 'm.room_key_request' }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map?; expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), json['content']); }); @@ -148,7 +148,7 @@ void main() { }, 'type': 'm.forwarded_room_key' }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map?; expect(BasicEvent.fromJson(json!).parsedForwardedRoomKeyContent.toJson(), json['content']); }); @@ -164,7 +164,7 @@ void main() { 'recipient_keys': {'ed25519': ''}, 'keys': {'ed25519': ''} }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map?; expect(OlmPlaintextPayload.fromJson(json!).toJson(), json); }); test('Image Pack Content', () { @@ -190,7 +190,7 @@ void main() { 'org.custom': 'blah', }, }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map; expect(BasicEvent.fromJson(json).parsedImagePackContent.toJson(), json['content']); @@ -205,7 +205,7 @@ void main() { }, }, }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map; expect( BasicEvent.fromJson(json) .parsedImagePackContent @@ -223,7 +223,7 @@ void main() { }, }, }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map; expect( BasicEvent.fromJson(json) .parsedImagePackContent @@ -242,7 +242,7 @@ void main() { }, }, }; - json = jsonDecode(jsonEncode(json)); + json = jsonDecode(jsonEncode(json)) as Map; expect(BasicEvent.fromJson(json).parsedImagePackContent.images['emote'], null); }); From 4675783311096ec728f0bb097abda6b717ad915c Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Wed, 24 Aug 2022 07:57:16 +0000 Subject: [PATCH 134/174] Revert "fix: Secret storage keys are used as account data but are not uri encoded" This reverts commit 2f944292ba3d940464975cb8d80ad8ca994222b4 --- lib/src/model/event_types.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index 3878cb7a..b948c8a2 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -81,9 +81,7 @@ abstract class EventTypes { static const String MegolmBackup = 'm.megolm_backup.v1'; static const String SecretStorageDefaultKey = 'm.secret_storage.default_key'; - // Also used as account data type so it needs to be uri encoded - static String secretStorageKey(String keyId) => - Uri.encodeComponent('m.secret_storage.key.$keyId'); + static String secretStorageKey(String keyId) => 'm.secret_storage.key.$keyId'; // Spaces static const String spaceParent = 'm.space.parent'; From f2ab312091f414b91118bcf5f24a6388de9706e8 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Thu, 25 Aug 2022 12:07:36 +0200 Subject: [PATCH 135/174] chore: Bump version --- CHANGELOG.md | 9 +++++++++ pubspec.yaml | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b56a5030..e85ec2fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [1.1.4] - 25nd Aug 2022 +- Revert "fix: Secret storage keys are used as account data but are not uri encoded" +- chore: disable dynamic calls (Nicolas Werner) +- chore: export filter map extension (Nicolas Werner) +- chore: strict casts (Nicolas Werner) +- chore: strict inference (Nicolas Werner) +- chore: strict raw types (Nicolas Werner) +- chore: upgrade from pedantic to lints (Nicolas Werner) + ## [1.1.3] - 2nd Aug 2022 - fix: Secret storage keys are used as account data but are not uri encoded - chore: export filter map extension diff --git a/pubspec.yaml b/pubspec.yaml index 77c4a4aa..65460852 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.3 +version: 1.1.4 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From ea93867b94b3ed9047a2844dc8ba094f6307b65f Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Thu, 25 Aug 2022 17:55:14 +0200 Subject: [PATCH 136/174] fix: Fixed dysfunctional key-verification (Emoji+manual) - added snippet from Nico in matrix_keys.dart Fixes #24 --- .gitignore | 2 +- lib/src/model/matrix_keys.dart | 21 +++++++++++++++++++-- test/matrix_api_test.dart | 10 +++++----- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 4d9b87d1..40dcabc2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ *.class *.log *.pyc -*.swp +*.sw* .DS_Store .atom/ .buildlog/ diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index 432dccfc..ca25a197 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -42,8 +42,25 @@ abstract class MatrixSignableKey { userId = json['user_id'] as String, keys = Map.from(json['keys'] as Map), // we need to manually copy to ensure that our map is Map> - signatures = json.tryGetMap>('signatures'), - unsigned = json.tryGetMap('unsigned'); + signatures = (() { + final orig = json.tryGetMap('signatures'); + final res = >{}; + for (final entry + in (orig?.entries ?? >[])) { + final deviceSigs = entry.value; + if (deviceSigs is Map) { + for (final nestedEntry in deviceSigs.entries) { + final nestedValue = nestedEntry.value; + if (nestedValue is String) { + (res[entry.key] ??= {})[nestedEntry.key] = + nestedValue; + } + } + } + } + return res; + }()), + unsigned = json.tryGetMap('unsigned')?.copy(); Map toJson() { final data = _json ?? {}; diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 98331e3c..57454e72 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -1197,7 +1197,7 @@ void main() { 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8', }, - 'signatures': {}, + 'signatures': >{}, }); final selfSigningKey = MatrixCrossSigningKey.fromJson({ 'user_id': '@test:fakeServer.notExisting', @@ -1206,7 +1206,7 @@ void main() { 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': 'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY', }, - 'signatures': {}, + 'signatures': >{}, }); final userSigningKey = MatrixCrossSigningKey.fromJson({ 'user_id': '@test:fakeServer.notExisting', @@ -1215,7 +1215,7 @@ void main() { 'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g': '0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g', }, - 'signatures': {}, + 'signatures': >{}, }); await matrixApi.uploadCrossSigningKeys( masterKey: masterKey, @@ -1638,7 +1638,7 @@ void main() { final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; final authData = { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', - 'signatures': {}, + 'signatures': >{}, }; final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); expect( @@ -1663,7 +1663,7 @@ void main() { final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; final authData = { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', - 'signatures': {}, + 'signatures': >{}, }; await matrixApi.putRoomKeysVersion('5', algorithm, authData); }); From fccc2171fe8ee910bc27a9146ff27823b98144b4 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Thu, 25 Aug 2022 17:58:16 +0200 Subject: [PATCH 137/174] chore: version bump --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e85ec2fa..37022e78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [1.1.5] - 25nd Aug 2022 +- fix: Fixed dysfunctional key-verification (Emoji+manual) + ## [1.1.4] - 25nd Aug 2022 - Revert "fix: Secret storage keys are used as account data but are not uri encoded" - chore: disable dynamic calls (Nicolas Werner) diff --git a/pubspec.yaml b/pubspec.yaml index 65460852..fe18fea8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.4 +version: 1.1.5 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From ec848f5bc352d95836171cb02d839250e30d568f Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Fri, 26 Aug 2022 11:12:39 +0200 Subject: [PATCH 138/174] fix: Fixed missing .pub-cache folder creation in .gitlab-ci.yml --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cef66890..b19ced69 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -84,6 +84,8 @@ pub-dev: echo "Missing PUB_DEV_PUBLISH_EXPIRATION environment variable" exit 1 fi + + mkdir -p ~/.pub-cache cat < ~/.pub-cache/credentials.json { From 7413dacdce0c59a61662066ee5eaef23846d443c Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Fri, 26 Aug 2022 11:33:44 +0200 Subject: [PATCH 139/174] chore: version bump --- CHANGELOG.md | 7 +++++-- pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37022e78..07fe38ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ -## [1.1.5] - 25nd Aug 2022 +## [1.1.6] - 26th Aug 2022 +- fix: Fixed missing .pub-cache folder creation in .gitlab-ci.yml + +## [1.1.5] - 25th Aug 2022 - fix: Fixed dysfunctional key-verification (Emoji+manual) -## [1.1.4] - 25nd Aug 2022 +## [1.1.4] - 25th Aug 2022 - Revert "fix: Secret storage keys are used as account data but are not uri encoded" - chore: disable dynamic calls (Nicolas Werner) - chore: export filter map extension (Nicolas Werner) diff --git a/pubspec.yaml b/pubspec.yaml index fe18fea8..d37fcee1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.5 +version: 1.1.6 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 5d3f8d132d255dbd7c507cf7e651ca66ffaef649 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Fri, 26 Aug 2022 14:18:01 +0200 Subject: [PATCH 140/174] fix: Fix for tag version publishing --- .gitlab-ci.yml | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b19ced69..02e44e1e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -62,41 +62,19 @@ dry-run: pub-dev: stage: publish image: dart + dependencies: [dry-run] script: - rm -rf ./docs - | - if [ -z "${PUB_DEV_PUBLISH_ACCESS_TOKEN}" ]; then - echo "Missing PUB_DEV_PUBLISH_ACCESS_TOKEN environment variable" + if [ -z "${PUB_DEV_CREDENTIALS}" ]; then + echo "Missing PUB_DEV_CREDENTIALS environment variable" exit 1 fi - if [ -z "${PUB_DEV_PUBLISH_REFRESH_TOKEN}" ]; then - echo "Missing PUB_DEV_PUBLISH_REFRESH_TOKEN environment variable" - exit 1 - fi + mkdir -p ~/.config/dart/ + cp "${PUB_DEV_CREDENTIALS}" ~/.config/dart/pub-credentials.json - if [ -z "${PUB_DEV_PUBLISH_TOKEN_ENDPOINT}" ]; then - echo "Missing PUB_DEV_PUBLISH_TOKEN_ENDPOINT environment variable" - exit 1 - fi - - if [ -z "${PUB_DEV_PUBLISH_EXPIRATION}" ]; then - echo "Missing PUB_DEV_PUBLISH_EXPIRATION environment variable" - exit 1 - fi - - mkdir -p ~/.pub-cache - - cat < ~/.pub-cache/credentials.json - { - "accessToken":"$(echo "${PUB_DEV_PUBLISH_ACCESS_TOKEN}" | base64 -d)", - "refreshToken":"$(echo "${PUB_DEV_PUBLISH_REFRESH_TOKEN}" | base64 -d)", - "tokenEndpoint":"${PUB_DEV_PUBLISH_TOKEN_ENDPOINT}", - "scopes":["https://www.googleapis.com/auth/userinfo.email","openid"], - "expiration":${PUB_DEV_PUBLISH_EXPIRATION} - } - EOF - dart pub get - - dart pub publish --force + - dart pub publish rules: - if: $CI_COMMIT_TAG From 855f9ee2e60bf4f87d30b853ba37f806fbcdb4d5 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Fri, 26 Aug 2022 14:44:20 +0200 Subject: [PATCH 141/174] fix: forced publish command in .gitlab-ci.yml --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 02e44e1e..d6127b73 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,6 +75,6 @@ pub-dev: cp "${PUB_DEV_CREDENTIALS}" ~/.config/dart/pub-credentials.json - dart pub get - - dart pub publish + - dart pub publish --force rules: - if: $CI_COMMIT_TAG From 6948eb8c064ae3b0820d484e768a21e4652f0512 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 29 Aug 2022 10:23:44 +0200 Subject: [PATCH 142/174] fix: Parsing of MatrixException parameters --- lib/src/model/matrix_exception.dart | 31 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index e04aee1e..28e14445 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -24,6 +24,7 @@ import 'dart:convert'; import 'package:http/http.dart' as http; +import 'package:matrix_api_lite/matrix_api_lite.dart'; enum MatrixError { M_UNKNOWN, @@ -65,12 +66,12 @@ class MatrixException implements Exception { /// The unique identifier for this error. String get errcode => - raw['errcode'] as String? ?? + raw.tryGet('errcode') ?? (requireAdditionalAuthentication ? 'M_FORBIDDEN' : 'M_UNKNOWN'); /// A human readable error description. String get errorMessage => - raw['error'] as String? ?? + raw.tryGet('error') ?? (requireAdditionalAuthentication ? 'Require additional authentication' : 'Unknown error'); @@ -91,11 +92,11 @@ class MatrixException implements Exception { (e) => e.toString() == 'MatrixError.${(raw["errcode"] ?? "")}', orElse: () => MatrixError.M_UNKNOWN); - int? get retryAfterMs => raw['retry_after_ms'] as int?; + int? get retryAfterMs => raw.tryGet('retry_after_ms'); /// This is a session identifier that the client must pass back to the homeserver, if one is provided, /// in subsequent attempts to authenticate in the same API call. - String? get session => raw['session'] as String?; + String? get session => raw.tryGet('session'); /// Returns true if the server requires additional authentication. bool get requireAdditionalAuthentication => response != null @@ -105,26 +106,24 @@ class MatrixException implements Exception { /// For each endpoint, a server offers one or more 'flows' that the client can use /// to authenticate itself. Each flow comprises a series of stages. If this request /// doesn't need additional authentication, then this is null. - List? get authenticationFlows { - final flows = raw['flows']; - return (flows is List>>) - ? flows - .map((flow) => flow['stages']) - .whereType>() - .map((stages) => AuthenticationFlow(List.from(stages))) - .toList() - : null; - } + List? get authenticationFlows => raw + .tryGet>('flows') + ?.whereType>() + .map((flow) => flow['stages']) + .whereType>() + .map((stages) => + AuthenticationFlow(List.from(stages.whereType()))) + .toList(); /// This section contains any information that the client will need to know in order to use a given type /// of authentication. For each authentication type presented, that type may be present as a key in this /// dictionary. For example, the public part of an OAuth client ID could be given here. Map? get authenticationParams => - raw['params'] as Map?; + raw.tryGetMap('params'); /// Returns the list of already completed authentication flows from previous requests. List get completedAuthenticationFlows => - List.from(raw['completed'] as List? ?? []); + raw.tryGetList('completed') ?? []; } /// For each endpoint, a server offers one or more 'flows' that the client can use From dcde0af99e0ee4fbf060136383b57215df3ef015 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 29 Aug 2022 10:33:16 +0200 Subject: [PATCH 143/174] chore: Bump version --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07fe38ac..8c263805 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [1.1.7] - 29th Aug 2022 +- fix: Parsing of MatrixException parameters + ## [1.1.6] - 26th Aug 2022 - fix: Fixed missing .pub-cache folder creation in .gitlab-ci.yml diff --git a/pubspec.yaml b/pubspec.yaml index d37fcee1..67f67bf7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.6 +version: 1.1.7 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 881f8c3fd8ef9819303160fe8aec0adf627e3cef Mon Sep 17 00:00:00 2001 From: Krille Fear Date: Fri, 26 Aug 2022 12:20:44 +0000 Subject: [PATCH 144/174] refactor: Remove unused api docs job --- .gitlab-ci.yml | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d6127b73..1fe91d72 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,5 @@ stages: - coverage - - builddocs - - deploy - publish test: @@ -23,34 +21,6 @@ code_analyze: - flutter format lib/ test/ --set-exit-if-changed - flutter analyze -build_api_doc: - tags: - - docker - stage: builddocs - image: cirrusci/flutter - script: - - dartdoc --exclude "dart:async,dart:collection,dart:convert,dart:core,dart:developer,dart:io,dart:isolate,dart:math,dart:typed_data,dart:ui" - artifacts: - paths: - - doc/api/ - only: - - main - -pages: - tags: - - linux - stage: deploy - image: alpine:latest - script: - - mv doc/api/ public - dependencies: - - build_api_doc - artifacts: - paths: - - public - only: - - main - dry-run: stage: publish image: dart From 3cc2f2fa4a4c0eecdf9e6a662c9bbdf1d0d9c032 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 14 Oct 2022 14:11:17 +0200 Subject: [PATCH 145/174] fix: Edge case where MatrixException.error differs from errcode --- lib/src/model/matrix_exception.dart | 7 ++++--- test/matrix_api_test.dart | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 28e14445..48231e3e 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -87,10 +87,11 @@ class MatrixException implements Exception { @override String toString() => '$errcode: $errorMessage'; - /// Returns the [ResponseError]. Is ResponseError.NONE if there wasn't an error. + /// Returns the errcode as an [MatrixError]. MatrixError get error => MatrixError.values.firstWhere( - (e) => e.toString() == 'MatrixError.${(raw["errcode"] ?? "")}', - orElse: () => MatrixError.M_UNKNOWN); + (e) => e.name == errcode, + orElse: () => MatrixError.M_UNKNOWN, + ); int? get retryAfterMs => raw.tryGet('retry_after_ms'); diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 57454e72..fe5a69b4 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -70,7 +70,7 @@ void main() { expect(exception.completedAuthenticationFlows, ['example.type.foo']); expect(exception.requireAdditionalAuthentication, true); expect(exception.retryAfterMs, null); - expect(exception.error, MatrixError.M_UNKNOWN); + expect(exception.error, MatrixError.M_FORBIDDEN); expect(exception.errcode, 'M_FORBIDDEN'); expect(exception.errorMessage, 'Require additional authentication'); }); From 1719bcec9e5f0ef734d2bef329206721afc86cd7 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 12 Oct 2022 16:36:56 +0200 Subject: [PATCH 146/174] chore: add pushrules to the event types --- lib/src/model/event_types.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index b948c8a2..f0f49edd 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -80,6 +80,7 @@ abstract class EventTypes { static const String CrossSigningMasterKey = 'm.cross_signing.master'; static const String MegolmBackup = 'm.megolm_backup.v1'; static const String SecretStorageDefaultKey = 'm.secret_storage.default_key'; + static const String PushRules = 'm.push_rules'; static String secretStorageKey(String keyId) => 'm.secret_storage.key.$keyId'; From abe793302e7064a34d2766382fb0cd8f640d14bd Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 14 Oct 2022 14:28:01 +0200 Subject: [PATCH 147/174] chore: Bump version --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c263805..b6ab6ce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [1.1.8] - 29th Aug 2022 +- fix: Edge case where MatrixException.error differs from errcode +- chore: add pushrules to the event types + ## [1.1.7] - 29th Aug 2022 - fix: Parsing of MatrixException parameters diff --git a/pubspec.yaml b/pubspec.yaml index 67f67bf7..34c4aced 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.7 +version: 1.1.8 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 2af89aeb8b730b0ab5a35f95fd2582f9711c31d1 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 7 Nov 2022 10:40:02 +0100 Subject: [PATCH 148/174] feat: Allow converting of stacktraces in logs This makes it possible to print the correct stacktraces when using web. --- lib/src/utils/logs.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/src/utils/logs.dart b/lib/src/utils/logs.dart index 8c509899..628e6d55 100644 --- a/lib/src/utils/logs.dart +++ b/lib/src/utils/logs.dart @@ -35,6 +35,10 @@ enum Level { class Logs { static final Logs _singleton = Logs._internal(); + /// Override this function if you want to convert a stacktrace for some reason + /// for example to apply a source map in the browser. + static StackTrace? Function(StackTrace?) stackTraceConverter = (s) => s; + factory Logs() { return _singleton; } @@ -58,7 +62,7 @@ class Logs { LogEvent( title, exception: exception, - stackTrace: stackTrace, + stackTrace: stackTraceConverter(stackTrace), level: Level.wtf, ), ); @@ -68,7 +72,7 @@ class Logs { LogEvent( title, exception: exception, - stackTrace: stackTrace, + stackTrace: stackTraceConverter(stackTrace), level: Level.error, ), ); @@ -78,7 +82,7 @@ class Logs { LogEvent( title, exception: exception, - stackTrace: stackTrace, + stackTrace: stackTraceConverter(stackTrace), level: Level.warning, ), ); @@ -88,7 +92,7 @@ class Logs { LogEvent( title, exception: exception, - stackTrace: stackTrace, + stackTrace: stackTraceConverter(stackTrace), level: Level.info, ), ); @@ -98,7 +102,7 @@ class Logs { LogEvent( title, exception: exception, - stackTrace: stackTrace, + stackTrace: stackTraceConverter(stackTrace), level: Level.debug, ), ); @@ -108,7 +112,7 @@ class Logs { LogEvent( title, exception: exception, - stackTrace: stackTrace, + stackTrace: stackTraceConverter(stackTrace), level: Level.verbose, ), ); From 7655d322e9e85d9b0bb7760adeb16da1fdb588d3 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 7 Nov 2022 10:40:40 +0100 Subject: [PATCH 149/174] chore: Bump version --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6ab6ce1..245fdbe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [1.1.9] - 7th Nov 2022 +- feat: Allow converting of stacktraces in logs + ## [1.1.8] - 29th Aug 2022 - fix: Edge case where MatrixException.error differs from errcode - chore: add pushrules to the event types diff --git a/pubspec.yaml b/pubspec.yaml index 34c4aced..22c3829c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.8 +version: 1.1.9 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 25e2205dbf9b95f27f0367bb3c588d7525a745b9 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 27 Jan 2023 14:28:07 +0100 Subject: [PATCH 150/174] chore: Update enhanced_enum to 0.2.4 --- pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 22c3829c..ca8d38bc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,12 +9,12 @@ environment: sdk: ">=2.17.0 <3.0.0" dependencies: - enhanced_enum: ^0.1.1 + enhanced_enum: ^0.2.4 http: ^0.13.0 mime: ^1.0.0 dev_dependencies: build_runner: ^2.1.8 - enhanced_enum_generator: ^0.1.1 + enhanced_enum_generator: ^0.2.4 lints: ^2.0.0 test: ^1.14.4 From ab7fc034f2bddb00cc8754bf5ea561738d8ee425 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Fri, 27 Jan 2023 14:28:35 +0100 Subject: [PATCH 151/174] chore: Bump version --- CHANGELOG.md | 3 +++ pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 245fdbe2..f8a081e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [1.1.10] - 27th Jan 2023 +- chore: Update enhanced_enum to 0.2.4 + ## [1.1.9] - 7th Nov 2022 - feat: Allow converting of stacktraces in logs diff --git a/pubspec.yaml b/pubspec.yaml index ca8d38bc..ceee2efc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.9 +version: 1.1.10 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From d99bb05f475a469c3534afd4e57629865a40cde2 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 17 Apr 2023 11:57:56 +0200 Subject: [PATCH 152/174] feat: Upgrade to spec 1.6 In theory this is a breaking change, since it changes the read receipt API slightly. --- lib/src/generated/api.dart | 446 +++++++++++++++++++++++++++++++---- lib/src/generated/model.dart | 416 ++++++++++++++++++++++++++++---- test/matrix_api_test.dart | 3 +- 3 files changed, 767 insertions(+), 98 deletions(-) diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 7a495b1c..c0e63c86 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -119,6 +119,277 @@ class Api { return GetSpaceHierarchyResponse.fromJson(json); } + /// Retrieve all of the child events for a given parent event. + /// + /// Note that when paginating the `from` token should be "after" the `to` token in + /// terms of topological ordering, because it is only possible to paginate "backwards" + /// through events, starting at `from`. + /// + /// For example, passing a `from` token from page 2 of the results, and a `to` token + /// from page 1, would return the empty set. The caller can use a `from` token from + /// page 1 and a `to` token from page 2 to paginate over the same range, however. + /// + /// [roomId] The ID of the room containing the parent event. + /// + /// [eventId] The ID of the parent event whose child events are to be returned. + /// + /// [from] The pagination token to start returning results from. If not supplied, results + /// start at the most recent topological event known to the server. + /// + /// Can be a `next_batch` or `prev_batch` token from a previous call, or a returned + /// `start` token from [`/messages`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidmessages), + /// or a `next_batch` token from [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync). + /// + /// [to] The pagination token to stop returning results at. If not supplied, results + /// continue up to `limit` or until there are no more events. + /// + /// Like `from`, this can be a previous token from a prior call to this endpoint + /// or from `/messages` or `/sync`. + /// + /// [limit] The maximum number of results to return in a single `chunk`. The server can + /// and should apply a maximum value to this parameter to avoid large responses. + /// + /// Similarly, the server should apply a default value when not supplied. + /// + /// [dir] Optional (default `b`) direction to return events from. If this is set to `f`, events + /// will be returned in chronological order starting at `from`. If it + /// is set to `b`, events will be returned in *reverse* chronological + /// order, again starting at `from`. + Future getRelatingEvents( + String roomId, String eventId, + {String? from, String? to, int? limit, Direction? dir}) async { + final requestUri = Uri( + path: + '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/relations/${Uri.encodeComponent(eventId)}', + queryParameters: { + if (from != null) 'from': from, + if (to != null) 'to': to, + if (limit != null) 'limit': limit.toString(), + if (dir != null) 'dir': dir.name, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetRelatingEventsResponse.fromJson(json); + } + + /// Retrieve all of the child events for a given parent event which relate to the parent + /// using the given `relType`. + /// + /// Note that when paginating the `from` token should be "after" the `to` token in + /// terms of topological ordering, because it is only possible to paginate "backwards" + /// through events, starting at `from`. + /// + /// For example, passing a `from` token from page 2 of the results, and a `to` token + /// from page 1, would return the empty set. The caller can use a `from` token from + /// page 1 and a `to` token from page 2 to paginate over the same range, however. + /// + /// [roomId] The ID of the room containing the parent event. + /// + /// [eventId] The ID of the parent event whose child events are to be returned. + /// + /// [relType] The [relationship type](https://spec.matrix.org/unstable/client-server-api/#relationship-types) to search for. + /// + /// [from] The pagination token to start returning results from. If not supplied, results + /// start at the most recent topological event known to the server. + /// + /// Can be a `next_batch` or `prev_batch` token from a previous call, or a returned + /// `start` token from [`/messages`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidmessages), + /// or a `next_batch` token from [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync). + /// + /// [to] The pagination token to stop returning results at. If not supplied, results + /// continue up to `limit` or until there are no more events. + /// + /// Like `from`, this can be a previous token from a prior call to this endpoint + /// or from `/messages` or `/sync`. + /// + /// [limit] The maximum number of results to return in a single `chunk`. The server can + /// and should apply a maximum value to this parameter to avoid large responses. + /// + /// Similarly, the server should apply a default value when not supplied. + /// + /// [dir] Optional (default `b`) direction to return events from. If this is set to `f`, events + /// will be returned in chronological order starting at `from`. If it + /// is set to `b`, events will be returned in *reverse* chronological + /// order, again starting at `from`. + Future getRelatingEventsWithRelType( + String roomId, String eventId, String relType, + {String? from, String? to, int? limit, Direction? dir}) async { + final requestUri = Uri( + path: + '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/relations/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(relType)}', + queryParameters: { + if (from != null) 'from': from, + if (to != null) 'to': to, + if (limit != null) 'limit': limit.toString(), + if (dir != null) 'dir': dir.name, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetRelatingEventsWithRelTypeResponse.fromJson(json); + } + + /// Retrieve all of the child events for a given parent event which relate to the parent + /// using the given `relType` and have the given `eventType`. + /// + /// Note that when paginating the `from` token should be "after" the `to` token in + /// terms of topological ordering, because it is only possible to paginate "backwards" + /// through events, starting at `from`. + /// + /// For example, passing a `from` token from page 2 of the results, and a `to` token + /// from page 1, would return the empty set. The caller can use a `from` token from + /// page 1 and a `to` token from page 2 to paginate over the same range, however. + /// + /// [roomId] The ID of the room containing the parent event. + /// + /// [eventId] The ID of the parent event whose child events are to be returned. + /// + /// [relType] The [relationship type](https://spec.matrix.org/unstable/client-server-api/#relationship-types) to search for. + /// + /// [eventType] The event type of child events to search for. + /// + /// Note that in encrypted rooms this will typically always be `m.room.encrypted` + /// regardless of the event type contained within the encrypted payload. + /// + /// [from] The pagination token to start returning results from. If not supplied, results + /// start at the most recent topological event known to the server. + /// + /// Can be a `next_batch` or `prev_batch` token from a previous call, or a returned + /// `start` token from [`/messages`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3roomsroomidmessages), + /// or a `next_batch` token from [`/sync`](https://spec.matrix.org/unstable/client-server-api/#get_matrixclientv3sync). + /// + /// [to] The pagination token to stop returning results at. If not supplied, results + /// continue up to `limit` or until there are no more events. + /// + /// Like `from`, this can be a previous token from a prior call to this endpoint + /// or from `/messages` or `/sync`. + /// + /// [limit] The maximum number of results to return in a single `chunk`. The server can + /// and should apply a maximum value to this parameter to avoid large responses. + /// + /// Similarly, the server should apply a default value when not supplied. + /// + /// [dir] Optional (default `b`) direction to return events from. If this is set to `f`, events + /// will be returned in chronological order starting at `from`. If it + /// is set to `b`, events will be returned in *reverse* chronological + /// order, again starting at `from`. + Future + getRelatingEventsWithRelTypeAndEventType( + String roomId, String eventId, String relType, String eventType, + {String? from, String? to, int? limit, Direction? dir}) async { + final requestUri = Uri( + path: + '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/relations/${Uri.encodeComponent(eventId)}/${Uri.encodeComponent(relType)}/${Uri.encodeComponent(eventType)}', + queryParameters: { + if (from != null) 'from': from, + if (to != null) 'to': to, + if (limit != null) 'limit': limit.toString(), + if (dir != null) 'dir': dir.name, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetRelatingEventsWithRelTypeAndEventTypeResponse.fromJson(json); + } + + /// Paginates over the thread roots in a room, ordered by the `latest_event` of each thread root + /// in its bundle. + /// + /// [roomId] The room ID where the thread roots are located. + /// + /// [include] Optional (default `all`) flag to denote which thread roots are of interest to the caller. + /// When `all`, all thread roots found in the room are returned. When `participated`, only + /// thread roots for threads the user has [participated in](https://spec.matrix.org/unstable/client-server-api/#server-side-aggregation-of-mthread-relationships) + /// will be returned. + /// + /// [limit] Optional limit for the maximum number of thread roots to include per response. Must be an integer + /// greater than zero. + /// + /// Servers should apply a default value, and impose a maximum value to avoid resource exhaustion. + /// + /// [from] A pagination token from a previous result. When not provided, the server starts paginating from + /// the most recent event visible to the user (as per history visibility rules; topologically). + Future getThreadRoots(String roomId, + {Include? include, int? limit, String? from}) async { + final requestUri = Uri( + path: '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/threads', + queryParameters: { + if (include != null) 'include': include.name, + if (limit != null) 'limit': limit.toString(), + if (from != null) 'from': from, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetThreadRootsResponse.fromJson(json); + } + + /// Get the ID of the event closest to the given timestamp, in the + /// direction specified by the `dir` parameter. + /// + /// If the server does not have all of the room history and does not have + /// an event suitably close to the requested timestamp, it can use the + /// corresponding [federation endpoint](https://spec.matrix.org/unstable/server-server-api/#get_matrixfederationv1timestamp_to_eventroomid) + /// to ask other servers for a suitable event. + /// + /// After calling this endpoint, clients can call + /// [`/rooms/{roomId}/context/{eventId}`](#get_matrixclientv3roomsroomidcontexteventid) + /// to obtain a pagination token to retrieve the events around the returned event. + /// + /// The event returned by this endpoint could be an event that the client + /// cannot render, and so may need to paginate in order to locate an event + /// that it can display, which may end up being outside of the client's + /// suitable range. Clients can employ different strategies to display + /// something reasonable to the user. For example, the client could try + /// paginating in one direction for a while, while looking at the + /// timestamps of the events that it is paginating through, and if it + /// exceeds a certain difference from the target timestamp, it can try + /// paginating in the opposite direction. The client could also simply + /// paginate in one direction and inform the user that the closest event + /// found in that direction is outside of the expected range. + /// + /// [roomId] The ID of the room to search + /// + /// [ts] The timestamp to search from, as given in milliseconds + /// since the Unix epoch. + /// + /// [dir] The direction in which to search. `f` for forwards, `b` for backwards. + Future getEventByTimestamp( + String roomId, int ts, Direction dir) async { + final requestUri = Uri( + path: + '_matrix/client/v1/rooms/${Uri.encodeComponent(roomId)}/timestamp_to_event', + queryParameters: { + 'ts': ts.toString(), + 'dir': dir.name, + }); + final request = Request('GET', baseUri!.resolveUri(requestUri)); + request.headers['authorization'] = 'Bearer ${bearerToken!}'; + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return GetEventByTimestampResponse.fromJson(json); + } + /// Gets a list of the third party identifiers that the homeserver has /// associated with the user's account. /// @@ -1134,7 +1405,9 @@ class Api { /// checks, delete the alias and return a successful response even if the user does not /// have permission to update the `m.room.canonical_alias` event. /// - /// [roomAlias] The room alias to remove. + /// [roomAlias] The room alias to remove. Its format is defined + /// [in the appendices](https://spec.matrix.org/unstable/appendices/#room-aliases). + /// Future deleteRoomAlias(String roomAlias) async { final requestUri = Uri( path: @@ -1155,7 +1428,9 @@ class Api { /// domain part of the alias does not correspond to the server's own /// domain. /// - /// [roomAlias] The room alias. + /// [roomAlias] The room alias. Its format is defined + /// [in the appendices](https://spec.matrix.org/unstable/appendices/#room-aliases). + /// Future getRoomIdByAlias(String roomAlias) async { final requestUri = Uri( path: @@ -1171,7 +1446,9 @@ class Api { /// setRoomAlias /// - /// [roomAlias] The room alias to set. + /// [roomAlias] The room alias to set. Its format is defined + /// [in the appendices](https://spec.matrix.org/unstable/appendices/#room-aliases). + /// /// /// [roomId] The room ID to set. Future setRoomAlias(String roomAlias, String roomId) async { @@ -1277,7 +1554,7 @@ class Api { return MatrixEvent.fromJson(json); } - /// *Note that this API takes either a room ID or alias, unlike* `/room/{roomId}/join`. + /// *Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`. /// /// This API starts a user participating in a particular room, if that user /// is allowed to participate in that room. After this call, the client is @@ -1609,6 +1886,8 @@ class Api { /// [password] Required when `type` is `m.login.password`. The user's /// password. /// + /// [refreshToken] If true, the client supports refresh tokens. + /// /// [token] Required when `type` is `m.login.token`. Part of Token-based login. /// /// [type] The login type being used. @@ -1621,6 +1900,7 @@ class Api { String? initialDeviceDisplayName, String? medium, String? password, + bool? refreshToken, String? token, String? user}) async { final requestUri = Uri(path: '_matrix/client/v3/login'); @@ -1634,6 +1914,7 @@ class Api { 'initial_device_display_name': initialDeviceDisplayName, if (medium != null) 'medium': medium, if (password != null) 'password': password, + if (refreshToken != null) 'refresh_token': refreshToken, if (token != null) 'token': token, 'type': type.name, if (user != null) 'user': user, @@ -2037,9 +2318,20 @@ class Api { return PushRule.fromJson(json); } - /// This endpoint allows the creation, modification and deletion of pushers - /// for this user ID. The behaviour of this endpoint varies depending on the - /// values in the JSON body. + /// This endpoint allows the creation and modification of user defined push + /// rules. + /// + /// If a rule with the same `rule_id` already exists among rules of the same + /// kind, it is updated with the new parameters, otherwise a new rule is + /// created. + /// + /// If both `after` and `before` are provided, the new or updated rule must + /// be the next most important rule with respect to the rule identified by + /// `before`. + /// + /// If neither `after` nor `before` are provided and the rule is created, it + /// should be added as the most important user defined rule among rules of + /// the same kind. /// /// When creating push rules, they MUST be enabled by default. /// @@ -2048,7 +2340,9 @@ class Api { /// [kind] The kind of rule /// /// - /// [ruleId] The identifier for the rule. + /// [ruleId] The identifier for the rule. If the string starts with a dot ("."), + /// the request MUST be rejected as this is reserved for server-default + /// rules. Slashes ("/") and backslashes ("\\") are also not allowed. /// /// /// [before] Use 'before' with a `rule_id` as its value to make the new rule the @@ -2213,6 +2507,40 @@ class Api { return ignore(json); } + /// Refresh an access token. Clients should use the returned access token + /// when making subsequent API calls, and store the returned refresh token + /// (if given) in order to refresh the new access token when necessary. + /// + /// After an access token has been refreshed, a server can choose to + /// invalidate the old access token immediately, or can choose not to, for + /// example if the access token would expire soon anyways. Clients should + /// not make any assumptions about the old access token still being valid, + /// and should use the newly provided access token instead. + /// + /// The old refresh token remains valid until the new access token or refresh token + /// is used, at which point the old refresh token is revoked. + /// + /// Note that this endpoint does not require authentication via an + /// access token. Authentication is provided via the refresh token. + /// + /// Application Service identity assertion is disabled for this endpoint. + /// + /// [refreshToken] The refresh token + Future refresh(String refreshToken) async { + final requestUri = Uri(path: '_matrix/client/v3/refresh'); + final request = Request('POST', baseUri!.resolveUri(requestUri)); + request.headers['content-type'] = 'application/json'; + request.bodyBytes = utf8.encode(jsonEncode({ + 'refresh_token': refreshToken, + })); + final response = await httpClient.send(request); + final responseBody = await response.stream.toBytes(); + if (response.statusCode != 200) unexpectedResponse(response, responseBody); + final responseString = utf8.decode(responseBody); + final json = jsonDecode(responseString); + return RefreshResponse.fromJson(json); + } + /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api), except in /// the cases where a guest account is being registered. /// @@ -2274,6 +2602,8 @@ class Api { /// /// [password] The desired password for the account. /// + /// [refreshToken] If true, the client supports refresh tokens. + /// /// [username] The basis for the localpart of the desired Matrix ID. If omitted, /// the homeserver MUST generate a Matrix ID local part. Future register( @@ -2283,6 +2613,7 @@ class Api { bool? inhibitLogin, String? initialDeviceDisplayName, String? password, + bool? refreshToken, String? username}) async { final requestUri = Uri(path: '_matrix/client/v3/register', queryParameters: { @@ -2297,6 +2628,7 @@ class Api { if (initialDeviceDisplayName != null) 'initial_device_display_name': initialDeviceDisplayName, if (password != null) 'password': password, + if (refreshToken != null) 'refresh_token': refreshToken, if (username != null) 'username': username, })); final response = await httpClient.send(request); @@ -2861,7 +3193,10 @@ class Api { /// /// [eventId] The event to get context around. /// - /// [limit] The maximum number of events to return. Default: 10. + /// [limit] The maximum number of context events to return. The limit applies + /// to the sum of the `events_before` and `events_after` arrays. The + /// requested event ID is always returned in `event` even if `limit` is + /// 0. Defaults to 10. /// /// [filter] A JSON `RoomEventFilter` to filter the returned events with. The /// filter is only applied to `events_before`, `events_after`, and @@ -2984,7 +3319,8 @@ class Api { /// /// [idServer] The hostname+port of the identity server which should be used for third party identifier lookups. /// - /// [medium] The kind of address being passed in the address field, for example `email`. + /// [medium] The kind of address being passed in the address field, for example + /// `email` (see [the list of recognised values](https://spec.matrix.org/unstable/appendices/#3pid-types)). Future inviteBy3PID(String roomId, String address, String idAccessToken, String idServer, String medium) async { final requestUri = Uri( @@ -3008,8 +3344,8 @@ class Api { /// *Note that there are two forms of this API, which are documented separately. /// This version of the API requires that the inviter knows the Matrix - /// identifier of the invitee. The other is documented in the* - /// [third party invites section](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3roomsroomidinvite-1). + /// identifier of the invitee. The other is documented in the + /// [third party invites](https://spec.matrix.org/unstable/client-server-api/#third-party-invites) section.* /// /// This API invites a user to participate in a particular room. /// They do not start participating in the room until they actually join the @@ -3280,8 +3616,12 @@ class Api { /// [mRead] The event ID to set the read receipt location at. This is /// equivalent to calling `/receipt/m.read/$elsewhere:example.org` /// and is provided here to save that extra call. - Future setReadMarker(String roomId, String mFullyRead, - {String? mRead}) async { + /// + /// [mReadPrivate] The event ID to set the *private* read receipt location at. This + /// equivalent to calling `/receipt/m.read.private/$elsewhere:example.org` + /// and is provided here to save that extra call. + Future setReadMarker(String roomId, + {String? mFullyRead, String? mRead, String? mReadPrivate}) async { final requestUri = Uri( path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/read_markers'); @@ -3289,8 +3629,9 @@ class Api { request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; request.bodyBytes = utf8.encode(jsonEncode({ - 'm.fully_read': mFullyRead, + if (mFullyRead != null) 'm.fully_read': mFullyRead, if (mRead != null) 'm.read': mRead, + if (mReadPrivate != null) 'm.read.private': mReadPrivate, })); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); @@ -3305,21 +3646,31 @@ class Api { /// /// [roomId] The room in which to send the event. /// - /// [receiptType] The type of receipt to send. + /// [receiptType] The type of receipt to send. This can also be `m.fully_read` as an + /// alternative to [`/read_markers`](https://spec.matrix.org/unstable/client-server-api/#post_matrixclientv3roomsroomidread_markers). + /// + /// Note that `m.fully_read` does not appear under `m.receipt`: this endpoint + /// effectively calls `/read_markers` internally when presented with a receipt + /// type of `m.fully_read`. /// /// [eventId] The event ID to acknowledge up to. /// - /// [receipt] Extra receipt information to attach to `content` if any. The - /// server will automatically set the `ts` field. - Future postReceipt(String roomId, ReceiptType receiptType, - String eventId, Map receipt) async { + /// [threadId] The root thread event's ID (or `main`) for which + /// thread this receipt is intended to be under. If + /// not specified, the read receipt is *unthreaded* + /// (default). + Future postReceipt( + String roomId, ReceiptType receiptType, String eventId, + {String? threadId}) async { final requestUri = Uri( path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/receipt/${Uri.encodeComponent(receiptType.name)}/${Uri.encodeComponent(eventId)}'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; request.headers['content-type'] = 'application/json'; - request.bodyBytes = utf8.encode(jsonEncode(receipt)); + request.bodyBytes = utf8.encode(jsonEncode({ + if (threadId != null) 'thread_id': threadId, + })); final response = await httpClient.send(request); final responseBody = await response.stream.toBytes(); if (response.statusCode != 200) unexpectedResponse(response, responseBody); @@ -3344,7 +3695,7 @@ class Api { /// /// [eventId] The ID of the event to redact /// - /// [txnId] The transaction ID for this event. Clients should generate a + /// [txnId] The [transaction ID](https://spec.matrix.org/unstable/client-server-api/#transaction-identifiers) for this event. Clients should generate a /// unique ID; it will be used by the server to ensure idempotency of requests. /// /// [reason] The reason for the event being redacted. @@ -3413,7 +3764,7 @@ class Api { /// /// [eventType] The type of event to send. /// - /// [txnId] The transaction ID for this event. Clients should generate an + /// [txnId] The [transaction ID](https://spec.matrix.org/unstable/client-server-api/#transaction-identifiers) 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. /// @@ -3640,7 +3991,7 @@ class Api { /// /// [eventType] The type of event to send. /// - /// [txnId] The transaction ID for this event. Clients should generate an + /// [txnId] The [transaction ID](https://spec.matrix.org/unstable/client-server-api/#transaction-identifiers) 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. /// @@ -3877,13 +4228,13 @@ class Api { return (json as List).map((v) => ThirdPartyUser.fromJson(v)).toList(); } - /// Get some account_data for the client. This config is only visible to the user - /// that set the account_data. + /// Get some account data for the client. This config is only visible to the user + /// that set the account data. /// - /// [userId] The ID of the user to get account_data for. The access token must be + /// [userId] The ID of the user to get account data for. The access token must be /// authorized to make requests for this user ID. /// - /// [type] The event type of the account_data to get. Custom types should be + /// [type] The event type of the account data to get. Custom types should be /// namespaced to avoid clashes. Future> getAccountData( String userId, String type) async { @@ -3900,17 +4251,18 @@ class Api { return json as Map; } - /// Set some account_data for the client. This config is only visible to the user - /// that set the account_data. The config will be synced to clients in the - /// top-level `account_data`. + /// Set some account data for the client. This config is only visible to the user + /// that set the account data. The config will be available to clients through the + /// top-level `account_data` field in the homeserver response to + /// [/sync](#get_matrixclientv3sync). /// - /// [userId] The ID of the user to set account_data for. The access token must be + /// [userId] The ID of the user to set account data for. The access token must be /// authorized to make requests for this user ID. /// - /// [type] The event type of the account_data to set. Custom types should be + /// [type] The event type of the account data to set. Custom types should be /// namespaced to avoid clashes. /// - /// [content] The content of the account_data + /// [content] The content of the account data. Future setAccountData( String userId, String type, Map content) async { final requestUri = Uri( @@ -3984,7 +4336,7 @@ class Api { /// be used to request another OpenID access token or call `/sync`, for /// example. /// - /// [userId] The user to request and OpenID token for. Should be the user who + /// [userId] The user to request an OpenID token for. Should be the user who /// is authenticated for the request. /// /// [body] An empty object. Reserved for future expansion. @@ -4005,15 +4357,15 @@ class Api { return OpenIdCredentials.fromJson(json); } - /// Get some account_data for the client on a given room. This config is only - /// visible to the user that set the account_data. + /// Get some account data for the client on a given room. This config is only + /// visible to the user that set the account data. /// - /// [userId] The ID of the user to set account_data for. The access token must be + /// [userId] The ID of the user to get account data for. The access token must be /// authorized to make requests for this user ID. /// - /// [roomId] The ID of the room to get account_data for. + /// [roomId] The ID of the room to get account data for. /// - /// [type] The event type of the account_data to get. Custom types should be + /// [type] The event type of the account data to get. Custom types should be /// namespaced to avoid clashes. Future> getAccountDataPerRoom( String userId, String roomId, String type) async { @@ -4030,19 +4382,19 @@ class Api { return json as Map; } - /// Set some account_data for the client on a given room. This config is only - /// visible to the user that set the account_data. The config will be synced to - /// clients in the per-room `account_data`. + /// Set some account data for the client on a given room. This config is only + /// visible to the user that set the account data. The config will be delivered to + /// clients in the per-room entries via [/sync](#get_matrixclientv3sync). /// - /// [userId] The ID of the user to set account_data for. The access token must be + /// [userId] The ID of the user to set account data for. The access token must be /// authorized to make requests for this user ID. /// - /// [roomId] The ID of the room to set account_data on. + /// [roomId] The ID of the room to set account data on. /// - /// [type] The event type of the account_data to set. Custom types should be + /// [type] The event type of the account data to set. Custom types should be /// namespaced to avoid clashes. /// - /// [content] The content of the account_data + /// [content] The content of the account data. Future setAccountDataPerRoom(String userId, String roomId, String type, Map content) async { final requestUri = Uri( diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index 37e3e477..5b355f2d 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -95,6 +95,7 @@ class PublicRoomsChunk { this.name, required this.numJoinedMembers, required this.roomId, + this.roomType, this.topic, required this.worldReadable, }); @@ -109,6 +110,7 @@ class PublicRoomsChunk { name = ((v) => v != null ? v as String : null)(json['name']), numJoinedMembers = json['num_joined_members'] as int, roomId = json['room_id'] as String, + roomType = ((v) => v != null ? v as String : null)(json['room_type']), topic = ((v) => v != null ? v as String : null)(json['topic']), worldReadable = json['world_readable'] as bool; Map toJson() { @@ -116,6 +118,7 @@ class PublicRoomsChunk { final canonicalAlias = this.canonicalAlias; final joinRule = this.joinRule; final name = this.name; + final roomType = this.roomType; final topic = this.topic; return { if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), @@ -125,6 +128,7 @@ class PublicRoomsChunk { if (name != null) 'name': name, 'num_joined_members': numJoinedMembers, 'room_id': roomId, + if (roomType != null) 'room_type': roomType, if (topic != null) 'topic': topic, 'world_readable': worldReadable, }; @@ -154,6 +158,9 @@ class PublicRoomsChunk { /// The ID of the room. String roomId; + /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. + String? roomType; + /// The topic of the room, if any. String? topic; @@ -161,14 +168,14 @@ class PublicRoomsChunk { bool worldReadable; } -@_NameSource('rule override generated') -class SpaceRoomsChunkBase { - SpaceRoomsChunkBase({ +@_NameSource('spec') +class ChildRoomsChunk { + ChildRoomsChunk({ required this.childrenState, this.roomType, }); - SpaceRoomsChunkBase.fromJson(Map json) + ChildRoomsChunk.fromJson(Map json) : childrenState = (json['children_state'] as List) .map((v) => ChildrenState.fromJson(v)) .toList(), @@ -192,7 +199,7 @@ class SpaceRoomsChunkBase { } @_NameSource('rule override generated') -class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { +class SpaceRoomsChunk implements PublicRoomsChunk, ChildRoomsChunk { SpaceRoomsChunk({ this.avatarUrl, this.canonicalAlias, @@ -201,10 +208,10 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { this.name, required this.numJoinedMembers, required this.roomId, + this.roomType, this.topic, required this.worldReadable, required this.childrenState, - this.roomType, }); SpaceRoomsChunk.fromJson(Map json) @@ -217,19 +224,19 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { name = ((v) => v != null ? v as String : null)(json['name']), numJoinedMembers = json['num_joined_members'] as int, roomId = json['room_id'] as String, + roomType = ((v) => v != null ? v as String : null)(json['room_type']), topic = ((v) => v != null ? v as String : null)(json['topic']), worldReadable = json['world_readable'] as bool, childrenState = (json['children_state'] as List) .map((v) => ChildrenState.fromJson(v)) - .toList(), - roomType = ((v) => v != null ? v as String : null)(json['room_type']); + .toList(); Map toJson() { final avatarUrl = this.avatarUrl; final canonicalAlias = this.canonicalAlias; final joinRule = this.joinRule; final name = this.name; - final topic = this.topic; final roomType = this.roomType; + final topic = this.topic; return { if (avatarUrl != null) 'avatar_url': avatarUrl.toString(), if (canonicalAlias != null) 'canonical_alias': canonicalAlias, @@ -238,10 +245,10 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { if (name != null) 'name': name, 'num_joined_members': numJoinedMembers, 'room_id': roomId, + if (roomType != null) 'room_type': roomType, if (topic != null) 'topic': topic, 'world_readable': worldReadable, 'children_state': childrenState.map((v) => v.toJson()).toList(), - if (roomType != null) 'room_type': roomType, }; } @@ -269,6 +276,9 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { /// The ID of the room. String roomId; + /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. + String? roomType; + /// The topic of the room, if any. String? topic; @@ -280,9 +290,6 @@ class SpaceRoomsChunk implements PublicRoomsChunk, SpaceRoomsChunkBase { /// /// If the room is not a space-room, this should be empty. List childrenState; - - /// The `type` of room (from [`m.room.create`](https://spec.matrix.org/unstable/client-server-api/#mroomcreate)), if any. - String? roomType; } @_NameSource('generated') @@ -313,6 +320,195 @@ class GetSpaceHierarchyResponse { List rooms; } +@_NameSource('rule override generated') +@EnhancedEnum() +enum Direction { + @EnhancedEnumValue(name: 'b') + b, + @EnhancedEnumValue(name: 'f') + f +} + +@_NameSource('generated') +class GetRelatingEventsResponse { + GetRelatingEventsResponse({ + required this.chunk, + this.nextBatch, + this.prevBatch, + }); + + GetRelatingEventsResponse.fromJson(Map json) + : chunk = (json['chunk'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(), + nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), + prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']); + Map toJson() { + final nextBatch = this.nextBatch; + final prevBatch = this.prevBatch; + return { + 'chunk': chunk.map((v) => v.toJson()).toList(), + if (nextBatch != null) 'next_batch': nextBatch, + if (prevBatch != null) 'prev_batch': prevBatch, + }; + } + + /// The child events of the requested event, ordered topologically most-recent first. + List chunk; + + /// An opaque string representing a pagination token. The absence of this token + /// means there are no more results to fetch and the client should stop paginating. + String? nextBatch; + + /// An opaque string representing a pagination token. The absence of this token + /// means this is the start of the result set, i.e. this is the first batch/page. + String? prevBatch; +} + +@_NameSource('generated') +class GetRelatingEventsWithRelTypeResponse { + GetRelatingEventsWithRelTypeResponse({ + required this.chunk, + this.nextBatch, + this.prevBatch, + }); + + GetRelatingEventsWithRelTypeResponse.fromJson(Map json) + : chunk = (json['chunk'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(), + nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), + prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']); + Map toJson() { + final nextBatch = this.nextBatch; + final prevBatch = this.prevBatch; + return { + 'chunk': chunk.map((v) => v.toJson()).toList(), + if (nextBatch != null) 'next_batch': nextBatch, + if (prevBatch != null) 'prev_batch': prevBatch, + }; + } + + /// The child events of the requested event, ordered topologically + /// most-recent first. The events returned will match the `relType` + /// supplied in the URL. + List chunk; + + /// An opaque string representing a pagination token. The absence of this token + /// means there are no more results to fetch and the client should stop paginating. + String? nextBatch; + + /// An opaque string representing a pagination token. The absence of this token + /// means this is the start of the result set, i.e. this is the first batch/page. + String? prevBatch; +} + +@_NameSource('generated') +class GetRelatingEventsWithRelTypeAndEventTypeResponse { + GetRelatingEventsWithRelTypeAndEventTypeResponse({ + required this.chunk, + this.nextBatch, + this.prevBatch, + }); + + GetRelatingEventsWithRelTypeAndEventTypeResponse.fromJson( + Map json) + : chunk = (json['chunk'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(), + nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), + prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']); + Map toJson() { + final nextBatch = this.nextBatch; + final prevBatch = this.prevBatch; + return { + 'chunk': chunk.map((v) => v.toJson()).toList(), + if (nextBatch != null) 'next_batch': nextBatch, + if (prevBatch != null) 'prev_batch': prevBatch, + }; + } + + /// The child events of the requested event, ordered topologically most-recent + /// first. The events returned will match the `relType` and `eventType` supplied + /// in the URL. + List chunk; + + /// An opaque string representing a pagination token. The absence of this token + /// means there are no more results to fetch and the client should stop paginating. + String? nextBatch; + + /// An opaque string representing a pagination token. The absence of this token + /// means this is the start of the result set, i.e. this is the first batch/page. + String? prevBatch; +} + +@_NameSource('generated') +@EnhancedEnum() +enum Include { + @EnhancedEnumValue(name: 'all') + all, + @EnhancedEnumValue(name: 'participated') + participated +} + +@_NameSource('generated') +class GetThreadRootsResponse { + GetThreadRootsResponse({ + required this.chunk, + this.nextBatch, + }); + + GetThreadRootsResponse.fromJson(Map json) + : chunk = (json['chunk'] as List) + .map((v) => MatrixEvent.fromJson(v)) + .toList(), + nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']); + Map toJson() { + final nextBatch = this.nextBatch; + return { + 'chunk': chunk.map((v) => v.toJson()).toList(), + if (nextBatch != null) 'next_batch': nextBatch, + }; + } + + /// The thread roots, ordered by the `latest_event` in each event's aggregation bundle. All events + /// returned include bundled [aggregations](https://spec.matrix.org/unstable/client-server-api/#aggregations). + /// + /// If the thread root event was sent by an [ignored user](https://spec.matrix.org/unstable/client-server-api/#ignoring-users), the + /// event is returned redacted to the caller. This is to simulate the same behaviour of a client doing + /// aggregation locally on the thread. + List chunk; + + /// A token to supply to `from` to keep paginating the responses. Not present when there are + /// no further results. + String? nextBatch; +} + +@_NameSource('generated') +class GetEventByTimestampResponse { + GetEventByTimestampResponse({ + required this.eventId, + required this.originServerTs, + }); + + GetEventByTimestampResponse.fromJson(Map json) + : eventId = json['event_id'] as String, + originServerTs = json['origin_server_ts'] as int; + Map toJson() => { + 'event_id': eventId, + 'origin_server_ts': originServerTs, + }; + + /// The ID of the event found + String eventId; + + /// The event's timestamp, in milliseconds since the Unix epoch. + /// This makes it easy to do a quick comparison to see if the + /// `event_id` fetched is too far out of range to be useful for your + /// use case. + int originServerTs; +} + @_NameSource('rule override generated') @EnhancedEnum() enum ThirdPartyIdentifierMedium { @@ -734,7 +930,8 @@ class Invite3pid { /// The hostname+port of the identity server which should be used for third party identifier lookups. String idServer; - /// The kind of address being passed in the address field, for example `email`. + /// The kind of address being passed in the address field, for example `email` + /// (see [the list of recognised values](https://spec.matrix.org/unstable/appendices/#3pid-types)). String medium; } @@ -996,7 +1193,7 @@ class ClaimKeysResponse { (k, v) => MapEntry( k, (v as Map) - .map((k, v) => MapEntry(k, v as dynamic)))); + .map((k, v) => MapEntry(k, v as Map)))); Map toJson() { final failures = this.failures; return { @@ -1023,7 +1220,7 @@ class ClaimKeysResponse { /// /// If necessary, the claimed key might be a fallback key. Fallback /// keys are re-used by the server until replaced by the device. - Map> oneTimeKeys; + Map>> oneTimeKeys; } @_NameSource('generated') @@ -1151,45 +1348,59 @@ enum LoginType { @_NameSource('generated') class LoginResponse { LoginResponse({ - this.accessToken, - this.deviceId, + required this.accessToken, + required this.deviceId, + this.expiresInMs, this.homeServer, - this.userId, + this.refreshToken, + required this.userId, this.wellKnown, }); LoginResponse.fromJson(Map json) - : accessToken = - ((v) => v != null ? v as String : null)(json['access_token']), - deviceId = ((v) => v != null ? v as String : null)(json['device_id']), + : accessToken = json['access_token'] as String, + deviceId = json['device_id'] as String, + expiresInMs = + ((v) => v != null ? v as int : null)(json['expires_in_ms']), homeServer = ((v) => v != null ? v as String : null)(json['home_server']), - userId = ((v) => v != null ? v as String : null)(json['user_id']), + refreshToken = + ((v) => v != null ? v as String : null)(json['refresh_token']), + userId = json['user_id'] as String, wellKnown = ((v) => v != null ? DiscoveryInformation.fromJson(v) : null)(json['well_known']); Map toJson() { - final accessToken = this.accessToken; - final deviceId = this.deviceId; + final expiresInMs = this.expiresInMs; final homeServer = this.homeServer; - final userId = this.userId; + final refreshToken = this.refreshToken; final wellKnown = this.wellKnown; return { - if (accessToken != null) 'access_token': accessToken, - if (deviceId != null) 'device_id': deviceId, + 'access_token': accessToken, + 'device_id': deviceId, + if (expiresInMs != null) 'expires_in_ms': expiresInMs, if (homeServer != null) 'home_server': homeServer, - if (userId != null) 'user_id': userId, + if (refreshToken != null) 'refresh_token': refreshToken, + 'user_id': userId, if (wellKnown != null) 'well_known': wellKnown.toJson(), }; } /// An access token for the account. /// This access token can then be used to authorize other requests. - String? accessToken; + String accessToken; /// ID of the logged-in device. Will be the same as the /// corresponding parameter in the request, if one was specified. - String? deviceId; + String deviceId; + + /// The lifetime of the access token, in milliseconds. Once + /// the access token has expired a new access token can be + /// obtained by using the provided refresh token. If no + /// refresh token is provided, the client will need to re-log in + /// to obtain a new access token. If not given, the client can + /// assume that the access token will not expire. + int? expiresInMs; /// The server_name of the homeserver on which the account has /// been registered. @@ -1199,8 +1410,13 @@ class LoginResponse { /// it. Note also that `homeserver` is not spelt this way. String? homeServer; + /// A refresh token for the account. This token can be used to + /// obtain a new access token when it expires by calling the + /// `/refresh` endpoint. + String? refreshToken; + /// The fully-qualified Matrix ID for the account. - String? userId; + String userId; /// Optional client configuration provided by the server. If present, /// clients SHOULD use the provided object to reconfigure themselves, @@ -1425,21 +1641,33 @@ class GetPublicRoomsResponse { class PublicRoomQueryFilter { PublicRoomQueryFilter({ this.genericSearchTerm, + this.roomTypes, }); PublicRoomQueryFilter.fromJson(Map json) : genericSearchTerm = ((v) => - v != null ? v as String : null)(json['generic_search_term']); + v != null ? v as String : null)(json['generic_search_term']), + roomTypes = ((v) => v != null + ? (v as List).map((v) => v as String).toList() + : null)(json['room_types']); Map toJson() { final genericSearchTerm = this.genericSearchTerm; + final roomTypes = this.roomTypes; return { if (genericSearchTerm != null) 'generic_search_term': genericSearchTerm, + if (roomTypes != null) 'room_types': roomTypes.map((v) => v).toList(), }; } - /// A string to search for in the room metadata, e.g. name, - /// topic, canonical alias etc. (Optional). + /// An optional string to search for in the room metadata, e.g. name, + /// topic, canonical alias, etc. String? genericSearchTerm; + + /// An optional list of [room types](https://spec.matrix.org/unstable/client-server-api/#types) to search + /// for. To include rooms without a room type, specify `null` within this + /// list. When not specified, all applicable rooms (regardless of type) + /// are returned. + List? roomTypes; } /// A list of the rooms on the server. @@ -1797,6 +2025,44 @@ enum PushRuleKind { underride } +@_NameSource('generated') +class RefreshResponse { + RefreshResponse({ + required this.accessToken, + this.expiresInMs, + this.refreshToken, + }); + + RefreshResponse.fromJson(Map json) + : accessToken = json['access_token'] as String, + expiresInMs = + ((v) => v != null ? v as int : null)(json['expires_in_ms']), + refreshToken = + ((v) => v != null ? v as String : null)(json['refresh_token']); + Map toJson() { + final expiresInMs = this.expiresInMs; + final refreshToken = this.refreshToken; + return { + 'access_token': accessToken, + if (expiresInMs != null) 'expires_in_ms': expiresInMs, + if (refreshToken != null) 'refresh_token': refreshToken, + }; + } + + /// The new access token to use. + String accessToken; + + /// The lifetime of the access token, in milliseconds. If not + /// given, the client can assume that the access token will not + /// expire. + int? expiresInMs; + + /// The new refresh token to use when the access token needs to + /// be refreshed again. If not given, the old refresh token can + /// be re-used. + String? refreshToken; +} + @_NameSource('rule override generated') @EnhancedEnum() enum AccountKind { @@ -1811,7 +2077,9 @@ class RegisterResponse { RegisterResponse({ this.accessToken, this.deviceId, + this.expiresInMs, this.homeServer, + this.refreshToken, required this.userId, }); @@ -1819,17 +2087,25 @@ class RegisterResponse { : accessToken = ((v) => v != null ? v as String : null)(json['access_token']), deviceId = ((v) => v != null ? v as String : null)(json['device_id']), + expiresInMs = + ((v) => v != null ? v as int : null)(json['expires_in_ms']), homeServer = ((v) => v != null ? v as String : null)(json['home_server']), + refreshToken = + ((v) => v != null ? v as String : null)(json['refresh_token']), userId = json['user_id'] as String; Map toJson() { final accessToken = this.accessToken; final deviceId = this.deviceId; + final expiresInMs = this.expiresInMs; final homeServer = this.homeServer; + final refreshToken = this.refreshToken; return { if (accessToken != null) 'access_token': accessToken, if (deviceId != null) 'device_id': deviceId, + if (expiresInMs != null) 'expires_in_ms': expiresInMs, if (homeServer != null) 'home_server': homeServer, + if (refreshToken != null) 'refresh_token': refreshToken, 'user_id': userId, }; } @@ -1844,6 +2120,16 @@ class RegisterResponse { /// Required if the `inhibit_login` option is false. String? deviceId; + /// The lifetime of the access token, in milliseconds. Once + /// the access token has expired a new access token can be + /// obtained by using the provided refresh token. If no + /// refresh token is provided, the client will need to re-log in + /// to obtain a new access token. If not given, the client can + /// assume that the access token will not expire. + /// + /// Omitted if the `inhibit_login` option is true. + int? expiresInMs; + /// The server_name of the homeserver on which the account has /// been registered. /// @@ -1852,6 +2138,13 @@ class RegisterResponse { /// it. Note also that `homeserver` is not spelt this way. String? homeServer; + /// A refresh token for the account. This token can be used to + /// obtain a new access token when it expires by calling the + /// `/refresh` endpoint. + /// + /// Omitted if the `inhibit_login` option is true. + String? refreshToken; + /// The fully-qualified Matrix user ID (MXID) that has been registered. /// /// Any user ID returned by this API must conform to the grammar given in the @@ -2161,15 +2454,6 @@ enum Membership { leave } -@_NameSource('rule override generated') -@EnhancedEnum() -enum Direction { - @EnhancedEnumValue(name: 'b') - b, - @EnhancedEnumValue(name: 'f') - f -} - /// A list of messages with a new token to request more. @_NameSource('generated') class GetRoomEventsResponse { @@ -2237,8 +2521,12 @@ class GetRoomEventsResponse { @_NameSource('generated') @EnhancedEnum() enum ReceiptType { + @EnhancedEnumValue(name: 'm.fully_read') + mFullyRead, @EnhancedEnumValue(name: 'm.read') - mRead + mRead, + @EnhancedEnumValue(name: 'm.read.private') + mReadPrivate } @_NameSource('spec') @@ -2344,6 +2632,7 @@ class RoomEventFilter { this.lazyLoadMembers, this.notRooms, this.rooms, + this.unreadThreadNotifications, }); RoomEventFilter.fromJson(Map json) @@ -2358,13 +2647,16 @@ class RoomEventFilter { : null)(json['not_rooms']), rooms = ((v) => v != null ? (v as List).map((v) => v as String).toList() - : null)(json['rooms']); + : null)(json['rooms']), + unreadThreadNotifications = ((v) => + v != null ? v as bool : null)(json['unread_thread_notifications']); Map toJson() { final containsUrl = this.containsUrl; final includeRedundantMembers = this.includeRedundantMembers; final lazyLoadMembers = this.lazyLoadMembers; final notRooms = this.notRooms; final rooms = this.rooms; + final unreadThreadNotifications = this.unreadThreadNotifications; return { if (containsUrl != null) 'contains_url': containsUrl, if (includeRedundantMembers != null) @@ -2372,6 +2664,8 @@ class RoomEventFilter { if (lazyLoadMembers != null) 'lazy_load_members': lazyLoadMembers, if (notRooms != null) 'not_rooms': notRooms.map((v) => v).toList(), if (rooms != null) 'rooms': rooms.map((v) => v).toList(), + if (unreadThreadNotifications != null) + 'unread_thread_notifications': unreadThreadNotifications, }; } @@ -2395,6 +2689,10 @@ class RoomEventFilter { /// A list of room IDs to include. If this list is absent then all rooms are included. List? rooms; + + /// If `true`, enables per-[thread](https://spec.matrix.org/unstable/client-server-api/#threading) notification + /// counts. Only applies to the `/sync` endpoint. Defaults to `false`. + bool? unreadThreadNotifications; } @_NameSource('rule override generated') @@ -2410,6 +2708,7 @@ class SearchFilter implements EventFilter, RoomEventFilter { this.lazyLoadMembers, this.notRooms, this.rooms, + this.unreadThreadNotifications, }); SearchFilter.fromJson(Map json) @@ -2437,7 +2736,9 @@ class SearchFilter implements EventFilter, RoomEventFilter { : null)(json['not_rooms']), rooms = ((v) => v != null ? (v as List).map((v) => v as String).toList() - : null)(json['rooms']); + : null)(json['rooms']), + unreadThreadNotifications = ((v) => + v != null ? v as bool : null)(json['unread_thread_notifications']); Map toJson() { final limit = this.limit; final notSenders = this.notSenders; @@ -2449,6 +2750,7 @@ class SearchFilter implements EventFilter, RoomEventFilter { final lazyLoadMembers = this.lazyLoadMembers; final notRooms = this.notRooms; final rooms = this.rooms; + final unreadThreadNotifications = this.unreadThreadNotifications; return { if (limit != null) 'limit': limit, if (notSenders != null) 'not_senders': notSenders.map((v) => v).toList(), @@ -2461,6 +2763,8 @@ class SearchFilter implements EventFilter, RoomEventFilter { if (lazyLoadMembers != null) 'lazy_load_members': lazyLoadMembers, if (notRooms != null) 'not_rooms': notRooms.map((v) => v).toList(), if (rooms != null) 'rooms': rooms.map((v) => v).toList(), + if (unreadThreadNotifications != null) + 'unread_thread_notifications': unreadThreadNotifications, }; } @@ -2499,6 +2803,10 @@ class SearchFilter implements EventFilter, RoomEventFilter { /// A list of room IDs to include. If this list is absent then all rooms are included. List? rooms; + + /// If `true`, enables per-[thread](https://spec.matrix.org/unstable/client-server-api/#threading) notification + /// counts. Only applies to the `/sync` endpoint. Defaults to `false`. + bool? unreadThreadNotifications; } @_NameSource('rule override generated') @@ -3145,6 +3453,7 @@ class StateFilter implements EventFilter, RoomEventFilter { this.lazyLoadMembers, this.notRooms, this.rooms, + this.unreadThreadNotifications, }); StateFilter.fromJson(Map json) @@ -3172,7 +3481,9 @@ class StateFilter implements EventFilter, RoomEventFilter { : null)(json['not_rooms']), rooms = ((v) => v != null ? (v as List).map((v) => v as String).toList() - : null)(json['rooms']); + : null)(json['rooms']), + unreadThreadNotifications = ((v) => + v != null ? v as bool : null)(json['unread_thread_notifications']); Map toJson() { final limit = this.limit; final notSenders = this.notSenders; @@ -3184,6 +3495,7 @@ class StateFilter implements EventFilter, RoomEventFilter { final lazyLoadMembers = this.lazyLoadMembers; final notRooms = this.notRooms; final rooms = this.rooms; + final unreadThreadNotifications = this.unreadThreadNotifications; return { if (limit != null) 'limit': limit, if (notSenders != null) 'not_senders': notSenders.map((v) => v).toList(), @@ -3196,6 +3508,8 @@ class StateFilter implements EventFilter, RoomEventFilter { if (lazyLoadMembers != null) 'lazy_load_members': lazyLoadMembers, if (notRooms != null) 'not_rooms': notRooms.map((v) => v).toList(), if (rooms != null) 'rooms': rooms.map((v) => v).toList(), + if (unreadThreadNotifications != null) + 'unread_thread_notifications': unreadThreadNotifications, }; } @@ -3234,6 +3548,10 @@ class StateFilter implements EventFilter, RoomEventFilter { /// A list of room IDs to include. If this list is absent then all rooms are included. List? rooms; + + /// If `true`, enables per-[thread](https://spec.matrix.org/unstable/client-server-api/#threading) notification + /// counts. Only applies to the `/sync` endpoint. Defaults to `false`. + bool? unreadThreadNotifications; } @_NameSource('spec') @@ -3287,7 +3605,7 @@ class RoomFilter { /// The per user account data to include for rooms. StateFilter? accountData; - /// The events that aren't recorded in the room history, e.g. typing and receipts, to include for rooms. + /// The ephemeral events to include for rooms. These are the events that appear in the `ephemeral` property in the `/sync` response. StateFilter? ephemeral; /// Include rooms that the user has left in the sync, default false diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index fe5a69b4..bfef3cb4 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -979,7 +979,6 @@ void main() { '!localpart:example.com', ReceiptType.mRead, '\$1234:example.com', - {}, ); matrixApi.homeserver = matrixApi.accessToken = null; @@ -990,7 +989,7 @@ void main() { await matrixApi.setReadMarker( '!localpart:example.com', - '\$1234:example.com', + mFullyRead: '\$1234:example.com', mRead: '\$1234:example.com', ); From ab0403657d14fe05868c908b88bd39394170ab73 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 17 Apr 2023 12:05:11 +0200 Subject: [PATCH 153/174] chore: Bump version to 1.6 to reflect spec update --- CHANGELOG.md | 16 ++++++++++++++++ pubspec.yaml | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8a081e5..576d2f59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,23 +1,37 @@ +## [1.6.0] - 17th Apr 2023 + +This release updates to version 1.6 of the Matrix specification. Users might +need to update their read receipt calls to the API changes. + +- feat: Upgrade to spec 1.6 + ## [1.1.10] - 27th Jan 2023 + - chore: Update enhanced_enum to 0.2.4 ## [1.1.9] - 7th Nov 2022 + - feat: Allow converting of stacktraces in logs ## [1.1.8] - 29th Aug 2022 + - fix: Edge case where MatrixException.error differs from errcode - chore: add pushrules to the event types ## [1.1.7] - 29th Aug 2022 + - fix: Parsing of MatrixException parameters ## [1.1.6] - 26th Aug 2022 + - fix: Fixed missing .pub-cache folder creation in .gitlab-ci.yml ## [1.1.5] - 25th Aug 2022 + - fix: Fixed dysfunctional key-verification (Emoji+manual) ## [1.1.4] - 25th Aug 2022 + - Revert "fix: Secret storage keys are used as account data but are not uri encoded" - chore: disable dynamic calls (Nicolas Werner) - chore: export filter map extension (Nicolas Werner) @@ -27,10 +41,12 @@ - chore: upgrade from pedantic to lints (Nicolas Werner) ## [1.1.3] - 2nd Aug 2022 + - fix: Secret storage keys are used as account data but are not uri encoded - chore: export filter map extension ## [1.1.2] - 2nd Aug 2022 + - feat: Add a flag to disable colors in logs ## 1.1.1 diff --git a/pubspec.yaml b/pubspec.yaml index ceee2efc..95328d0c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.1.10 +version: 1.6.0 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From b95edec462e5d3a1a21f467d3e0cc0a1746100a6 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 17 Apr 2023 16:54:43 +0200 Subject: [PATCH 154/174] fix: Update the generated enum files --- CHANGELOG.md | 7 ++ lib/src/generated/model.g.dart | 137 +++++++++++++++++++++++---------- pubspec.yaml | 2 +- 3 files changed, 104 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 576d2f59..a40bf5ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.6.1] - 17th Apr 2023 + +Fixes a small issue in the last release, where some enhanced enums were not +updated and as such missing a few members. + +- fix: Update the generated enum files + ## [1.6.0] - 17th Apr 2023 This release updates to version 1.6 of the Matrix specification. Users might diff --git a/lib/src/generated/model.g.dart b/lib/src/generated/model.g.dart index b5f907e3..08265a66 100644 --- a/lib/src/generated/model.g.dart +++ b/lib/src/generated/model.g.dart @@ -6,6 +6,88 @@ part of 'model.dart'; // EnhancedEnumGenerator // ************************************************************************** +extension DirectionFromStringExtension on Iterable { + Direction? fromString(String val) { + final override = { + 'b': Direction.b, + 'f': Direction.f, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension DirectionEnhancedEnum on Direction { + @override +// ignore: override_on_non_overriding_member + String get name => { + Direction.b: 'b', + Direction.f: 'f', + }[this]!; + bool get isB => this == Direction.b; + bool get isF => this == Direction.f; + T when({ + required T Function() b, + required T Function() f, + }) => + { + Direction.b: b, + Direction.f: f, + }[this]!(); + T maybeWhen({ + T? Function()? b, + T? Function()? f, + required T Function() orElse, + }) => + { + Direction.b: b, + Direction.f: f, + }[this] + ?.call() ?? + orElse(); +} + +extension IncludeFromStringExtension on Iterable { + Include? fromString(String val) { + final override = { + 'all': Include.all, + 'participated': Include.participated, + }[val]; +// ignore: unnecessary_this + return this.contains(override) ? override : null; + } +} + +extension IncludeEnhancedEnum on Include { + @override +// ignore: override_on_non_overriding_member + String get name => { + Include.all: 'all', + Include.participated: 'participated', + }[this]!; + bool get isAll => this == Include.all; + bool get isParticipated => this == Include.participated; + T when({ + required T Function() all, + required T Function() participated, + }) => + { + Include.all: all, + Include.participated: participated, + }[this]!(); + T maybeWhen({ + T? Function()? all, + T? Function()? participated, + required T Function() orElse, + }) => + { + Include.all: all, + Include.participated: participated, + }[this] + ?.call() ?? + orElse(); +} + extension ThirdPartyIdentifierMediumFromStringExtension on Iterable { ThirdPartyIdentifierMedium? fromString(String val) { @@ -514,51 +596,12 @@ extension MembershipEnhancedEnum on Membership { orElse(); } -extension DirectionFromStringExtension on Iterable { - Direction? fromString(String val) { - final override = { - 'b': Direction.b, - 'f': Direction.f, - }[val]; -// ignore: unnecessary_this - return this.contains(override) ? override : null; - } -} - -extension DirectionEnhancedEnum on Direction { - @override -// ignore: override_on_non_overriding_member - String get name => { - Direction.b: 'b', - Direction.f: 'f', - }[this]!; - bool get isB => this == Direction.b; - bool get isF => this == Direction.f; - T when({ - required T Function() b, - required T Function() f, - }) => - { - Direction.b: b, - Direction.f: f, - }[this]!(); - T maybeWhen({ - T? Function()? b, - T? Function()? f, - required T Function() orElse, - }) => - { - Direction.b: b, - Direction.f: f, - }[this] - ?.call() ?? - orElse(); -} - extension ReceiptTypeFromStringExtension on Iterable { ReceiptType? fromString(String val) { final override = { + 'm.fully_read': ReceiptType.mFullyRead, 'm.read': ReceiptType.mRead, + 'm.read.private': ReceiptType.mReadPrivate, }[val]; // ignore: unnecessary_this return this.contains(override) ? override : null; @@ -569,21 +612,33 @@ extension ReceiptTypeEnhancedEnum on ReceiptType { @override // ignore: override_on_non_overriding_member String get name => { + ReceiptType.mFullyRead: 'm.fully_read', ReceiptType.mRead: 'm.read', + ReceiptType.mReadPrivate: 'm.read.private', }[this]!; + bool get isMFullyRead => this == ReceiptType.mFullyRead; bool get isMRead => this == ReceiptType.mRead; + bool get isMReadPrivate => this == ReceiptType.mReadPrivate; T when({ + required T Function() mFullyRead, required T Function() mRead, + required T Function() mReadPrivate, }) => { + ReceiptType.mFullyRead: mFullyRead, ReceiptType.mRead: mRead, + ReceiptType.mReadPrivate: mReadPrivate, }[this]!(); T maybeWhen({ + T? Function()? mFullyRead, T? Function()? mRead, + T? Function()? mReadPrivate, required T Function() orElse, }) => { + ReceiptType.mFullyRead: mFullyRead, ReceiptType.mRead: mRead, + ReceiptType.mReadPrivate: mReadPrivate, }[this] ?.call() ?? orElse(); diff --git a/pubspec.yaml b/pubspec.yaml index 95328d0c..ab670998 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.6.0 +version: 1.6.1 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From a1e8971c39ce6e044500b1a8b565be38435b7622 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 8 May 2023 14:47:10 +0200 Subject: [PATCH 155/174] ci: Use the ci template --- .gitlab-ci.yml | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1fe91d72..0997dd7a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,28 +1,18 @@ -stages: - - coverage - - publish +include: + project: "famedly/company/frontend/ci-templates" + file: "all.yml" test: tags: - linux - stage: coverage + stage: test image: dart script: - dart pub get - dart pub run test - -code_analyze: - tags: - - docker - stage: coverage - image: cirrusci/flutter - dependencies: [] - script: - - flutter format lib/ test/ --set-exit-if-changed - - flutter analyze dry-run: - stage: publish + stage: deploy image: dart script: - rm -rf ./docs @@ -30,7 +20,7 @@ dry-run: - dart pub publish --dry-run pub-dev: - stage: publish + stage: deploy image: dart dependencies: [dry-run] script: From 53fbe4f7ef4fc1f94e37dc13dc777b35d9596e15 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 8 May 2023 14:49:34 +0200 Subject: [PATCH 156/174] chore: sort imports --- lib/fake_matrix_api.dart | 1 + lib/src/generated/api.dart | 26 +++++++++---------- lib/src/generated/model.dart | 11 ++++---- lib/src/model/events/image_pack_content.dart | 2 +- .../model/events/room_encrypted_content.dart | 1 - lib/src/model/matrix_exception.dart | 1 + lib/src/utils/print_logs_web.dart | 3 ++- pubspec.yaml | 1 + test/event_content_test.dart | 3 ++- test/map_copy_extension_test.dart | 3 ++- test/matrix_api_test.dart | 3 ++- test/try_get_map_extension_test.dart | 3 ++- 12 files changed, 33 insertions(+), 25 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 3a63be40..fc32738f 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -27,6 +27,7 @@ import 'dart:math'; import 'package:http/http.dart'; import 'package:http/testing.dart'; + import 'package:matrix_api_lite/matrix_api_lite.dart'; Map decodeJson(dynamic data) { diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index c0e63c86..89164749 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -1,19 +1,19 @@ -import '../model/auth/authentication_data.dart'; -import '../model/auth/authentication_types.dart'; -import '../model/auth/authentication_identifier.dart'; -import '../model/matrix_keys.dart'; -import '../model/sync_update.dart'; -import '../model/matrix_event.dart'; -import '../model/children_state.dart'; - -import 'model.dart'; -import 'fixed_model.dart'; -import 'internal.dart'; - -import 'package:http/http.dart'; import 'dart:convert'; import 'dart:typed_data'; +import 'package:http/http.dart'; + +import '../model/auth/authentication_data.dart'; +import '../model/auth/authentication_identifier.dart'; +import '../model/auth/authentication_types.dart'; +import '../model/children_state.dart'; +import '../model/matrix_event.dart'; +import '../model/matrix_keys.dart'; +import '../model/sync_update.dart'; +import 'fixed_model.dart'; +import 'internal.dart'; +import 'model.dart'; + class Api { Client httpClient; Uri? baseUri; diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index 5b355f2d..a4341e68 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -1,13 +1,14 @@ +import 'package:enhanced_enum/enhanced_enum.dart'; + import '../model/auth/authentication_data.dart'; -import '../model/auth/authentication_types.dart'; import '../model/auth/authentication_identifier.dart'; +import '../model/auth/authentication_types.dart'; +import '../model/children_state.dart'; +import '../model/matrix_event.dart'; import '../model/matrix_keys.dart'; import '../model/sync_update.dart'; -import '../model/matrix_event.dart'; -import '../model/children_state.dart'; - import 'internal.dart'; -import 'package:enhanced_enum/enhanced_enum.dart'; + part 'model.g.dart'; class _NameSource { diff --git a/lib/src/model/events/image_pack_content.dart b/lib/src/model/events/image_pack_content.dart index a7cbdf37..4365f0ea 100644 --- a/lib/src/model/events/image_pack_content.dart +++ b/lib/src/model/events/image_pack_content.dart @@ -21,9 +21,9 @@ * SOFTWARE. */ -import '../basic_event.dart'; import '../../utils/filter_map_extension.dart'; import '../../utils/try_get_map_extension.dart'; +import '../basic_event.dart'; extension ImagePackContentBasicEventExtension on BasicEvent { ImagePackContent get parsedImagePackContent => diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 48dc6e24..7d4ef4b0 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -22,7 +22,6 @@ */ import 'package:matrix_api_lite/src/utils/logs.dart'; - import '../../utils/filter_map_extension.dart'; import '../../utils/try_get_map_extension.dart'; import '../basic_event.dart'; diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 48231e3e..0f20c674 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -24,6 +24,7 @@ import 'dart:convert'; import 'package:http/http.dart' as http; + import 'package:matrix_api_lite/matrix_api_lite.dart'; enum MatrixError { diff --git a/lib/src/utils/print_logs_web.dart b/lib/src/utils/print_logs_web.dart index aa7c6e0f..f13f0311 100644 --- a/lib/src/utils/print_logs_web.dart +++ b/lib/src/utils/print_logs_web.dart @@ -1,6 +1,7 @@ -import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'dart:html'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; + extension PrintLogs on LogEvent { void printOut() { var logsStr = '[Matrix] $title'; diff --git a/pubspec.yaml b/pubspec.yaml index ab670998..594d94c9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,5 +16,6 @@ dependencies: dev_dependencies: build_runner: ^2.1.8 enhanced_enum_generator: ^0.2.4 + import_sorter: ^4.6.0 lints: ^2.0.0 test: ^1.14.4 diff --git a/test/event_content_test.dart b/test/event_content_test.dart index 3b5bf6d4..b6124ce7 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -23,9 +23,10 @@ import 'dart:convert'; -import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; + void main() { group('Event Content tests', () { test('Room Encryption Content', () { diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart index 3578c624..188a18ee 100644 --- a/test/map_copy_extension_test.dart +++ b/test/map_copy_extension_test.dart @@ -21,9 +21,10 @@ * SOFTWARE. */ -import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; + void main() { group('Map-copy-extension', () { test('it should work', () { diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index bfef3cb4..0306ad28 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -23,9 +23,10 @@ import 'dart:typed_data'; +import 'package:test/test.dart'; + import 'package:matrix_api_lite/fake_matrix_api.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; -import 'package:test/test.dart'; const emptyRequest = {}; diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index c31e78e4..13e60c51 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -21,9 +21,10 @@ * SOFTWARE. */ -import 'package:matrix_api_lite/matrix_api_lite.dart'; import 'package:test/test.dart'; +import 'package:matrix_api_lite/matrix_api_lite.dart'; + void main() { group('Try-get-map-extension', () { Logs().level = Level.verbose; From cf984d61f9beda8aa277e9bc4ab13138327df243 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Wed, 7 Jun 2023 17:37:09 +0200 Subject: [PATCH 157/174] chore: generated folder from recent dart_openapi_codegen --- lib/src/generated/api.dart | 272 ++++++----- lib/src/generated/model.dart | 846 +++++++++++++++++++++-------------- 2 files changed, 659 insertions(+), 459 deletions(-) diff --git a/lib/src/generated/api.dart b/lib/src/generated/api.dart index 89164749..77390b0f 100644 --- a/lib/src/generated/api.dart +++ b/lib/src/generated/api.dart @@ -40,7 +40,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return DiscoveryInformation.fromJson(json); + return DiscoveryInformation.fromJson(json as Map); } /// Queries the server to determine if a given registration token is still @@ -116,7 +116,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetSpaceHierarchyResponse.fromJson(json); + return GetSpaceHierarchyResponse.fromJson(json as Map); } /// Retrieve all of the child events for a given parent event. @@ -174,7 +174,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetRelatingEventsResponse.fromJson(json); + return GetRelatingEventsResponse.fromJson(json as Map); } /// Retrieve all of the child events for a given parent event which relate to the parent @@ -235,7 +235,8 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetRelatingEventsWithRelTypeResponse.fromJson(json); + return GetRelatingEventsWithRelTypeResponse.fromJson( + json as Map); } /// Retrieve all of the child events for a given parent event which relate to the parent @@ -302,7 +303,8 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetRelatingEventsWithRelTypeAndEventTypeResponse.fromJson(json); + return GetRelatingEventsWithRelTypeAndEventTypeResponse.fromJson( + json as Map); } /// Paginates over the thread roots in a room, ordered by the `latest_event` of each thread root @@ -338,7 +340,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetThreadRootsResponse.fromJson(json); + return GetThreadRootsResponse.fromJson(json as Map); } /// Get the ID of the event closest to the given timestamp, in the @@ -387,7 +389,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetEventByTimestampResponse.fromJson(json); + return GetEventByTimestampResponse.fromJson(json as Map); } /// Gets a list of the third party identifiers that the homeserver has @@ -399,7 +401,8 @@ class Api { /// Identifiers in this list may be used by the homeserver as, for example, /// identifiers that it will accept to reset the user's account password. /// - /// returns `threepids` + /// returns `threepids`: + /// Future?> getAccount3PIDs() async { final requestUri = Uri(path: '_matrix/client/v3/account/3pid'); final request = Request('GET', baseUri!.resolveUri(requestUri)); @@ -410,7 +413,10 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return ((v) => v != null - ? (v as List).map((v) => ThirdPartyIdentifier.fromJson(v)).toList() + ? (v as List) + .map( + (v) => ThirdPartyIdentifier.fromJson(v as Map)) + .toList() : null)(json['threepids']); } @@ -454,7 +460,8 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return ((v) => v != null ? Uri.parse(v) : null)(json['submit_url']); + return ((v) => + v != null ? Uri.parse(v as String) : null)(json['submit_url']); } /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api). @@ -566,7 +573,7 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return IdServerUnbindResult.values - .fromString(json['id_server_unbind_result'])!; + .fromString(json['id_server_unbind_result'] as String)!; } /// The homeserver must check that the given email address is **not** @@ -631,7 +638,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RequestTokenResponse.fromJson(json); + return RequestTokenResponse.fromJson(json as Map); } /// The homeserver must check that the given phone number is **not** @@ -699,7 +706,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RequestTokenResponse.fromJson(json); + return RequestTokenResponse.fromJson(json as Map); } /// Removes a user's third party identifier from the provided identity server @@ -742,7 +749,7 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return IdServerUnbindResult.values - .fromString(json['id_server_unbind_result'])!; + .fromString(json['id_server_unbind_result'] as String)!; } /// Deactivate the user's account, removing all ability for the user to @@ -794,7 +801,7 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return IdServerUnbindResult.values - .fromString(json['id_server_unbind_result'])!; + .fromString(json['id_server_unbind_result'] as String)!; } /// Changes the password for an account on this homeserver. @@ -908,7 +915,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RequestTokenResponse.fromJson(json); + return RequestTokenResponse.fromJson(json as Map); } /// The homeserver must check that the given phone number **is @@ -983,7 +990,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RequestTokenResponse.fromJson(json); + return RequestTokenResponse.fromJson(json as Map); } /// Gets information about the owner of a given access token. @@ -1003,7 +1010,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return TokenOwnerInfo.fromJson(json); + return TokenOwnerInfo.fromJson(json as Map); } /// Gets information about a particular user. @@ -1023,7 +1030,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return WhoIsInfo.fromJson(json); + return WhoIsInfo.fromJson(json as Map); } /// Gets information about the server's supported feature set @@ -1041,7 +1048,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return Capabilities.fromJson(json['capabilities']); + return Capabilities.fromJson(json['capabilities'] as Map); } /// Create a new room with various configuration options. @@ -1157,13 +1164,13 @@ class Api { /// returns `room_id`: /// The created room's ID. Future createRoom( - {Map? creationContent, + {Map? creationContent, List? initialState, List? invite, List? invite3pid, bool? isDirect, String? name, - Map? powerLevelContentOverride, + Map? powerLevelContentOverride, CreateRoomPreset? preset, String? roomAliasName, String? roomVersion, @@ -1238,7 +1245,9 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return ((v) => v != null - ? (v as List).map((v) => Device.fromJson(v)).toList() + ? (v as List) + .map((v) => Device.fromJson(v as Map)) + .toList() : null)(json['devices']); } @@ -1280,7 +1289,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return Device.fromJson(json); + return Device.fromJson(json as Map); } /// Updates the metadata on the given device. @@ -1324,7 +1333,7 @@ class Api { /// /// [visibility] Whether the room should be visible (public) in the directory /// or not (private). - Future> updateAppserviceRoomDirectoryVisibility( + Future> updateAppserviceRoomDirectoryVisibility( String networkId, String roomId, Visibility visibility) async { final requestUri = Uri( path: @@ -1340,7 +1349,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return json as Map; + return json as Map; } /// Gets the visibility of a given room on the server's public room directory. @@ -1359,8 +1368,9 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return ((v) => v != null ? Visibility.values.fromString(v)! : null)( - json['visibility']); + return ((v) => v != null + ? Visibility.values.fromString(v as String)! + : null)(json['visibility']); } /// Sets the visibility of a given room in the server's public room @@ -1441,10 +1451,10 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetRoomIdByAliasResponse.fromJson(json); + return GetRoomIdByAliasResponse.fromJson(json as Map); } - /// setRoomAlias + /// /// /// [roomAlias] The room alias to set. Its format is defined /// [in the appendices](https://spec.matrix.org/unstable/appendices/#room-aliases). @@ -1494,7 +1504,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetEventsResponse.fromJson(json); + return GetEventsResponse.fromJson(json as Map); } /// This will listen for new events related to a particular room and return @@ -1528,7 +1538,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PeekEventsResponse.fromJson(json); + return PeekEventsResponse.fromJson(json as Map); } /// Get a single event based on `event_id`. You must have permission to @@ -1551,7 +1561,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return MatrixEvent.fromJson(json); + return MatrixEvent.fromJson(json as Map); } /// *Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`. @@ -1654,7 +1664,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetKeysChangesResponse.fromJson(json); + return GetKeysChangesResponse.fromJson(json as Map); } /// Claims one-time keys for use in pre-key messages. @@ -1681,7 +1691,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return ClaimKeysResponse.fromJson(json); + return ClaimKeysResponse.fromJson(json as Map); } /// Publishes cross-signing keys for the user. @@ -1756,7 +1766,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return QueryKeysResponse.fromJson(json); + return QueryKeysResponse.fromJson(json as Map); } /// Publishes cross-signing signatures for the user. The request body is a @@ -1768,9 +1778,9 @@ class Api { /// A map from user ID to key ID to an error for any signatures /// that failed. If a signature was invalid, the `errcode` will /// be set to `M_INVALID_SIGNATURE`. - Future>>?> + Future>>?> uploadCrossSigningSignatures( - Map>> signatures) async { + Map>> signatures) async { final requestUri = Uri(path: '_matrix/client/v3/keys/signatures/upload'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; @@ -1783,10 +1793,10 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return ((v) => v != null - ? (v as Map).map((k, v) => MapEntry( + ? (v as Map).map((k, v) => MapEntry( k, - (v as Map) - .map((k, v) => MapEntry(k, v as Map)))) + (v as Map) + .map((k, v) => MapEntry(k, v as Map)))) : null)(json['failures']); } @@ -1852,7 +1862,9 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return ((v) => v != null - ? (v as List).map((v) => LoginFlow.fromJson(v)).toList() + ? (v as List) + .map((v) => LoginFlow.fromJson(v as Map)) + .toList() : null)(json['flows']); } @@ -1924,7 +1936,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return LoginResponse.fromJson(json); + return LoginResponse.fromJson(json as Map); } /// Invalidates an existing access token, so that it can no longer be used for @@ -1991,7 +2003,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetNotificationsResponse.fromJson(json); + return GetNotificationsResponse.fromJson(json as Map); } /// Get the given user's presence state. @@ -2008,7 +2020,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetPresenceResponse.fromJson(json); + return GetPresenceResponse.fromJson(json as Map); } /// This API sets the given user's presence state. When setting the status, @@ -2056,7 +2068,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return ProfileInformation.fromJson(json); + return ProfileInformation.fromJson(json as Map); } /// Get the user's avatar URL. This API may be used to fetch the user's @@ -2077,7 +2089,8 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']); + return ((v) => + v != null ? Uri.parse(v as String) : null)(json['avatar_url']); } /// This API sets the given user's avatar URL. You must have permission to @@ -2177,7 +2190,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetPublicRoomsResponse.fromJson(json); + return GetPublicRoomsResponse.fromJson(json as Map); } /// Lists the public rooms on the server, with optional filter. @@ -2230,7 +2243,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return QueryPublicRoomsResponse.fromJson(json); + return QueryPublicRoomsResponse.fromJson(json as Map); } /// Gets all currently active pushers for the authenticated user. @@ -2247,7 +2260,9 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return ((v) => v != null - ? (v as List).map((v) => Pusher.fromJson(v)).toList() + ? (v as List) + .map((v) => Pusher.fromJson(v as Map)) + .toList() : null)(json['pushers']); } @@ -2267,7 +2282,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PushRuleSet.fromJson(json['global']); + return PushRuleSet.fromJson(json['global'] as Map); } /// This endpoint removes the push rule defined in the path. @@ -2315,7 +2330,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return PushRule.fromJson(json); + return PushRule.fromJson(json as Map); } /// This endpoint allows the creation and modification of user defined push @@ -2361,7 +2376,7 @@ class Api { /// /// [pattern] Only applicable to `content` rules. The glob-style pattern to match against. Future setPushRule( - String scope, PushRuleKind kind, String ruleId, List actions, + String scope, PushRuleKind kind, String ruleId, List actions, {String? before, String? after, List? conditions, @@ -2403,7 +2418,7 @@ class Api { /// /// returns `actions`: /// The action(s) to perform for this rule. - Future> getPushRuleActions( + Future> getPushRuleActions( String scope, PushRuleKind kind, String ruleId) async { final requestUri = Uri( path: @@ -2415,7 +2430,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return (json['actions'] as List).map((v) => v as dynamic).toList(); + return (json['actions'] as List).map((v) => v as Object?).toList(); } /// This endpoint allows clients to change the actions of a push rule. @@ -2431,7 +2446,7 @@ class Api { /// /// [actions] The action(s) to perform for this rule. Future setPushRuleActions(String scope, PushRuleKind kind, - String ruleId, List actions) async { + String ruleId, List actions) async { final requestUri = Uri( path: '_matrix/client/v3/pushrules/${Uri.encodeComponent(scope)}/${Uri.encodeComponent(kind.name)}/${Uri.encodeComponent(ruleId)}/actions'); @@ -2538,7 +2553,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RefreshResponse.fromJson(json); + return RefreshResponse.fromJson(json as Map); } /// This API endpoint uses the [User-Interactive Authentication API](https://spec.matrix.org/unstable/client-server-api/#user-interactive-authentication-api), except in @@ -2636,7 +2651,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RegisterResponse.fromJson(json); + return RegisterResponse.fromJson(json as Map); } /// Checks to see if a username is available, and valid, for the server. @@ -2729,7 +2744,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RequestTokenResponse.fromJson(json); + return RequestTokenResponse.fromJson(json as Map); } /// The homeserver must check that the given phone number is **not** @@ -2793,7 +2808,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RequestTokenResponse.fromJson(json); + return RequestTokenResponse.fromJson(json as Map); } /// Delete the keys from the backup. @@ -2811,7 +2826,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RoomKeysUpdateResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json as Map); } /// Retrieve the keys from the backup. @@ -2829,7 +2844,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RoomKeys.fromJson(json); + return RoomKeys.fromJson(json as Map); } /// Store several keys in the backup. @@ -2852,7 +2867,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RoomKeysUpdateResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json as Map); } /// Delete the keys from the backup for a given room. @@ -2874,7 +2889,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RoomKeysUpdateResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json as Map); } /// Retrieve the keys from the backup for a given room. @@ -2896,7 +2911,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RoomKeyBackup.fromJson(json); + return RoomKeyBackup.fromJson(json as Map); } /// Store several keys in the backup for a given room. @@ -2922,7 +2937,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RoomKeysUpdateResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json as Map); } /// Delete a key from the backup. @@ -2947,7 +2962,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RoomKeysUpdateResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json as Map); } /// Retrieve a key from the backup. @@ -2972,7 +2987,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return KeyBackupData.fromJson(json); + return KeyBackupData.fromJson(json as Map); } /// Store a key in the backup. @@ -3001,7 +3016,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return RoomKeysUpdateResponse.fromJson(json); + return RoomKeysUpdateResponse.fromJson(json as Map); } /// Get information about the latest backup version. @@ -3014,7 +3029,8 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetRoomKeysVersionCurrentResponse.fromJson(json); + return GetRoomKeysVersionCurrentResponse.fromJson( + json as Map); } /// Creates a new backup. @@ -3028,7 +3044,7 @@ class Api { /// returns `version`: /// The backup version. This is an opaque string. Future postRoomKeysVersion( - BackupAlgorithm algorithm, Map authData) async { + BackupAlgorithm algorithm, Map authData) async { final requestUri = Uri(path: '_matrix/client/v3/room_keys/version'); final request = Request('POST', baseUri!.resolveUri(requestUri)); request.headers['authorization'] = 'Bearer ${bearerToken!}'; @@ -3083,7 +3099,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetRoomKeysVersionResponse.fromJson(json); + return GetRoomKeysVersionResponse.fromJson(json as Map); } /// Update information about an existing backup. Only `auth_data` can be modified. @@ -3099,8 +3115,8 @@ class Api { /// [authData] Algorithm-dependent data. See the documentation for the backup /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the /// expected format of the data. - Future> putRoomKeysVersion(String version, - BackupAlgorithm algorithm, Map authData) async { + Future> putRoomKeysVersion(String version, + BackupAlgorithm algorithm, Map authData) async { final requestUri = Uri( path: '_matrix/client/v3/room_keys/version/${Uri.encodeComponent(version)}'); @@ -3116,7 +3132,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return json as Map; + return json as Map; } /// Get a list of aliases maintained by the local server for the @@ -3221,7 +3237,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return EventContext.fromJson(json); + return EventContext.fromJson(json as Map); } /// Get a single event based on `roomId/eventId`. You must have permission to @@ -3241,7 +3257,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return MatrixEvent.fromJson(json); + return MatrixEvent.fromJson(json as Map); } /// This API stops a user remembering about a particular room. @@ -3443,8 +3459,8 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, RoomMember.fromJson(v))) + ? (v as Map).map((k, v) => + MapEntry(k, RoomMember.fromJson(v as Map))) : null)(json['joined']); } @@ -3530,7 +3546,8 @@ class Api { /// [notMembership] The kind of membership to exclude from the results. Defaults to no /// filtering if unspecified. /// - /// returns `chunk` + /// returns `chunk`: + /// Future?> getMembersByRoom(String roomId, {String? at, Membership? membership, Membership? notMembership}) async { final requestUri = Uri( @@ -3548,7 +3565,9 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['chunk']); } @@ -3602,7 +3621,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetRoomEventsResponse.fromJson(json); + return GetRoomEventsResponse.fromJson(json as Map); } /// Sets the position of the read marker for a given room, and optionally @@ -3768,10 +3787,12 @@ class Api { /// ID unique across requests with the same access token; it will be /// used by the server to ensure idempotency of requests. /// + /// [body] + /// /// returns `event_id`: /// A unique identifier for the event. Future sendMessage(String roomId, String eventType, String txnId, - Map body) async { + Map body) async { final requestUri = Uri( path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/send/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}'); @@ -3800,7 +3821,9 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return (json as List).map((v) => MatrixEvent.fromJson(v)).toList(); + return (json as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList(); } /// Looks up the contents of a state event in a room. If the user is @@ -3814,7 +3837,7 @@ class Api { /// /// [stateKey] The key of the state to look up. Defaults to an empty string. When /// an empty string, the trailing slash on this endpoint is optional. - Future> getRoomStateWithKey( + Future> getRoomStateWithKey( String roomId, String eventType, String stateKey) async { final requestUri = Uri( path: @@ -3826,7 +3849,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return json as Map; + return json as Map; } /// State events can be sent using this endpoint. These events will be @@ -3855,10 +3878,12 @@ class Api { /// [stateKey] The state_key for the state to send. Defaults to the empty string. When /// an empty string, the trailing slash on this endpoint is optional. /// + /// [body] + /// /// returns `event_id`: /// A unique identifier for the event. Future setRoomStateWithKey(String roomId, String eventType, - String stateKey, Map body) async { + String stateKey, Map body) async { final requestUri = Uri( path: '_matrix/client/v3/rooms/${Uri.encodeComponent(roomId)}/state/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(stateKey)}'); @@ -3983,7 +4008,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return SearchResults.fromJson(json); + return SearchResults.fromJson(json as Map); } /// This endpoint is used to send send-to-device events to a set of @@ -3999,7 +4024,7 @@ class Api { /// device ID to message body. The device ID may also be `*`, /// meaning all known devices for the user. Future sendToDevice(String eventType, String txnId, - Map>> messages) async { + Map>> messages) async { final requestUri = Uri( path: '_matrix/client/v3/sendToDevice/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}'); @@ -4100,7 +4125,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return SyncUpdate.fromJson(json); + return SyncUpdate.fromJson(json as Map); } /// Retrieve an array of third party network locations from a Matrix room @@ -4119,7 +4144,9 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return (json as List).map((v) => Location.fromJson(v)).toList(); + return (json as List) + .map((v) => Location.fromJson(v as Map)) + .toList(); } /// Requesting this endpoint with a valid protocol name results in a list @@ -4150,7 +4177,9 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return (json as List).map((v) => Location.fromJson(v)).toList(); + return (json as List) + .map((v) => Location.fromJson(v as Map)) + .toList(); } /// Fetches the metadata from the homeserver about a particular third party protocol. @@ -4167,7 +4196,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return Protocol.fromJson(json); + return Protocol.fromJson(json as Map); } /// Fetches the overall metadata about protocols supported by the @@ -4182,8 +4211,8 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return (json as Map) - .map((k, v) => MapEntry(k, Protocol.fromJson(v))); + return (json as Map).map( + (k, v) => MapEntry(k, Protocol.fromJson(v as Map))); } /// Retrieve an array of third party users from a Matrix User ID. @@ -4201,7 +4230,9 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return (json as List).map((v) => ThirdPartyUser.fromJson(v)).toList(); + return (json as List) + .map((v) => ThirdPartyUser.fromJson(v as Map)) + .toList(); } /// Retrieve a Matrix User ID linked to a user on the third party service, given @@ -4225,7 +4256,9 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return (json as List).map((v) => ThirdPartyUser.fromJson(v)).toList(); + return (json as List) + .map((v) => ThirdPartyUser.fromJson(v as Map)) + .toList(); } /// Get some account data for the client. This config is only visible to the user @@ -4236,7 +4269,7 @@ class Api { /// /// [type] The event type of the account data to get. Custom types should be /// namespaced to avoid clashes. - Future> getAccountData( + Future> getAccountData( String userId, String type) async { final requestUri = Uri( path: @@ -4248,7 +4281,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return json as Map; + return json as Map; } /// Set some account data for the client. This config is only visible to the user @@ -4264,7 +4297,7 @@ class Api { /// /// [content] The content of the account data. Future setAccountData( - String userId, String type, Map content) async { + String userId, String type, Map content) async { final requestUri = Uri( path: '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/account_data/${Uri.encodeComponent(type)}'); @@ -4308,7 +4341,7 @@ class Api { return json['filter_id'] as String; } - /// getFilter + /// /// /// [userId] The user ID to download a filter for. /// @@ -4324,7 +4357,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return Filter.fromJson(json); + return Filter.fromJson(json as Map); } /// Gets an OpenID token object that the requester may supply to another @@ -4341,7 +4374,7 @@ class Api { /// /// [body] An empty object. Reserved for future expansion. Future requestOpenIdToken( - String userId, Map body) async { + String userId, Map body) async { final requestUri = Uri( path: '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/openid/request_token'); @@ -4354,7 +4387,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return OpenIdCredentials.fromJson(json); + return OpenIdCredentials.fromJson(json as Map); } /// Get some account data for the client on a given room. This config is only @@ -4367,7 +4400,7 @@ class Api { /// /// [type] The event type of the account data to get. Custom types should be /// namespaced to avoid clashes. - Future> getAccountDataPerRoom( + Future> getAccountDataPerRoom( String userId, String roomId, String type) async { final requestUri = Uri( path: @@ -4379,7 +4412,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return json as Map; + return json as Map; } /// Set some account data for the client on a given room. This config is only @@ -4396,7 +4429,7 @@ class Api { /// /// [content] The content of the account data. Future setAccountDataPerRoom(String userId, String roomId, String type, - Map content) async { + Map content) async { final requestUri = Uri( path: '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/account_data/${Uri.encodeComponent(type)}'); @@ -4419,7 +4452,8 @@ class Api { /// /// [roomId] The ID of the room to get tags for. /// - /// returns `tags` + /// returns `tags`: + /// Future?> getRoomTags(String userId, String roomId) async { final requestUri = Uri( path: @@ -4432,8 +4466,8 @@ class Api { final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); return ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, Tag.fromJson(v))) + ? (v as Map) + .map((k, v) => MapEntry(k, Tag.fromJson(v as Map))) : null)(json['tags']); } @@ -4472,7 +4506,7 @@ class Api { /// position of the room under the given tag. Future setRoomTag(String userId, String roomId, String tag, {double? order, - Map additionalProperties = const {}}) async { + Map additionalProperties = const {}}) async { final requestUri = Uri( path: '_matrix/client/v3/user/${Uri.encodeComponent(userId)}/rooms/${Uri.encodeComponent(roomId)}/tags/${Uri.encodeComponent(tag)}'); @@ -4520,7 +4554,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return SearchUserDirectoryResponse.fromJson(json); + return SearchUserDirectoryResponse.fromJson(json as Map); } /// This API provides credentials for the client to use when initiating @@ -4534,7 +4568,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return TurnServerCredentials.fromJson(json); + return TurnServerCredentials.fromJson(json as Map); } /// Gets the versions of the specification supported by the server. @@ -4563,7 +4597,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetVersionsResponse.fromJson(json); + return GetVersionsResponse.fromJson(json as Map); } /// This endpoint allows clients to retrieve the configuration of the content @@ -4585,10 +4619,10 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return ServerConfig.fromJson(json); + return ServerConfig.fromJson(json as Map); } - /// getContent + /// /// /// [serverName] The server name from the `mxc://` URI (the authoritory component) /// @@ -4678,7 +4712,7 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return GetUrlPreviewResponse.fromJson(json); + return GetUrlPreviewResponse.fromJson(json as Map); } /// Download a thumbnail of content from the content repository. @@ -4723,7 +4757,7 @@ class Api { contentType: response.headers['content-type'], data: responseBody); } - /// uploadContent + /// /// /// [filename] The name of the file being uploaded /// @@ -4747,6 +4781,6 @@ class Api { if (response.statusCode != 200) unexpectedResponse(response, responseBody); final responseString = utf8.decode(responseBody); final json = jsonDecode(responseString); - return Uri.parse(json['content_uri']); + return Uri.parse(json['content_uri'] as String); } } diff --git a/lib/src/generated/model.dart b/lib/src/generated/model.dart index a4341e68..3ab82f75 100644 --- a/lib/src/generated/model.dart +++ b/lib/src/generated/model.dart @@ -16,15 +16,16 @@ class _NameSource { const _NameSource(this.source); } +/// @_NameSource('spec') class HomeserverInformation { HomeserverInformation({ required this.baseUrl, }); - HomeserverInformation.fromJson(Map json) - : baseUrl = Uri.parse(json['base_url']); - Map toJson() => { + HomeserverInformation.fromJson(Map json) + : baseUrl = Uri.parse(json['base_url'] as String); + Map toJson() => { 'base_url': baseUrl.toString(), }; @@ -32,15 +33,16 @@ class HomeserverInformation { Uri baseUrl; } +/// @_NameSource('spec') class IdentityServerInformation { IdentityServerInformation({ required this.baseUrl, }); - IdentityServerInformation.fromJson(Map json) - : baseUrl = Uri.parse(json['base_url']); - Map toJson() => { + IdentityServerInformation.fromJson(Map json) + : baseUrl = Uri.parse(json['base_url'] as String); + Map toJson() => { 'base_url': baseUrl.toString(), }; @@ -58,16 +60,17 @@ class DiscoveryInformation { this.additionalProperties = const {}, }); - DiscoveryInformation.fromJson(Map json) - : mHomeserver = HomeserverInformation.fromJson(json['m.homeserver']), + DiscoveryInformation.fromJson(Map json) + : mHomeserver = HomeserverInformation.fromJson( + json['m.homeserver'] as Map), mIdentityServer = ((v) => v != null - ? IdentityServerInformation.fromJson(v) + ? IdentityServerInformation.fromJson(v as Map) : null)(json['m.identity_server']), additionalProperties = Map.fromEntries(json.entries .where( (e) => !['m.homeserver', 'm.identity_server'].contains(e.key)) - .map((e) => MapEntry(e.key, e.value as Map))); - Map toJson() { + .map((e) => MapEntry(e.key, e.value as Map))); + Map toJson() { final mIdentityServer = this.mIdentityServer; return { ...additionalProperties, @@ -83,9 +86,10 @@ class DiscoveryInformation { /// Used by clients to discover identity server information. IdentityServerInformation? mIdentityServer; - Map> additionalProperties; + Map> additionalProperties; } +/// @_NameSource('spec') class PublicRoomsChunk { PublicRoomsChunk({ @@ -101,9 +105,9 @@ class PublicRoomsChunk { required this.worldReadable, }); - PublicRoomsChunk.fromJson(Map json) - : avatarUrl = - ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + PublicRoomsChunk.fromJson(Map json) + : avatarUrl = ((v) => + v != null ? Uri.parse(v as String) : null)(json['avatar_url']), canonicalAlias = ((v) => v != null ? v as String : null)(json['canonical_alias']), guestCanJoin = json['guest_can_join'] as bool, @@ -114,7 +118,7 @@ class PublicRoomsChunk { roomType = ((v) => v != null ? v as String : null)(json['room_type']), topic = ((v) => v != null ? v as String : null)(json['topic']), worldReadable = json['world_readable'] as bool; - Map toJson() { + Map toJson() { final avatarUrl = this.avatarUrl; final canonicalAlias = this.canonicalAlias; final joinRule = this.joinRule; @@ -169,6 +173,7 @@ class PublicRoomsChunk { bool worldReadable; } +/// @_NameSource('spec') class ChildRoomsChunk { ChildRoomsChunk({ @@ -176,12 +181,12 @@ class ChildRoomsChunk { this.roomType, }); - ChildRoomsChunk.fromJson(Map json) + ChildRoomsChunk.fromJson(Map json) : childrenState = (json['children_state'] as List) - .map((v) => ChildrenState.fromJson(v)) + .map((v) => ChildrenState.fromJson(v as Map)) .toList(), roomType = ((v) => v != null ? v as String : null)(json['room_type']); - Map toJson() { + Map toJson() { final roomType = this.roomType; return { 'children_state': childrenState.map((v) => v.toJson()).toList(), @@ -199,6 +204,7 @@ class ChildRoomsChunk { String? roomType; } +/// @_NameSource('rule override generated') class SpaceRoomsChunk implements PublicRoomsChunk, ChildRoomsChunk { SpaceRoomsChunk({ @@ -215,9 +221,9 @@ class SpaceRoomsChunk implements PublicRoomsChunk, ChildRoomsChunk { required this.childrenState, }); - SpaceRoomsChunk.fromJson(Map json) - : avatarUrl = - ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + SpaceRoomsChunk.fromJson(Map json) + : avatarUrl = ((v) => + v != null ? Uri.parse(v as String) : null)(json['avatar_url']), canonicalAlias = ((v) => v != null ? v as String : null)(json['canonical_alias']), guestCanJoin = json['guest_can_join'] as bool, @@ -229,9 +235,9 @@ class SpaceRoomsChunk implements PublicRoomsChunk, ChildRoomsChunk { topic = ((v) => v != null ? v as String : null)(json['topic']), worldReadable = json['world_readable'] as bool, childrenState = (json['children_state'] as List) - .map((v) => ChildrenState.fromJson(v)) + .map((v) => ChildrenState.fromJson(v as Map)) .toList(); - Map toJson() { + Map toJson() { final avatarUrl = this.avatarUrl; final canonicalAlias = this.canonicalAlias; final joinRule = this.joinRule; @@ -293,6 +299,7 @@ class SpaceRoomsChunk implements PublicRoomsChunk, ChildRoomsChunk { List childrenState; } +/// @_NameSource('generated') class GetSpaceHierarchyResponse { GetSpaceHierarchyResponse({ @@ -300,12 +307,12 @@ class GetSpaceHierarchyResponse { required this.rooms, }); - GetSpaceHierarchyResponse.fromJson(Map json) + GetSpaceHierarchyResponse.fromJson(Map json) : nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), rooms = (json['rooms'] as List) - .map((v) => SpaceRoomsChunk.fromJson(v)) + .map((v) => SpaceRoomsChunk.fromJson(v as Map)) .toList(); - Map toJson() { + Map toJson() { final nextBatch = this.nextBatch; return { if (nextBatch != null) 'next_batch': nextBatch, @@ -321,6 +328,7 @@ class GetSpaceHierarchyResponse { List rooms; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum Direction { @@ -330,6 +338,7 @@ enum Direction { f } +/// @_NameSource('generated') class GetRelatingEventsResponse { GetRelatingEventsResponse({ @@ -338,13 +347,13 @@ class GetRelatingEventsResponse { this.prevBatch, }); - GetRelatingEventsResponse.fromJson(Map json) + GetRelatingEventsResponse.fromJson(Map json) : chunk = (json['chunk'] as List) - .map((v) => MatrixEvent.fromJson(v)) + .map((v) => MatrixEvent.fromJson(v as Map)) .toList(), nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']); - Map toJson() { + Map toJson() { final nextBatch = this.nextBatch; final prevBatch = this.prevBatch; return { @@ -366,6 +375,7 @@ class GetRelatingEventsResponse { String? prevBatch; } +/// @_NameSource('generated') class GetRelatingEventsWithRelTypeResponse { GetRelatingEventsWithRelTypeResponse({ @@ -374,13 +384,13 @@ class GetRelatingEventsWithRelTypeResponse { this.prevBatch, }); - GetRelatingEventsWithRelTypeResponse.fromJson(Map json) + GetRelatingEventsWithRelTypeResponse.fromJson(Map json) : chunk = (json['chunk'] as List) - .map((v) => MatrixEvent.fromJson(v)) + .map((v) => MatrixEvent.fromJson(v as Map)) .toList(), nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']); - Map toJson() { + Map toJson() { final nextBatch = this.nextBatch; final prevBatch = this.prevBatch; return { @@ -404,6 +414,7 @@ class GetRelatingEventsWithRelTypeResponse { String? prevBatch; } +/// @_NameSource('generated') class GetRelatingEventsWithRelTypeAndEventTypeResponse { GetRelatingEventsWithRelTypeAndEventTypeResponse({ @@ -413,13 +424,13 @@ class GetRelatingEventsWithRelTypeAndEventTypeResponse { }); GetRelatingEventsWithRelTypeAndEventTypeResponse.fromJson( - Map json) + Map json) : chunk = (json['chunk'] as List) - .map((v) => MatrixEvent.fromJson(v)) + .map((v) => MatrixEvent.fromJson(v as Map)) .toList(), nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']); - Map toJson() { + Map toJson() { final nextBatch = this.nextBatch; final prevBatch = this.prevBatch; return { @@ -443,6 +454,7 @@ class GetRelatingEventsWithRelTypeAndEventTypeResponse { String? prevBatch; } +/// @_NameSource('generated') @EnhancedEnum() enum Include { @@ -452,6 +464,7 @@ enum Include { participated } +/// @_NameSource('generated') class GetThreadRootsResponse { GetThreadRootsResponse({ @@ -459,12 +472,12 @@ class GetThreadRootsResponse { this.nextBatch, }); - GetThreadRootsResponse.fromJson(Map json) + GetThreadRootsResponse.fromJson(Map json) : chunk = (json['chunk'] as List) - .map((v) => MatrixEvent.fromJson(v)) + .map((v) => MatrixEvent.fromJson(v as Map)) .toList(), nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']); - Map toJson() { + Map toJson() { final nextBatch = this.nextBatch; return { 'chunk': chunk.map((v) => v.toJson()).toList(), @@ -485,6 +498,7 @@ class GetThreadRootsResponse { String? nextBatch; } +/// @_NameSource('generated') class GetEventByTimestampResponse { GetEventByTimestampResponse({ @@ -492,10 +506,10 @@ class GetEventByTimestampResponse { required this.originServerTs, }); - GetEventByTimestampResponse.fromJson(Map json) + GetEventByTimestampResponse.fromJson(Map json) : eventId = json['event_id'] as String, originServerTs = json['origin_server_ts'] as int; - Map toJson() => { + Map toJson() => { 'event_id': eventId, 'origin_server_ts': originServerTs, }; @@ -510,6 +524,7 @@ class GetEventByTimestampResponse { int originServerTs; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum ThirdPartyIdentifierMedium { @@ -519,6 +534,7 @@ enum ThirdPartyIdentifierMedium { msisdn } +/// @_NameSource('spec') class ThirdPartyIdentifier { ThirdPartyIdentifier({ @@ -528,12 +544,13 @@ class ThirdPartyIdentifier { required this.validatedAt, }); - ThirdPartyIdentifier.fromJson(Map json) + ThirdPartyIdentifier.fromJson(Map json) : addedAt = json['added_at'] as int, address = json['address'] as String, - medium = ThirdPartyIdentifierMedium.values.fromString(json['medium'])!, + medium = ThirdPartyIdentifierMedium.values + .fromString(json['medium'] as String)!, validatedAt = json['validated_at'] as int; - Map toJson() => { + Map toJson() => { 'added_at': addedAt, 'address': address, 'medium': medium.name, @@ -554,6 +571,7 @@ class ThirdPartyIdentifier { int validatedAt; } +/// @_NameSource('spec') class ThreePidCredentials { ThreePidCredentials({ @@ -563,12 +581,12 @@ class ThreePidCredentials { required this.sid, }); - ThreePidCredentials.fromJson(Map json) + ThreePidCredentials.fromJson(Map json) : clientSecret = json['client_secret'] as String, idAccessToken = json['id_access_token'] as String, idServer = json['id_server'] as String, sid = json['sid'] as String; - Map toJson() => { + Map toJson() => { 'client_secret': clientSecret, 'id_access_token': idAccessToken, 'id_server': idServer, @@ -590,6 +608,7 @@ class ThreePidCredentials { String sid; } +/// @_NameSource('generated') @EnhancedEnum() enum IdServerUnbindResult { @@ -599,6 +618,7 @@ enum IdServerUnbindResult { success } +/// @_NameSource('spec') class RequestTokenResponse { RequestTokenResponse({ @@ -606,11 +626,11 @@ class RequestTokenResponse { this.submitUrl, }); - RequestTokenResponse.fromJson(Map json) + RequestTokenResponse.fromJson(Map json) : sid = json['sid'] as String, - submitUrl = - ((v) => v != null ? Uri.parse(v) : null)(json['submit_url']); - Map toJson() { + submitUrl = ((v) => + v != null ? Uri.parse(v as String) : null)(json['submit_url']); + Map toJson() { final submitUrl = this.submitUrl; return { 'sid': sid, @@ -636,6 +656,7 @@ class RequestTokenResponse { Uri? submitUrl; } +/// @_NameSource('rule override generated') class TokenOwnerInfo { TokenOwnerInfo({ @@ -644,11 +665,11 @@ class TokenOwnerInfo { required this.userId, }); - TokenOwnerInfo.fromJson(Map json) + TokenOwnerInfo.fromJson(Map json) : deviceId = ((v) => v != null ? v as String : null)(json['device_id']), isGuest = ((v) => v != null ? v as bool : null)(json['is_guest']), userId = json['user_id'] as String; - Map toJson() { + Map toJson() { final deviceId = this.deviceId; final isGuest = this.isGuest; return { @@ -673,6 +694,7 @@ class TokenOwnerInfo { String userId; } +/// @_NameSource('spec') class ConnectionInfo { ConnectionInfo({ @@ -681,11 +703,11 @@ class ConnectionInfo { this.userAgent, }); - ConnectionInfo.fromJson(Map json) + ConnectionInfo.fromJson(Map json) : ip = ((v) => v != null ? v as String : null)(json['ip']), lastSeen = ((v) => v != null ? v as int : null)(json['last_seen']), userAgent = ((v) => v != null ? v as String : null)(json['user_agent']); - Map toJson() { + Map toJson() { final ip = this.ip; final lastSeen = this.lastSeen; final userAgent = this.userAgent; @@ -706,17 +728,20 @@ class ConnectionInfo { String? userAgent; } +/// @_NameSource('spec') class SessionInfo { SessionInfo({ this.connections, }); - SessionInfo.fromJson(Map json) + SessionInfo.fromJson(Map json) : connections = ((v) => v != null - ? (v as List).map((v) => ConnectionInfo.fromJson(v)).toList() + ? (v as List) + .map((v) => ConnectionInfo.fromJson(v as Map)) + .toList() : null)(json['connections']); - Map toJson() { + Map toJson() { final connections = this.connections; return { if (connections != null) @@ -728,17 +753,20 @@ class SessionInfo { List? connections; } +/// @_NameSource('spec') class DeviceInfo { DeviceInfo({ this.sessions, }); - DeviceInfo.fromJson(Map json) + DeviceInfo.fromJson(Map json) : sessions = ((v) => v != null - ? (v as List).map((v) => SessionInfo.fromJson(v)).toList() + ? (v as List) + .map((v) => SessionInfo.fromJson(v as Map)) + .toList() : null)(json['sessions']); - Map toJson() { + Map toJson() { final sessions = this.sessions; return { if (sessions != null) @@ -750,6 +778,7 @@ class DeviceInfo { List? sessions; } +/// @_NameSource('rule override generated') class WhoIsInfo { WhoIsInfo({ @@ -757,13 +786,13 @@ class WhoIsInfo { this.userId, }); - WhoIsInfo.fromJson(Map json) + WhoIsInfo.fromJson(Map json) : devices = ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, DeviceInfo.fromJson(v))) + ? (v as Map).map((k, v) => + MapEntry(k, DeviceInfo.fromJson(v as Map))) : null)(json['devices']), userId = ((v) => v != null ? v as String : null)(json['user_id']); - Map toJson() { + Map toJson() { final devices = this.devices; final userId = this.userId; return { @@ -780,15 +809,16 @@ class WhoIsInfo { String? userId; } +/// @_NameSource('spec') class ChangePasswordCapability { ChangePasswordCapability({ required this.enabled, }); - ChangePasswordCapability.fromJson(Map json) + ChangePasswordCapability.fromJson(Map json) : enabled = json['enabled'] as bool; - Map toJson() => { + Map toJson() => { 'enabled': enabled, }; @@ -806,6 +836,7 @@ enum RoomVersionAvailable { unstable } +/// @_NameSource('spec') class RoomVersionsCapability { RoomVersionsCapability({ @@ -813,11 +844,11 @@ class RoomVersionsCapability { required this.default$, }); - RoomVersionsCapability.fromJson(Map json) - : available = (json['available'] as Map).map( - (k, v) => MapEntry(k, RoomVersionAvailable.values.fromString(v)!)), + RoomVersionsCapability.fromJson(Map json) + : available = (json['available'] as Map).map((k, v) => + MapEntry(k, RoomVersionAvailable.values.fromString(v as String)!)), default$ = json['default'] as String; - Map toJson() => { + Map toJson() => { 'available': available.map((k, v) => MapEntry(k, v.name)), 'default': default$, }; @@ -829,6 +860,7 @@ class RoomVersionsCapability { String default$; } +/// @_NameSource('spec') class Capabilities { Capabilities({ @@ -837,18 +869,18 @@ class Capabilities { this.additionalProperties = const {}, }); - Capabilities.fromJson(Map json) + Capabilities.fromJson(Map json) : mChangePassword = ((v) => v != null - ? ChangePasswordCapability.fromJson(v) + ? ChangePasswordCapability.fromJson(v as Map) : null)(json['m.change_password']), mRoomVersions = ((v) => v != null - ? RoomVersionsCapability.fromJson(v) + ? RoomVersionsCapability.fromJson(v as Map) : null)(json['m.room_versions']), additionalProperties = Map.fromEntries(json.entries .where((e) => !['m.change_password', 'm.room_versions'].contains(e.key)) - .map((e) => MapEntry(e.key, e.value as Map))); - Map toJson() { + .map((e) => MapEntry(e.key, e.value as Map))); + Map toJson() { final mChangePassword = this.mChangePassword; final mRoomVersions = this.mRoomVersions; return { @@ -865,9 +897,10 @@ class Capabilities { /// The room versions the server supports. RoomVersionsCapability? mRoomVersions; - Map> additionalProperties; + Map> additionalProperties; } +/// @_NameSource('spec') class StateEvent { StateEvent({ @@ -876,11 +909,11 @@ class StateEvent { required this.type, }); - StateEvent.fromJson(Map json) - : content = json['content'] as Map, + StateEvent.fromJson(Map json) + : content = json['content'] as Map, stateKey = ((v) => v != null ? v as String : null)(json['state_key']), type = json['type'] as String; - Map toJson() { + Map toJson() { final stateKey = this.stateKey; return { 'content': content, @@ -890,7 +923,7 @@ class StateEvent { } /// The content of the event. - Map content; + Map content; /// The state_key of the state event. Defaults to an empty string. String? stateKey; @@ -899,6 +932,7 @@ class StateEvent { String type; } +/// @_NameSource('spec') class Invite3pid { Invite3pid({ @@ -908,12 +942,12 @@ class Invite3pid { required this.medium, }); - Invite3pid.fromJson(Map json) + Invite3pid.fromJson(Map json) : address = json['address'] as String, idAccessToken = json['id_access_token'] as String, idServer = json['id_server'] as String, medium = json['medium'] as String; - Map toJson() => { + Map toJson() => { 'address': address, 'id_access_token': idAccessToken, 'id_server': idServer, @@ -936,6 +970,7 @@ class Invite3pid { String medium; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum CreateRoomPreset { @@ -947,6 +982,7 @@ enum CreateRoomPreset { trustedPrivateChat } +/// @_NameSource('generated') @EnhancedEnum() enum Visibility { @@ -966,14 +1002,14 @@ class Device { this.lastSeenTs, }); - Device.fromJson(Map json) + Device.fromJson(Map json) : deviceId = json['device_id'] as String, displayName = ((v) => v != null ? v as String : null)(json['display_name']), lastSeenIp = ((v) => v != null ? v as String : null)(json['last_seen_ip']), lastSeenTs = ((v) => v != null ? v as int : null)(json['last_seen_ts']); - Map toJson() { + Map toJson() { final displayName = this.displayName; final lastSeenIp = this.lastSeenIp; final lastSeenTs = this.lastSeenTs; @@ -1002,6 +1038,7 @@ class Device { int? lastSeenTs; } +/// @_NameSource('generated') class GetRoomIdByAliasResponse { GetRoomIdByAliasResponse({ @@ -1009,12 +1046,12 @@ class GetRoomIdByAliasResponse { this.servers, }); - GetRoomIdByAliasResponse.fromJson(Map json) + GetRoomIdByAliasResponse.fromJson(Map json) : roomId = ((v) => v != null ? v as String : null)(json['room_id']), servers = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['servers']); - Map toJson() { + Map toJson() { final roomId = this.roomId; final servers = this.servers; return { @@ -1030,6 +1067,7 @@ class GetRoomIdByAliasResponse { List? servers; } +/// @_NameSource('generated') class GetEventsResponse { GetEventsResponse({ @@ -1038,13 +1076,15 @@ class GetEventsResponse { this.start, }); - GetEventsResponse.fromJson(Map json) + GetEventsResponse.fromJson(Map json) : chunk = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['chunk']), end = ((v) => v != null ? v as String : null)(json['end']), start = ((v) => v != null ? v as String : null)(json['start']); - Map toJson() { + Map toJson() { final chunk = this.chunk; final end = this.end; final start = this.start; @@ -1067,6 +1107,7 @@ class GetEventsResponse { String? start; } +/// @_NameSource('generated') class PeekEventsResponse { PeekEventsResponse({ @@ -1075,13 +1116,15 @@ class PeekEventsResponse { this.start, }); - PeekEventsResponse.fromJson(Map json) + PeekEventsResponse.fromJson(Map json) : chunk = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['chunk']), end = ((v) => v != null ? v as String : null)(json['end']), start = ((v) => v != null ? v as String : null)(json['start']); - Map toJson() { + Map toJson() { final chunk = this.chunk; final end = this.end; final start = this.start; @@ -1115,16 +1158,16 @@ class ThirdPartySigned { required this.token, }); - ThirdPartySigned.fromJson(Map json) + ThirdPartySigned.fromJson(Map json) : mxid = json['mxid'] as String, sender = json['sender'] as String, - signatures = (json['signatures'] as Map).map((k, v) => + signatures = (json['signatures'] as Map).map((k, v) => MapEntry( k, - (v as Map) + (v as Map) .map((k, v) => MapEntry(k, v as String)))), token = json['token'] as String; - Map toJson() => { + Map toJson() => { 'mxid': mxid, 'sender': sender, 'signatures': signatures @@ -1145,6 +1188,7 @@ class ThirdPartySigned { String token; } +/// @_NameSource('generated') class GetKeysChangesResponse { GetKeysChangesResponse({ @@ -1152,14 +1196,14 @@ class GetKeysChangesResponse { this.left, }); - GetKeysChangesResponse.fromJson(Map json) + GetKeysChangesResponse.fromJson(Map json) : changed = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['changed']), left = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['left']); - Map toJson() { + Map toJson() { final changed = this.changed; final left = this.left; return { @@ -1178,6 +1222,7 @@ class GetKeysChangesResponse { List? left; } +/// @_NameSource('generated') class ClaimKeysResponse { ClaimKeysResponse({ @@ -1185,17 +1230,17 @@ class ClaimKeysResponse { required this.oneTimeKeys, }); - ClaimKeysResponse.fromJson(Map json) + ClaimKeysResponse.fromJson(Map json) : failures = ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, v as Map)) + ? (v as Map) + .map((k, v) => MapEntry(k, v as Map)) : null)(json['failures']), - oneTimeKeys = (json['one_time_keys'] as Map).map( + oneTimeKeys = (json['one_time_keys'] as Map).map( (k, v) => MapEntry( k, - (v as Map) - .map((k, v) => MapEntry(k, v as Map)))); - Map toJson() { + (v as Map) + .map((k, v) => MapEntry(k, v as Map)))); + Map toJson() { final failures = this.failures; return { if (failures != null) 'failures': failures.map((k, v) => MapEntry(k, v)), @@ -1211,7 +1256,7 @@ class ClaimKeysResponse { /// If the homeserver could be reached, but the user or device /// was unknown, no failure is recorded. Instead, the corresponding /// user or device is missing from the `one_time_keys` result. - Map>? failures; + Map>? failures; /// One-time keys for the queried devices. A map from user ID, to a /// map from devices to a map from `:` to the key object. @@ -1221,9 +1266,10 @@ class ClaimKeysResponse { /// /// If necessary, the claimed key might be a fallback key. Fallback /// keys are re-used by the server until replaced by the device. - Map>> oneTimeKeys; + Map>> oneTimeKeys; } +/// @_NameSource('generated') class QueryKeysResponse { QueryKeysResponse({ @@ -1234,30 +1280,30 @@ class QueryKeysResponse { this.userSigningKeys, }); - QueryKeysResponse.fromJson(Map json) + QueryKeysResponse.fromJson(Map json) : deviceKeys = ((v) => v != null - ? (v as Map).map((k, v) => MapEntry( + ? (v as Map).map((k, v) => MapEntry( k, - (v as Map) - .map((k, v) => MapEntry(k, MatrixDeviceKeys.fromJson(v))))) + (v as Map).map((k, v) => MapEntry( + k, MatrixDeviceKeys.fromJson(v as Map))))) : null)(json['device_keys']), failures = ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, v as Map)) + ? (v as Map) + .map((k, v) => MapEntry(k, v as Map)) : null)(json['failures']), masterKeys = ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, MatrixCrossSigningKey.fromJson(v))) + ? (v as Map).map((k, v) => MapEntry( + k, MatrixCrossSigningKey.fromJson(v as Map))) : null)(json['master_keys']), selfSigningKeys = ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, MatrixCrossSigningKey.fromJson(v))) + ? (v as Map).map((k, v) => MapEntry( + k, MatrixCrossSigningKey.fromJson(v as Map))) : null)(json['self_signing_keys']), userSigningKeys = ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, MatrixCrossSigningKey.fromJson(v))) + ? (v as Map).map((k, v) => MapEntry( + k, MatrixCrossSigningKey.fromJson(v as Map))) : null)(json['user_signing_keys']); - Map toJson() { + Map toJson() { final deviceKeys = this.deviceKeys; final failures = this.failures; final masterKeys = this.masterKeys; @@ -1293,7 +1339,7 @@ class QueryKeysResponse { /// If the homeserver could be reached, but the user or device /// was unknown, no failure is recorded. Instead, the corresponding /// user or device is missing from the `device_keys` result. - Map>? failures; + Map>? failures; /// Information on the master cross-signing keys of the queried users. /// A map from user ID, to master key information. For each key, the @@ -1317,15 +1363,16 @@ class QueryKeysResponse { Map? userSigningKeys; } +/// @_NameSource('spec') class LoginFlow { LoginFlow({ this.type, }); - LoginFlow.fromJson(Map json) + LoginFlow.fromJson(Map json) : type = ((v) => v != null ? v as String : null)(json['type']); - Map toJson() { + Map toJson() { final type = this.type; return { if (type != null) 'type': type, @@ -1337,6 +1384,7 @@ class LoginFlow { String? type; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum LoginType { @@ -1346,6 +1394,7 @@ enum LoginType { mLoginToken } +/// @_NameSource('generated') class LoginResponse { LoginResponse({ @@ -1358,7 +1407,7 @@ class LoginResponse { this.wellKnown, }); - LoginResponse.fromJson(Map json) + LoginResponse.fromJson(Map json) : accessToken = json['access_token'] as String, deviceId = json['device_id'] as String, expiresInMs = @@ -1369,9 +1418,9 @@ class LoginResponse { ((v) => v != null ? v as String : null)(json['refresh_token']), userId = json['user_id'] as String, wellKnown = ((v) => v != null - ? DiscoveryInformation.fromJson(v) + ? DiscoveryInformation.fromJson(v as Map) : null)(json['well_known']); - Map toJson() { + Map toJson() { final expiresInMs = this.expiresInMs; final homeServer = this.homeServer; final refreshToken = this.refreshToken; @@ -1426,6 +1475,7 @@ class LoginResponse { DiscoveryInformation? wellKnown; } +/// @_NameSource('spec') class Notification { Notification({ @@ -1437,15 +1487,15 @@ class Notification { required this.ts, }); - Notification.fromJson(Map json) - : actions = (json['actions'] as List).map((v) => v as dynamic).toList(), - event = MatrixEvent.fromJson(json['event']), + Notification.fromJson(Map json) + : actions = (json['actions'] as List).map((v) => v as Object?).toList(), + event = MatrixEvent.fromJson(json['event'] as Map), profileTag = ((v) => v != null ? v as String : null)(json['profile_tag']), read = json['read'] as bool, roomId = json['room_id'] as String, ts = json['ts'] as int; - Map toJson() { + Map toJson() { final profileTag = this.profileTag; return { 'actions': actions.map((v) => v).toList(), @@ -1459,7 +1509,7 @@ class Notification { /// The action(s) to perform when the conditions for this rule are met. /// See [Push Rules: API](https://spec.matrix.org/unstable/client-server-api/#push-rules-api). - List actions; + List actions; /// The Event object for the event that triggered the notification. MatrixEvent event; @@ -1479,6 +1529,7 @@ class Notification { int ts; } +/// @_NameSource('generated') class GetNotificationsResponse { GetNotificationsResponse({ @@ -1486,12 +1537,12 @@ class GetNotificationsResponse { required this.notifications, }); - GetNotificationsResponse.fromJson(Map json) + GetNotificationsResponse.fromJson(Map json) : nextToken = ((v) => v != null ? v as String : null)(json['next_token']), notifications = (json['notifications'] as List) - .map((v) => Notification.fromJson(v)) + .map((v) => Notification.fromJson(v as Map)) .toList(); - Map toJson() { + Map toJson() { final nextToken = this.nextToken; return { if (nextToken != null) 'next_token': nextToken, @@ -1508,6 +1559,7 @@ class GetNotificationsResponse { List notifications; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum PresenceType { @@ -1519,6 +1571,7 @@ enum PresenceType { unavailable } +/// @_NameSource('generated') class GetPresenceResponse { GetPresenceResponse({ @@ -1528,14 +1581,14 @@ class GetPresenceResponse { this.statusMsg, }); - GetPresenceResponse.fromJson(Map json) + GetPresenceResponse.fromJson(Map json) : currentlyActive = ((v) => v != null ? v as bool : null)(json['currently_active']), lastActiveAgo = ((v) => v != null ? v as int : null)(json['last_active_ago']), - presence = PresenceType.values.fromString(json['presence'])!, + presence = PresenceType.values.fromString(json['presence'] as String)!, statusMsg = ((v) => v != null ? v as String : null)(json['status_msg']); - Map toJson() { + Map toJson() { final currentlyActive = this.currentlyActive; final lastActiveAgo = this.lastActiveAgo; final statusMsg = this.statusMsg; @@ -1561,6 +1614,7 @@ class GetPresenceResponse { String? statusMsg; } +/// @_NameSource('rule override generated') class ProfileInformation { ProfileInformation({ @@ -1568,12 +1622,12 @@ class ProfileInformation { this.displayname, }); - ProfileInformation.fromJson(Map json) - : avatarUrl = - ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + ProfileInformation.fromJson(Map json) + : avatarUrl = ((v) => + v != null ? Uri.parse(v as String) : null)(json['avatar_url']), displayname = ((v) => v != null ? v as String : null)(json['displayname']); - Map toJson() { + Map toJson() { final avatarUrl = this.avatarUrl; final displayname = this.displayname; return { @@ -1599,15 +1653,15 @@ class GetPublicRoomsResponse { this.totalRoomCountEstimate, }); - GetPublicRoomsResponse.fromJson(Map json) + GetPublicRoomsResponse.fromJson(Map json) : chunk = (json['chunk'] as List) - .map((v) => PublicRoomsChunk.fromJson(v)) + .map((v) => PublicRoomsChunk.fromJson(v as Map)) .toList(), nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']), totalRoomCountEstimate = ((v) => v != null ? v as int : null)(json['total_room_count_estimate']); - Map toJson() { + Map toJson() { final nextBatch = this.nextBatch; final prevBatch = this.prevBatch; final totalRoomCountEstimate = this.totalRoomCountEstimate; @@ -1638,6 +1692,7 @@ class GetPublicRoomsResponse { int? totalRoomCountEstimate; } +/// @_NameSource('rule override spec') class PublicRoomQueryFilter { PublicRoomQueryFilter({ @@ -1645,13 +1700,13 @@ class PublicRoomQueryFilter { this.roomTypes, }); - PublicRoomQueryFilter.fromJson(Map json) + PublicRoomQueryFilter.fromJson(Map json) : genericSearchTerm = ((v) => v != null ? v as String : null)(json['generic_search_term']), roomTypes = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['room_types']); - Map toJson() { + Map toJson() { final genericSearchTerm = this.genericSearchTerm; final roomTypes = this.roomTypes; return { @@ -1681,15 +1736,15 @@ class QueryPublicRoomsResponse { this.totalRoomCountEstimate, }); - QueryPublicRoomsResponse.fromJson(Map json) + QueryPublicRoomsResponse.fromJson(Map json) : chunk = (json['chunk'] as List) - .map((v) => PublicRoomsChunk.fromJson(v)) + .map((v) => PublicRoomsChunk.fromJson(v as Map)) .toList(), nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), prevBatch = ((v) => v != null ? v as String : null)(json['prev_batch']), totalRoomCountEstimate = ((v) => v != null ? v as int : null)(json['total_room_count_estimate']); - Map toJson() { + Map toJson() { final nextBatch = this.nextBatch; final prevBatch = this.prevBatch; final totalRoomCountEstimate = this.totalRoomCountEstimate; @@ -1720,6 +1775,7 @@ class QueryPublicRoomsResponse { int? totalRoomCountEstimate; } +/// @_NameSource('spec') class PusherData { PusherData({ @@ -1728,13 +1784,13 @@ class PusherData { this.additionalProperties = const {}, }); - PusherData.fromJson(Map json) + PusherData.fromJson(Map json) : format = ((v) => v != null ? v as String : null)(json['format']), - url = ((v) => v != null ? Uri.parse(v) : null)(json['url']), + url = ((v) => v != null ? Uri.parse(v as String) : null)(json['url']), additionalProperties = Map.fromEntries(json.entries .where((e) => !['format', 'url'].contains(e.key)) - .map((e) => MapEntry(e.key, e.value as dynamic))); - Map toJson() { + .map((e) => MapEntry(e.key, e.value as Object?))); + Map toJson() { final format = this.format; final url = this.url; return { @@ -1752,9 +1808,10 @@ class PusherData { /// notifications to. Uri? url; - Map additionalProperties; + Map additionalProperties; } +/// @_NameSource('spec') class PusherId { PusherId({ @@ -1762,10 +1819,10 @@ class PusherId { required this.pushkey, }); - PusherId.fromJson(Map json) + PusherId.fromJson(Map json) : appId = json['app_id'] as String, pushkey = json['pushkey'] as String; - Map toJson() => { + Map toJson() => { 'app_id': appId, 'pushkey': pushkey, }; @@ -1780,6 +1837,7 @@ class PusherId { String pushkey; } +/// @_NameSource('spec') class Pusher implements PusherId { Pusher({ @@ -1793,17 +1851,17 @@ class Pusher implements PusherId { this.profileTag, }); - Pusher.fromJson(Map json) + Pusher.fromJson(Map json) : appId = json['app_id'] as String, pushkey = json['pushkey'] as String, appDisplayName = json['app_display_name'] as String, - data = PusherData.fromJson(json['data']), + data = PusherData.fromJson(json['data'] as Map), deviceDisplayName = json['device_display_name'] as String, kind = json['kind'] as String, lang = json['lang'] as String, profileTag = ((v) => v != null ? v as String : null)(json['profile_tag']); - Map toJson() { + Map toJson() { final profileTag = this.profileTag; return { 'app_id': appId, @@ -1851,6 +1909,7 @@ class Pusher implements PusherId { String? profileTag; } +/// @_NameSource('spec') class PushCondition { PushCondition({ @@ -1860,12 +1919,12 @@ class PushCondition { this.pattern, }); - PushCondition.fromJson(Map json) + PushCondition.fromJson(Map json) : is$ = ((v) => v != null ? v as String : null)(json['is']), key = ((v) => v != null ? v as String : null)(json['key']), kind = json['kind'] as String, pattern = ((v) => v != null ? v as String : null)(json['pattern']); - Map toJson() { + Map toJson() { final is$ = this.is$; final key = this.key; final pattern = this.pattern; @@ -1901,6 +1960,7 @@ class PushCondition { String? pattern; } +/// @_NameSource('spec') class PushRule { PushRule({ @@ -1912,16 +1972,18 @@ class PushRule { required this.ruleId, }); - PushRule.fromJson(Map json) - : actions = (json['actions'] as List).map((v) => v as dynamic).toList(), + PushRule.fromJson(Map json) + : actions = (json['actions'] as List).map((v) => v as Object?).toList(), conditions = ((v) => v != null - ? (v as List).map((v) => PushCondition.fromJson(v)).toList() + ? (v as List) + .map((v) => PushCondition.fromJson(v as Map)) + .toList() : null)(json['conditions']), default$ = json['default'] as bool, enabled = json['enabled'] as bool, pattern = ((v) => v != null ? v as String : null)(json['pattern']), ruleId = json['rule_id'] as String; - Map toJson() { + Map toJson() { final conditions = this.conditions; final pattern = this.pattern; return { @@ -1936,7 +1998,7 @@ class PushRule { } /// The actions to perform when this rule is matched. - List actions; + List actions; /// 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 @@ -1957,6 +2019,7 @@ class PushRule { String ruleId; } +/// @_NameSource('rule override generated') class PushRuleSet { PushRuleSet({ @@ -1967,23 +2030,33 @@ class PushRuleSet { this.underride, }); - PushRuleSet.fromJson(Map json) + PushRuleSet.fromJson(Map json) : content = ((v) => v != null - ? (v as List).map((v) => PushRule.fromJson(v)).toList() + ? (v as List) + .map((v) => PushRule.fromJson(v as Map)) + .toList() : null)(json['content']), override = ((v) => v != null - ? (v as List).map((v) => PushRule.fromJson(v)).toList() + ? (v as List) + .map((v) => PushRule.fromJson(v as Map)) + .toList() : null)(json['override']), room = ((v) => v != null - ? (v as List).map((v) => PushRule.fromJson(v)).toList() + ? (v as List) + .map((v) => PushRule.fromJson(v as Map)) + .toList() : null)(json['room']), sender = ((v) => v != null - ? (v as List).map((v) => PushRule.fromJson(v)).toList() + ? (v as List) + .map((v) => PushRule.fromJson(v as Map)) + .toList() : null)(json['sender']), underride = ((v) => v != null - ? (v as List).map((v) => PushRule.fromJson(v)).toList() + ? (v as List) + .map((v) => PushRule.fromJson(v as Map)) + .toList() : null)(json['underride']); - Map toJson() { + Map toJson() { final content = this.content; final override = this.override; final room = this.room; @@ -2000,17 +2073,23 @@ class PushRuleSet { }; } + /// List? content; + /// List? override; + /// List? room; + /// List? sender; + /// List? underride; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum PushRuleKind { @@ -2026,6 +2105,7 @@ enum PushRuleKind { underride } +/// @_NameSource('generated') class RefreshResponse { RefreshResponse({ @@ -2034,13 +2114,13 @@ class RefreshResponse { this.refreshToken, }); - RefreshResponse.fromJson(Map json) + RefreshResponse.fromJson(Map json) : accessToken = json['access_token'] as String, expiresInMs = ((v) => v != null ? v as int : null)(json['expires_in_ms']), refreshToken = ((v) => v != null ? v as String : null)(json['refresh_token']); - Map toJson() { + Map toJson() { final expiresInMs = this.expiresInMs; final refreshToken = this.refreshToken; return { @@ -2064,6 +2144,7 @@ class RefreshResponse { String? refreshToken; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum AccountKind { @@ -2073,6 +2154,7 @@ enum AccountKind { user } +/// @_NameSource('generated') class RegisterResponse { RegisterResponse({ @@ -2084,7 +2166,7 @@ class RegisterResponse { required this.userId, }); - RegisterResponse.fromJson(Map json) + RegisterResponse.fromJson(Map json) : accessToken = ((v) => v != null ? v as String : null)(json['access_token']), deviceId = ((v) => v != null ? v as String : null)(json['device_id']), @@ -2095,7 +2177,7 @@ class RegisterResponse { refreshToken = ((v) => v != null ? v as String : null)(json['refresh_token']), userId = json['user_id'] as String; - Map toJson() { + Map toJson() { final accessToken = this.accessToken; final deviceId = this.deviceId; final expiresInMs = this.expiresInMs; @@ -2153,6 +2235,7 @@ class RegisterResponse { String userId; } +/// @_NameSource('spec') class RoomKeysUpdateResponse { RoomKeysUpdateResponse({ @@ -2160,10 +2243,10 @@ class RoomKeysUpdateResponse { required this.etag, }); - RoomKeysUpdateResponse.fromJson(Map json) + RoomKeysUpdateResponse.fromJson(Map json) : count = json['count'] as int, etag = json['etag'] as String; - Map toJson() => { + Map toJson() => { 'count': count, 'etag': etag, }; @@ -2186,12 +2269,12 @@ class KeyBackupData { required this.sessionData, }); - KeyBackupData.fromJson(Map json) + KeyBackupData.fromJson(Map json) : firstMessageIndex = json['first_message_index'] as int, forwardedCount = json['forwarded_count'] as int, isVerified = json['is_verified'] as bool, - sessionData = json['session_data'] as Map; - Map toJson() => { + sessionData = json['session_data'] as Map; + Map toJson() => { 'first_message_index': firstMessageIndex, 'forwarded_count': forwardedCount, 'is_verified': isVerified, @@ -2211,7 +2294,7 @@ class KeyBackupData { /// Algorithm-dependent data. See the documentation for the backup /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the /// expected format of the data. - Map sessionData; + Map sessionData; } /// The backed up keys for a room. @@ -2221,10 +2304,10 @@ class RoomKeyBackup { required this.sessions, }); - RoomKeyBackup.fromJson(Map json) - : sessions = (json['sessions'] as Map) - .map((k, v) => MapEntry(k, KeyBackupData.fromJson(v))); - Map toJson() => { + RoomKeyBackup.fromJson(Map json) + : sessions = (json['sessions'] as Map).map((k, v) => + MapEntry(k, KeyBackupData.fromJson(v as Map))); + Map toJson() => { 'sessions': sessions.map((k, v) => MapEntry(k, v.toJson())), }; @@ -2232,16 +2315,17 @@ class RoomKeyBackup { Map sessions; } +/// @_NameSource('rule override generated') class RoomKeys { RoomKeys({ required this.rooms, }); - RoomKeys.fromJson(Map json) - : rooms = (json['rooms'] as Map) - .map((k, v) => MapEntry(k, RoomKeyBackup.fromJson(v))); - Map toJson() => { + RoomKeys.fromJson(Map json) + : rooms = (json['rooms'] as Map).map((k, v) => + MapEntry(k, RoomKeyBackup.fromJson(v as Map))); + Map toJson() => { 'rooms': rooms.map((k, v) => MapEntry(k, v.toJson())), }; @@ -2249,6 +2333,7 @@ class RoomKeys { Map rooms; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum BackupAlgorithm { @@ -2256,6 +2341,7 @@ enum BackupAlgorithm { mMegolmBackupV1Curve25519AesSha2 } +/// @_NameSource('generated') class GetRoomKeysVersionCurrentResponse { GetRoomKeysVersionCurrentResponse({ @@ -2266,13 +2352,14 @@ class GetRoomKeysVersionCurrentResponse { required this.version, }); - GetRoomKeysVersionCurrentResponse.fromJson(Map json) - : algorithm = BackupAlgorithm.values.fromString(json['algorithm'])!, - authData = json['auth_data'] as Map, + GetRoomKeysVersionCurrentResponse.fromJson(Map json) + : algorithm = + BackupAlgorithm.values.fromString(json['algorithm'] as String)!, + authData = json['auth_data'] as Map, count = json['count'] as int, etag = json['etag'] as String, version = json['version'] as String; - Map toJson() => { + Map toJson() => { 'algorithm': algorithm.name, 'auth_data': authData, 'count': count, @@ -2286,7 +2373,7 @@ class GetRoomKeysVersionCurrentResponse { /// Algorithm-dependent data. See the documentation for the backup /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the /// expected format of the data. - Map authData; + Map authData; /// The number of keys stored in the backup. int count; @@ -2301,6 +2388,7 @@ class GetRoomKeysVersionCurrentResponse { String version; } +/// @_NameSource('generated') class GetRoomKeysVersionResponse { GetRoomKeysVersionResponse({ @@ -2311,13 +2399,14 @@ class GetRoomKeysVersionResponse { required this.version, }); - GetRoomKeysVersionResponse.fromJson(Map json) - : algorithm = BackupAlgorithm.values.fromString(json['algorithm'])!, - authData = json['auth_data'] as Map, + GetRoomKeysVersionResponse.fromJson(Map json) + : algorithm = + BackupAlgorithm.values.fromString(json['algorithm'] as String)!, + authData = json['auth_data'] as Map, count = json['count'] as int, etag = json['etag'] as String, version = json['version'] as String; - Map toJson() => { + Map toJson() => { 'algorithm': algorithm.name, 'auth_data': authData, 'count': count, @@ -2331,7 +2420,7 @@ class GetRoomKeysVersionResponse { /// Algorithm-dependent data. See the documentation for the backup /// algorithms in [Server-side key backups](https://spec.matrix.org/unstable/client-server-api/#server-side-key-backups) for more information on the /// expected format of the data. - Map authData; + Map authData; /// The number of keys stored in the backup. int count; @@ -2358,21 +2447,28 @@ class EventContext { this.state, }); - EventContext.fromJson(Map json) + EventContext.fromJson(Map json) : end = ((v) => v != null ? v as String : null)(json['end']), - event = - ((v) => v != null ? MatrixEvent.fromJson(v) : null)(json['event']), + event = ((v) => v != null + ? MatrixEvent.fromJson(v as Map) + : null)(json['event']), eventsAfter = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['events_after']), eventsBefore = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['events_before']), start = ((v) => v != null ? v as String : null)(json['start']), state = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['state']); - Map toJson() { + Map toJson() { final end = this.end; final event = this.event; final eventsAfter = this.eventsAfter; @@ -2412,6 +2508,7 @@ class EventContext { List? state; } +/// @_NameSource('spec') class RoomMember { RoomMember({ @@ -2419,12 +2516,12 @@ class RoomMember { this.displayName, }); - RoomMember.fromJson(Map json) - : avatarUrl = - ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + RoomMember.fromJson(Map json) + : avatarUrl = ((v) => + v != null ? Uri.parse(v as String) : null)(json['avatar_url']), displayName = ((v) => v != null ? v as String : null)(json['display_name']); - Map toJson() { + Map toJson() { final avatarUrl = this.avatarUrl; final displayName = this.displayName; return { @@ -2440,6 +2537,7 @@ class RoomMember { String? displayName; } +/// @_NameSource('(generated, rule override generated)') @EnhancedEnum() enum Membership { @@ -2465,16 +2563,18 @@ class GetRoomEventsResponse { this.state, }); - GetRoomEventsResponse.fromJson(Map json) + GetRoomEventsResponse.fromJson(Map json) : chunk = (json['chunk'] as List) - .map((v) => MatrixEvent.fromJson(v)) + .map((v) => MatrixEvent.fromJson(v as Map)) .toList(), end = ((v) => v != null ? v as String : null)(json['end']), start = json['start'] as String, state = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['state']); - Map toJson() { + Map toJson() { final end = this.end; final state = this.state; return { @@ -2519,6 +2619,7 @@ class GetRoomEventsResponse { List? state; } +/// @_NameSource('generated') @EnhancedEnum() enum ReceiptType { @@ -2530,6 +2631,7 @@ enum ReceiptType { mReadPrivate } +/// @_NameSource('spec') class IncludeEventContext { IncludeEventContext({ @@ -2538,13 +2640,13 @@ class IncludeEventContext { this.includeProfile, }); - IncludeEventContext.fromJson(Map json) + IncludeEventContext.fromJson(Map json) : afterLimit = ((v) => v != null ? v as int : null)(json['after_limit']), beforeLimit = ((v) => v != null ? v as int : null)(json['before_limit']), includeProfile = ((v) => v != null ? v as bool : null)(json['include_profile']); - Map toJson() { + Map toJson() { final afterLimit = this.afterLimit; final beforeLimit = this.beforeLimit; final includeProfile = this.includeProfile; @@ -2570,6 +2672,7 @@ class IncludeEventContext { bool? includeProfile; } +/// @_NameSource('spec') class EventFilter { EventFilter({ @@ -2580,7 +2683,7 @@ class EventFilter { this.types, }); - EventFilter.fromJson(Map json) + EventFilter.fromJson(Map json) : limit = ((v) => v != null ? v as int : null)(json['limit']), notSenders = ((v) => v != null ? (v as List).map((v) => v as String).toList() @@ -2594,7 +2697,7 @@ class EventFilter { types = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['types']); - Map toJson() { + Map toJson() { final limit = this.limit; final notSenders = this.notSenders; final notTypes = this.notTypes; @@ -2625,6 +2728,7 @@ class EventFilter { List? types; } +/// @_NameSource('spec') class RoomEventFilter { RoomEventFilter({ @@ -2636,7 +2740,7 @@ class RoomEventFilter { this.unreadThreadNotifications, }); - RoomEventFilter.fromJson(Map json) + RoomEventFilter.fromJson(Map json) : containsUrl = ((v) => v != null ? v as bool : null)(json['contains_url']), includeRedundantMembers = ((v) => @@ -2651,7 +2755,7 @@ class RoomEventFilter { : null)(json['rooms']), unreadThreadNotifications = ((v) => v != null ? v as bool : null)(json['unread_thread_notifications']); - Map toJson() { + Map toJson() { final containsUrl = this.containsUrl; final includeRedundantMembers = this.includeRedundantMembers; final lazyLoadMembers = this.lazyLoadMembers; @@ -2696,6 +2800,7 @@ class RoomEventFilter { bool? unreadThreadNotifications; } +/// @_NameSource('rule override generated') class SearchFilter implements EventFilter, RoomEventFilter { SearchFilter({ @@ -2712,7 +2817,7 @@ class SearchFilter implements EventFilter, RoomEventFilter { this.unreadThreadNotifications, }); - SearchFilter.fromJson(Map json) + SearchFilter.fromJson(Map json) : limit = ((v) => v != null ? v as int : null)(json['limit']), notSenders = ((v) => v != null ? (v as List).map((v) => v as String).toList() @@ -2740,7 +2845,7 @@ class SearchFilter implements EventFilter, RoomEventFilter { : null)(json['rooms']), unreadThreadNotifications = ((v) => v != null ? v as bool : null)(json['unread_thread_notifications']); - Map toJson() { + Map toJson() { final limit = this.limit; final notSenders = this.notSenders; final notTypes = this.notTypes; @@ -2810,6 +2915,7 @@ class SearchFilter implements EventFilter, RoomEventFilter { bool? unreadThreadNotifications; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum GroupKey { @@ -2826,10 +2932,11 @@ class Group { this.key, }); - Group.fromJson(Map json) - : key = ((v) => - v != null ? GroupKey.values.fromString(v)! : null)(json['key']); - Map toJson() { + Group.fromJson(Map json) + : key = ((v) => v != null + ? GroupKey.values.fromString(v as String)! + : null)(json['key']); + Map toJson() { final key = this.key; return { if (key != null) 'key': key.name, @@ -2840,17 +2947,20 @@ class Group { GroupKey? key; } +/// @_NameSource('spec') class Groupings { Groupings({ this.groupBy, }); - Groupings.fromJson(Map json) + Groupings.fromJson(Map json) : groupBy = ((v) => v != null - ? (v as List).map((v) => Group.fromJson(v)).toList() + ? (v as List) + .map((v) => Group.fromJson(v as Map)) + .toList() : null)(json['group_by']); - Map toJson() { + Map toJson() { final groupBy = this.groupBy; return { if (groupBy != null) 'group_by': groupBy.map((v) => v.toJson()).toList(), @@ -2861,6 +2971,7 @@ class Groupings { List? groupBy; } +/// @_NameSource('rule override generated') @EnhancedEnum() enum KeyKind { @@ -2872,6 +2983,7 @@ enum KeyKind { contentTopic } +/// @_NameSource('rule override generated') @EnhancedEnum() enum SearchOrder { @@ -2881,6 +2993,7 @@ enum SearchOrder { recent } +/// @_NameSource('spec') class RoomEventsCriteria { RoomEventsCriteria({ @@ -2893,23 +3006,28 @@ class RoomEventsCriteria { required this.searchTerm, }); - RoomEventsCriteria.fromJson(Map json) + RoomEventsCriteria.fromJson(Map json) : eventContext = ((v) => v != null - ? IncludeEventContext.fromJson(v) + ? IncludeEventContext.fromJson(v as Map) : null)(json['event_context']), - filter = ((v) => - v != null ? SearchFilter.fromJson(v) : null)(json['filter']), - groupings = ((v) => - v != null ? Groupings.fromJson(v) : null)(json['groupings']), + filter = ((v) => v != null + ? SearchFilter.fromJson(v as Map) + : null)(json['filter']), + groupings = ((v) => v != null + ? Groupings.fromJson(v as Map) + : null)(json['groupings']), includeState = ((v) => v != null ? v as bool : null)(json['include_state']), keys = ((v) => v != null - ? (v as List).map((v) => KeyKind.values.fromString(v)!).toList() + ? (v as List) + .map((v) => KeyKind.values.fromString(v as String)!) + .toList() : null)(json['keys']), - orderBy = ((v) => v != null ? SearchOrder.values.fromString(v)! : null)( - json['order_by']), + orderBy = ((v) => v != null + ? SearchOrder.values.fromString(v as String)! + : null)(json['order_by']), searchTerm = json['search_term'] as String; - Map toJson() { + Map toJson() { final eventContext = this.eventContext; final filter = this.filter; final groupings = this.groupings; @@ -2953,16 +3071,18 @@ class RoomEventsCriteria { String searchTerm; } +/// @_NameSource('spec') class Categories { Categories({ this.roomEvents, }); - Categories.fromJson(Map json) - : roomEvents = ((v) => v != null ? RoomEventsCriteria.fromJson(v) : null)( - json['room_events']); - Map toJson() { + Categories.fromJson(Map json) + : roomEvents = ((v) => v != null + ? RoomEventsCriteria.fromJson(v as Map) + : null)(json['room_events']); + Map toJson() { final roomEvents = this.roomEvents; return { if (roomEvents != null) 'room_events': roomEvents.toJson(), @@ -2982,13 +3102,13 @@ class GroupValue { this.results, }); - GroupValue.fromJson(Map json) + GroupValue.fromJson(Map json) : nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), order = ((v) => v != null ? v as int : null)(json['order']), results = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['results']); - Map toJson() { + Map toJson() { final nextBatch = this.nextBatch; final order = this.order; final results = this.results; @@ -3014,6 +3134,7 @@ class GroupValue { List? results; } +/// @_NameSource('spec') class UserProfile { UserProfile({ @@ -3021,12 +3142,12 @@ class UserProfile { this.displayname, }); - UserProfile.fromJson(Map json) - : avatarUrl = - ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + UserProfile.fromJson(Map json) + : avatarUrl = ((v) => + v != null ? Uri.parse(v as String) : null)(json['avatar_url']), displayname = ((v) => v != null ? v as String : null)(json['displayname']); - Map toJson() { + Map toJson() { final avatarUrl = this.avatarUrl; final displayname = this.displayname; return { @@ -3035,11 +3156,14 @@ class UserProfile { }; } + /// Uri? avatarUrl; + /// String? displayname; } +/// @_NameSource('rule override spec') class SearchResultsEventContext { SearchResultsEventContext({ @@ -3050,20 +3174,24 @@ class SearchResultsEventContext { this.start, }); - SearchResultsEventContext.fromJson(Map json) + SearchResultsEventContext.fromJson(Map json) : end = ((v) => v != null ? v as String : null)(json['end']), eventsAfter = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['events_after']), eventsBefore = ((v) => v != null - ? (v as List).map((v) => MatrixEvent.fromJson(v)).toList() + ? (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList() : null)(json['events_before']), profileInfo = ((v) => v != null - ? (v as Map) - .map((k, v) => MapEntry(k, UserProfile.fromJson(v))) + ? (v as Map).map((k, v) => + MapEntry(k, UserProfile.fromJson(v as Map))) : null)(json['profile_info']), start = ((v) => v != null ? v as String : null)(json['start']); - Map toJson() { + Map toJson() { final end = this.end; final eventsAfter = this.eventsAfter; final eventsBefore = this.eventsBefore; @@ -3110,14 +3238,15 @@ class Result { this.result, }); - Result.fromJson(Map json) + Result.fromJson(Map json) : context = ((v) => v != null - ? SearchResultsEventContext.fromJson(v) + ? SearchResultsEventContext.fromJson(v as Map) : null)(json['context']), rank = ((v) => v != null ? (v as num).toDouble() : null)(json['rank']), - result = - ((v) => v != null ? MatrixEvent.fromJson(v) : null)(json['result']); - Map toJson() { + result = ((v) => v != null + ? MatrixEvent.fromJson(v as Map) + : null)(json['result']); + Map toJson() { final context = this.context; final rank = this.rank; final result = this.result; @@ -3138,6 +3267,7 @@ class Result { MatrixEvent? result; } +/// @_NameSource('spec') class ResultRoomEvents { ResultRoomEvents({ @@ -3149,26 +3279,31 @@ class ResultRoomEvents { this.state, }); - ResultRoomEvents.fromJson(Map json) + ResultRoomEvents.fromJson(Map json) : count = ((v) => v != null ? v as int : null)(json['count']), groups = ((v) => v != null - ? (v as Map).map((k, v) => MapEntry( + ? (v as Map).map((k, v) => MapEntry( k, - (v as Map) - .map((k, v) => MapEntry(k, GroupValue.fromJson(v))))) + (v as Map).map((k, v) => MapEntry( + k, GroupValue.fromJson(v as Map))))) : null)(json['groups']), highlights = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['highlights']), nextBatch = ((v) => v != null ? v as String : null)(json['next_batch']), results = ((v) => v != null - ? (v as List).map((v) => Result.fromJson(v)).toList() + ? (v as List) + .map((v) => Result.fromJson(v as Map)) + .toList() : null)(json['results']), state = ((v) => v != null - ? (v as Map).map((k, v) => MapEntry( - k, (v as List).map((v) => MatrixEvent.fromJson(v)).toList())) + ? (v as Map).map((k, v) => MapEntry( + k, + (v as List) + .map((v) => MatrixEvent.fromJson(v as Map)) + .toList())) : null)(json['state']); - Map toJson() { + Map toJson() { final count = this.count; final groups = this.groups; final highlights = this.highlights; @@ -3220,16 +3355,18 @@ class ResultRoomEvents { Map>? state; } +/// @_NameSource('spec') class ResultCategories { ResultCategories({ this.roomEvents, }); - ResultCategories.fromJson(Map json) - : roomEvents = ((v) => v != null ? ResultRoomEvents.fromJson(v) : null)( - json['room_events']); - Map toJson() { + ResultCategories.fromJson(Map json) + : roomEvents = ((v) => v != null + ? ResultRoomEvents.fromJson(v as Map) + : null)(json['room_events']); + Map toJson() { final roomEvents = this.roomEvents; return { if (roomEvents != null) 'room_events': roomEvents.toJson(), @@ -3240,15 +3377,17 @@ class ResultCategories { ResultRoomEvents? roomEvents; } +/// @_NameSource('rule override spec') class SearchResults { SearchResults({ required this.searchCategories, }); - SearchResults.fromJson(Map json) - : searchCategories = ResultCategories.fromJson(json['search_categories']); - Map toJson() => { + SearchResults.fromJson(Map json) + : searchCategories = ResultCategories.fromJson( + json['search_categories'] as Map); + Map toJson() => { 'search_categories': searchCategories.toJson(), }; @@ -3256,6 +3395,7 @@ class SearchResults { ResultCategories searchCategories; } +/// @_NameSource('spec') class Location { Location({ @@ -3264,11 +3404,11 @@ class Location { required this.protocol, }); - Location.fromJson(Map json) + Location.fromJson(Map json) : alias = json['alias'] as String, - fields = json['fields'] as Map, + fields = json['fields'] as Map, protocol = json['protocol'] as String; - Map toJson() => { + Map toJson() => { 'alias': alias, 'fields': fields, 'protocol': protocol, @@ -3278,7 +3418,7 @@ class Location { String alias; /// Information used to identify this third party location. - Map fields; + Map fields; /// The protocol ID that the third party location is a part of. String protocol; @@ -3292,10 +3432,10 @@ class FieldType { required this.regexp, }); - FieldType.fromJson(Map json) + FieldType.fromJson(Map json) : placeholder = json['placeholder'] as String, regexp = json['regexp'] as String; - Map toJson() => { + Map toJson() => { 'placeholder': placeholder, 'regexp': regexp, }; @@ -3309,6 +3449,7 @@ class FieldType { String regexp; } +/// @_NameSource('spec') class ProtocolInstance { ProtocolInstance({ @@ -3318,12 +3459,12 @@ class ProtocolInstance { required this.networkId, }); - ProtocolInstance.fromJson(Map json) + ProtocolInstance.fromJson(Map json) : desc = json['desc'] as String, - fields = json['fields'] as Map, + fields = json['fields'] as Map, icon = ((v) => v != null ? v as String : null)(json['icon']), networkId = json['network_id'] as String; - Map toJson() { + Map toJson() { final icon = this.icon; return { 'desc': desc, @@ -3337,7 +3478,7 @@ class ProtocolInstance { String desc; /// Preset values for `fields` the client may use to search by. - Map fields; + Map fields; /// An optional content URI representing the protocol. Overrides the one provided /// at the higher level Protocol object. @@ -3347,6 +3488,7 @@ class ProtocolInstance { String networkId; } +/// @_NameSource('spec') class Protocol { Protocol({ @@ -3357,18 +3499,18 @@ class Protocol { required this.userFields, }); - Protocol.fromJson(Map json) - : fieldTypes = (json['field_types'] as Map) - .map((k, v) => MapEntry(k, FieldType.fromJson(v))), + Protocol.fromJson(Map json) + : fieldTypes = (json['field_types'] as Map).map((k, v) => + MapEntry(k, FieldType.fromJson(v as Map))), icon = json['icon'] as String, instances = (json['instances'] as List) - .map((v) => ProtocolInstance.fromJson(v)) + .map((v) => ProtocolInstance.fromJson(v as Map)) .toList(), locationFields = (json['location_fields'] as List).map((v) => v as String).toList(), userFields = (json['user_fields'] as List).map((v) => v as String).toList(); - Map toJson() => { + Map toJson() => { 'field_types': fieldTypes.map((k, v) => MapEntry(k, v.toJson())), 'icon': icon, 'instances': instances.map((v) => v.toJson()).toList(), @@ -3404,6 +3546,7 @@ class Protocol { List userFields; } +/// @_NameSource('rule override spec') class ThirdPartyUser { ThirdPartyUser({ @@ -3412,18 +3555,18 @@ class ThirdPartyUser { required this.userid, }); - ThirdPartyUser.fromJson(Map json) - : fields = json['fields'] as Map, + ThirdPartyUser.fromJson(Map json) + : fields = json['fields'] as Map, protocol = json['protocol'] as String, userid = json['userid'] as String; - Map toJson() => { + Map toJson() => { 'fields': fields, 'protocol': protocol, 'userid': userid, }; /// Information used to identify this third party location. - Map fields; + Map fields; /// The protocol ID that the third party location is a part of. String protocol; @@ -3432,6 +3575,7 @@ class ThirdPartyUser { String userid; } +/// @_NameSource('generated') @EnhancedEnum() enum EventFormat { @@ -3441,6 +3585,7 @@ enum EventFormat { federation } +/// @_NameSource('rule override generated') class StateFilter implements EventFilter, RoomEventFilter { StateFilter({ @@ -3457,7 +3602,7 @@ class StateFilter implements EventFilter, RoomEventFilter { this.unreadThreadNotifications, }); - StateFilter.fromJson(Map json) + StateFilter.fromJson(Map json) : limit = ((v) => v != null ? v as int : null)(json['limit']), notSenders = ((v) => v != null ? (v as List).map((v) => v as String).toList() @@ -3485,7 +3630,7 @@ class StateFilter implements EventFilter, RoomEventFilter { : null)(json['rooms']), unreadThreadNotifications = ((v) => v != null ? v as bool : null)(json['unread_thread_notifications']); - Map toJson() { + Map toJson() { final limit = this.limit; final notSenders = this.notSenders; final notTypes = this.notTypes; @@ -3555,6 +3700,7 @@ class StateFilter implements EventFilter, RoomEventFilter { bool? unreadThreadNotifications; } +/// @_NameSource('spec') class RoomFilter { RoomFilter({ @@ -3567,11 +3713,13 @@ class RoomFilter { this.timeline, }); - RoomFilter.fromJson(Map json) - : accountData = ((v) => - v != null ? StateFilter.fromJson(v) : null)(json['account_data']), - ephemeral = ((v) => - v != null ? StateFilter.fromJson(v) : null)(json['ephemeral']), + RoomFilter.fromJson(Map json) + : accountData = ((v) => v != null + ? StateFilter.fromJson(v as Map) + : null)(json['account_data']), + ephemeral = ((v) => v != null + ? StateFilter.fromJson(v as Map) + : null)(json['ephemeral']), includeLeave = ((v) => v != null ? v as bool : null)(json['include_leave']), notRooms = ((v) => v != null @@ -3580,11 +3728,13 @@ class RoomFilter { rooms = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['rooms']), - state = - ((v) => v != null ? StateFilter.fromJson(v) : null)(json['state']), - timeline = ((v) => - v != null ? StateFilter.fromJson(v) : null)(json['timeline']); - Map toJson() { + state = ((v) => v != null + ? StateFilter.fromJson(v as Map) + : null)(json['state']), + timeline = ((v) => v != null + ? StateFilter.fromJson(v as Map) + : null)(json['timeline']); + Map toJson() { final accountData = this.accountData; final ephemeral = this.ephemeral; final includeLeave = this.includeLeave; @@ -3625,6 +3775,7 @@ class RoomFilter { StateFilter? timeline; } +/// @_NameSource('spec') class Filter { Filter({ @@ -3635,19 +3786,23 @@ class Filter { this.room, }); - Filter.fromJson(Map json) - : accountData = ((v) => - v != null ? EventFilter.fromJson(v) : null)(json['account_data']), + Filter.fromJson(Map json) + : accountData = ((v) => v != null + ? EventFilter.fromJson(v as Map) + : null)(json['account_data']), eventFields = ((v) => v != null ? (v as List).map((v) => v as String).toList() : null)(json['event_fields']), eventFormat = ((v) => v != null - ? EventFormat.values.fromString(v)! + ? EventFormat.values.fromString(v as String)! : null)(json['event_format']), - presence = ((v) => - v != null ? EventFilter.fromJson(v) : null)(json['presence']), - room = ((v) => v != null ? RoomFilter.fromJson(v) : null)(json['room']); - Map toJson() { + presence = ((v) => v != null + ? EventFilter.fromJson(v as Map) + : null)(json['presence']), + room = ((v) => v != null + ? RoomFilter.fromJson(v as Map) + : null)(json['room']); + Map toJson() { final accountData = this.accountData; final eventFields = this.eventFields; final eventFormat = this.eventFormat; @@ -3679,6 +3834,7 @@ class Filter { RoomFilter? room; } +/// @_NameSource('spec') class OpenIdCredentials { OpenIdCredentials({ @@ -3688,12 +3844,12 @@ class OpenIdCredentials { required this.tokenType, }); - OpenIdCredentials.fromJson(Map json) + OpenIdCredentials.fromJson(Map json) : accessToken = json['access_token'] as String, expiresIn = json['expires_in'] as int, matrixServerName = json['matrix_server_name'] as String, tokenType = json['token_type'] as String; - Map toJson() => { + Map toJson() => { 'access_token': accessToken, 'expires_in': expiresIn, 'matrix_server_name': matrixServerName, @@ -3717,6 +3873,7 @@ class OpenIdCredentials { String tokenType; } +/// @_NameSource('spec') class Tag { Tag({ @@ -3724,13 +3881,13 @@ class Tag { this.additionalProperties = const {}, }); - Tag.fromJson(Map json) + Tag.fromJson(Map json) : order = ((v) => v != null ? (v as num).toDouble() : null)(json['order']), additionalProperties = Map.fromEntries(json.entries .where((e) => !['order'].contains(e.key)) - .map((e) => MapEntry(e.key, e.value as dynamic))); - Map toJson() { + .map((e) => MapEntry(e.key, e.value as Object?))); + Map toJson() { final order = this.order; return { ...additionalProperties, @@ -3742,9 +3899,10 @@ class Tag { /// position of the room under the given tag. double? order; - Map additionalProperties; + Map additionalProperties; } +/// @_NameSource('rule override spec') class Profile { Profile({ @@ -3753,13 +3911,13 @@ class Profile { required this.userId, }); - Profile.fromJson(Map json) - : avatarUrl = - ((v) => v != null ? Uri.parse(v) : null)(json['avatar_url']), + Profile.fromJson(Map json) + : avatarUrl = ((v) => + v != null ? Uri.parse(v as String) : null)(json['avatar_url']), displayName = ((v) => v != null ? v as String : null)(json['display_name']), userId = json['user_id'] as String; - Map toJson() { + Map toJson() { final avatarUrl = this.avatarUrl; final displayName = this.displayName; return { @@ -3779,6 +3937,7 @@ class Profile { String userId; } +/// @_NameSource('generated') class SearchUserDirectoryResponse { SearchUserDirectoryResponse({ @@ -3786,11 +3945,12 @@ class SearchUserDirectoryResponse { required this.results, }); - SearchUserDirectoryResponse.fromJson(Map json) + SearchUserDirectoryResponse.fromJson(Map json) : limited = json['limited'] as bool, - results = - (json['results'] as List).map((v) => Profile.fromJson(v)).toList(); - Map toJson() => { + results = (json['results'] as List) + .map((v) => Profile.fromJson(v as Map)) + .toList(); + Map toJson() => { 'limited': limited, 'results': results.map((v) => v.toJson()).toList(), }; @@ -3802,6 +3962,7 @@ class SearchUserDirectoryResponse { List results; } +/// @_NameSource('rule override generated') class TurnServerCredentials { TurnServerCredentials({ @@ -3811,12 +3972,12 @@ class TurnServerCredentials { required this.username, }); - TurnServerCredentials.fromJson(Map json) + TurnServerCredentials.fromJson(Map json) : password = json['password'] as String, ttl = json['ttl'] as int, uris = (json['uris'] as List).map((v) => v as String).toList(), username = json['username'] as String; - Map toJson() => { + Map toJson() => { 'password': password, 'ttl': ttl, 'uris': uris.map((v) => v).toList(), @@ -3836,6 +3997,7 @@ class TurnServerCredentials { String username; } +/// @_NameSource('generated') class GetVersionsResponse { GetVersionsResponse({ @@ -3843,12 +4005,12 @@ class GetVersionsResponse { required this.versions, }); - GetVersionsResponse.fromJson(Map json) + GetVersionsResponse.fromJson(Map json) : unstableFeatures = ((v) => v != null - ? (v as Map).map((k, v) => MapEntry(k, v as bool)) + ? (v as Map).map((k, v) => MapEntry(k, v as bool)) : null)(json['unstable_features']), versions = (json['versions'] as List).map((v) => v as String).toList(); - Map toJson() { + Map toJson() { final unstableFeatures = this.unstableFeatures; return { if (unstableFeatures != null) @@ -3866,16 +4028,17 @@ class GetVersionsResponse { List versions; } +/// @_NameSource('rule override generated') class ServerConfig { ServerConfig({ this.mUploadSize, }); - ServerConfig.fromJson(Map json) + ServerConfig.fromJson(Map json) : mUploadSize = ((v) => v != null ? v as int : null)(json['m.upload.size']); - Map toJson() { + Map toJson() { final mUploadSize = this.mUploadSize; return { if (mUploadSize != null) 'm.upload.size': mUploadSize, @@ -3888,6 +4051,7 @@ class ServerConfig { int? mUploadSize; } +/// @_NameSource('generated') class GetUrlPreviewResponse { GetUrlPreviewResponse({ @@ -3895,11 +4059,12 @@ class GetUrlPreviewResponse { this.ogImage, }); - GetUrlPreviewResponse.fromJson(Map json) + GetUrlPreviewResponse.fromJson(Map json) : matrixImageSize = ((v) => v != null ? v as int : null)(json['matrix:image:size']), - ogImage = ((v) => v != null ? Uri.parse(v) : null)(json['og:image']); - Map toJson() { + ogImage = ((v) => + v != null ? Uri.parse(v as String) : null)(json['og:image']); + Map toJson() { final matrixImageSize = this.matrixImageSize; final ogImage = this.ogImage; return { @@ -3915,6 +4080,7 @@ class GetUrlPreviewResponse { Uri? ogImage; } +/// @_NameSource('generated') @EnhancedEnum() enum Method { From 06d587e64f6bfb13498757dc6f8e09812529ae53 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Fri, 9 Jun 2023 09:49:24 +0200 Subject: [PATCH 158/174] refactor: Changed Map to Map - contains breaking changes because some type casts will be needed in Matrix SDK --- lib/fake_matrix_api.dart | 210 +++++++++--------- lib/src/matrix_api.dart | 14 +- lib/src/model/auth/authentication_data.dart | 6 +- .../model/auth/authentication_identifier.dart | 8 +- .../model/auth/authentication_password.dart | 6 +- .../auth/authentication_phone_identifier.dart | 4 +- .../model/auth/authentication_recaptcha.dart | 4 +- ...authentication_third_party_identifier.dart | 4 +- .../auth/authentication_three_pid_creds.dart | 12 +- lib/src/model/auth/authentication_token.dart | 4 +- .../auth/authentication_user_identifier.dart | 4 +- lib/src/model/basic_event.dart | 10 +- lib/src/model/basic_event_with_sender.dart | 6 +- lib/src/model/basic_room_event.dart | 6 +- lib/src/model/children_state.dart | 6 +- .../events/forwarded_room_key_content.dart | 4 +- lib/src/model/events/image_pack_content.dart | 32 +-- .../model/events/olm_plaintext_payload.dart | 8 +- .../model/events/room_encrypted_content.dart | 16 +- .../model/events/room_encryption_content.dart | 6 +- lib/src/model/events/room_key_content.dart | 6 +- .../events/room_key_request_content.dart | 14 +- .../secret_storage_default_key_content.dart | 6 +- .../events/secret_storage_key_content.dart | 14 +- lib/src/model/events/tombstone_content.dart | 6 +- lib/src/model/matrix_event.dart | 14 +- lib/src/model/matrix_exception.dart | 12 +- lib/src/model/matrix_keys.dart | 32 +-- lib/src/model/presence.dart | 4 +- lib/src/model/presence_content.dart | 6 +- lib/src/model/room_keys_keys.dart | 26 +-- lib/src/model/room_summary.dart | 6 +- lib/src/model/stripped_state_event.dart | 6 +- lib/src/model/sync_update.dart | 84 +++---- lib/src/utils/map_copy_extension.dart | 8 +- lib/src/utils/try_get_map_extension.dart | 6 +- test/event_content_test.dart | 52 ++--- test/map_copy_extension_test.dart | 18 +- test/matrix_api_test.dart | 26 +-- test/try_get_map_extension_test.dart | 10 +- 40 files changed, 363 insertions(+), 363 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index fc32738f..76002f73 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -30,14 +30,14 @@ import 'package:http/testing.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; -Map decodeJson(dynamic data) { +Map decodeJson(dynamic data) { if (data is String) { - return json.decode(data) as Map; + return json.decode(data) as Map; } if (data is Map && data.isEmpty) { - return {}; + return {}; } - return data as Map; + return data as Map; } T? tryCast(dynamic object) => object is T ? object : null; @@ -65,13 +65,13 @@ class FakeMatrixApi extends MockClient { final method = request.method; final dynamic data = method == 'GET' ? request.url.queryParameters : request.body; - dynamic res = {}; + dynamic res = {}; var statusCode = 200; //print('\$method request to $action with Data: $data'); // Sync requests with timeout - if (data is Map && data['timeout'] is String) { + if (data is Map && data['timeout'] is String) { await Future.delayed(Duration(seconds: 5)); } @@ -92,7 +92,7 @@ class FakeMatrixApi extends MockClient { } } else if (method == 'PUT' && action.contains('/client/v3/sendToDevice/')) { - res = {}; + res = {}; } else if (method == 'GET' && action.contains('/client/v3/rooms/') && action.contains('/state/m.room.member/')) { @@ -116,7 +116,7 @@ class FakeMatrixApi extends MockClient { return Response.bytes(utf8.encode(json.encode(res)), statusCode); }); - static Map messagesResponse = { + static Map messagesResponse = { 'start': 't47429-4392820_219380_26003_2265', 'end': 't47409-4357353_219380_26003_2265', 'chunk': [ @@ -172,10 +172,10 @@ class FakeMatrixApi extends MockClient { 'unsigned': {'age': 1234} } ], - 'state': >[], + 'state': >[], }; - static Map syncResponse = { + static Map syncResponse = { 'next_batch': Random().nextDouble().toString(), 'rooms': { 'join': { @@ -394,7 +394,7 @@ class FakeMatrixApi extends MockClient { 'override': [ { 'actions': ['dont_notify'], - 'conditions': >[], + 'conditions': >[], 'default': true, 'enabled': false, 'rule_id': '.m.rule.master' @@ -428,7 +428,7 @@ class FakeMatrixApi extends MockClient { 'rule_id': '!localpart:server.abc' } ], - 'sender': >[], + 'sender': >[], 'underride': [ { 'actions': [ @@ -676,14 +676,14 @@ class FakeMatrixApi extends MockClient { 'device_one_time_keys_count': {'curve25519': 10, 'signed_curve25519': 20}, }; - static Map archiveSyncResponse = { + static Map archiveSyncResponse = { 'next_batch': Random().nextDouble().toString(), - 'presence': {'events': >[]}, - 'account_data': {'events': >[]}, - 'to_device': {'events': >[]}, + 'presence': {'events': >[]}, + 'account_data': {'events': >[]}, + 'to_device': {'events': >[]}, 'rooms': { - 'join': {}, - 'invite': {}, + 'join': {}, + 'invite': {}, 'leave': { '!5345234234:example.com': { 'timeline': { @@ -728,7 +728,7 @@ class FakeMatrixApi extends MockClient { }, }, '!5345234235:example.com': { - 'timeline': {'events': >[]}, + 'timeline': {'events': >[]}, 'state': { 'events': [ { @@ -748,7 +748,7 @@ class FakeMatrixApi extends MockClient { } }; - static Map spaceHierarchyResponse = { + static Map spaceHierarchyResponse = { 'rooms': [ { 'room_id': '!gPxZhKUssFZKZcoCKY:neko.dev', @@ -864,7 +864,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': >[] + 'children_state': >[] }, { 'room_id': '!aZUzMIEZvEwnDquxLf:neko.dev', @@ -877,7 +877,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': >[] + 'children_state': >[] }, { 'room_id': '!aRzRZBvOAkHMcEjAPS:libera.chat', @@ -889,7 +889,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': >[] + 'children_state': >[] }, { 'room_id': '!DXsRRxkqqDhDkAyXfL:matrix.org', @@ -902,7 +902,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': >[] + 'children_state': >[] }, { 'room_id': '!tbCRpmsMiwMBlIThOd:matrix.org', @@ -914,7 +914,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': false, 'guest_can_join': false, - 'children_state': >[] + 'children_state': >[] }, { 'room_id': '!LPpmvMsEgDwuSuHSpM:matrix.org', @@ -926,7 +926,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': >[] + 'children_state': >[] }, { 'room_id': '!prlZxmnmAGuCYHUNSw:neko.dev', @@ -939,7 +939,7 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': false, - 'children_state': >[] + 'children_state': >[] }, { 'room_id': '!ooHixUOgoLVUjCSMZC:matrix.org', @@ -951,12 +951,12 @@ class FakeMatrixApi extends MockClient { 'join_rule': 'public', 'world_readable': true, 'guest_can_join': true, - 'children_state': >[] + 'children_state': >[] } ] }; - static final Map> api = { + static final Map> api = { 'GET': { '/path/to/auth/error': (var req) => { 'errcode': 'M_FORBIDDEN', @@ -983,7 +983,7 @@ class FakeMatrixApi extends MockClient { 'tags': { 'm.favourite': {'order': 0.1}, 'u.Work': {'order': 0.7}, - 'u.Customers': {}, + 'u.Customers': {}, } }, '/client/v3/events?from=1234&timeout=10&room_id=%211234': (var req) => { @@ -1093,7 +1093,7 @@ class FakeMatrixApi extends MockClient { 'network_id': 'gitter', 'desc': 'Gitter', 'icon': 'mxc://example.org/zXyWvUt', - 'fields': {} + 'fields': {} } ] } @@ -1611,7 +1611,7 @@ class FakeMatrixApi extends MockClient { 'override': [ { 'actions': ['dont_notify'], - 'conditions': >[], + 'conditions': >[], 'default': true, 'enabled': false, 'rule_id': '.m.rule.master' @@ -1630,8 +1630,8 @@ class FakeMatrixApi extends MockClient { 'rule_id': '.m.rule.suppress_notices' } ], - 'room': >[], - 'sender': >[], + 'room': >[], + 'sender': >[], 'underride': [ { 'actions': [ @@ -1781,7 +1781,7 @@ class FakeMatrixApi extends MockClient { 'algorithm': AlgorithmTypes.megolmBackupV1Curve25519AesSha2, 'auth_data': { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', - 'signatures': {}, + 'signatures': {}, }, 'count': 0, 'etag': '0', @@ -1840,15 +1840,15 @@ class FakeMatrixApi extends MockClient { (var req) => spaceHierarchyResponse, }, 'POST': { - '/client/v3/delete_devices': (var req) => {}, - '/client/v3/account/3pid/add': (var req) => {}, - '/client/v3/account/3pid/bind': (var req) => {}, + '/client/v3/delete_devices': (var req) => {}, + '/client/v3/account/3pid/add': (var req) => {}, + '/client/v3/account/3pid/bind': (var req) => {}, '/client/v3/account/3pid/delete': (var req) => {'id_server_unbind_result': 'success'}, '/client/v3/account/3pid/unbind': (var req) => {'id_server_unbind_result': 'success'}, - '/client/v3/account/password': (var req) => {}, - '/client/v3/rooms/1234/report/1234': (var req) => {}, + '/client/v3/account/password': (var req) => {}, + '/client/v3/rooms/1234/report/1234': (var req) => {}, '/client/v3/search': (var req) => { 'search_categories': { 'room_events': { @@ -1924,9 +1924,9 @@ class FakeMatrixApi extends MockClient { 'submit_url': 'https://example.org/path/to/submitToken' }, '/client/v3/rooms/!localpart%3Aexample.com/receipt/m.read/%241234%3Aexample.com': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aexample.com/read_markers': (var req) => - {}, + {}, '/client/v3/user/${Uri.encodeComponent('alice@example.com')}/filter': (var req) => {'filter_id': '1234'}, '/client/v3/publicRooms?server=example.com': (var req) => { @@ -1948,11 +1948,11 @@ class FakeMatrixApi extends MockClient { }, '/client/v3/keys/claim': (dynamic req) { final request = decodeJson(req)["one_time_keys"]; - final keys = (request is Map) - ? request["one_time_keys"] as Map? + final keys = (request is Map) + ? request["one_time_keys"] as Map? : null; return { - 'failures': {}, + 'failures': {}, 'one_time_keys': { if (keys?['@alice:example.com'] != null) '@alice:example.com': { @@ -1986,19 +1986,19 @@ class FakeMatrixApi extends MockClient { }; }, '/client/v3/rooms/!localpart%3Aexample.com/invite': (var req) => - {}, + {}, '/client/v3/rooms/!localpart%3Aexample.com/leave': (var req) => - {}, + {}, '/client/v3/rooms/!localpart%3Aexample.com/forget': (var req) => - {}, + {}, '/client/v3/rooms/!localpart%3Aserver.abc/kick': (var req) => - {}, + {}, '/client/v3/rooms/!localpart%3Aexample.com/kick': (var req) => - {}, + {}, '/client/v3/rooms/!localpart%3Aexample.com/ban': (var req) => - {}, + {}, '/client/v3/rooms/!localpart%3Aexample.com/unban': (var req) => - {}, + {}, '/client/v3/rooms/!localpart%3Aexample.com/join': (var req) => {'room_id': '!localpart:example.com'}, '/client/v3/join/!localpart%3Aexample.com?server_name=example.com&server_name=example.abc': @@ -2006,7 +2006,7 @@ class FakeMatrixApi extends MockClient { '/client/v3/keys/upload': (var req) => { 'one_time_key_counts': { 'curve25519': 10, - 'signed_curve25519': tryCast>>( + 'signed_curve25519': tryCast>>( decodeJson(req))?['one_time_keys'] ?.keys .length ?? @@ -2014,7 +2014,7 @@ class FakeMatrixApi extends MockClient { } }, '/client/v3/keys/query': (var req) => { - 'failures': {}, + 'failures': {}, 'device_keys': { '@alice:example.com': { 'JLAFKJWSCS': { @@ -2136,7 +2136,7 @@ class FakeMatrixApi extends MockClient { 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8', }, - 'signatures': {}, + 'signatures': {}, }, '@othertest:fakeServer.notExisting': { 'user_id': '@othertest:fakeServer.notExisting', @@ -2144,7 +2144,7 @@ class FakeMatrixApi extends MockClient { 'keys': { 'ed25519:master': 'master', }, - 'signatures': {}, + 'signatures': {}, }, }, 'self_signing_keys': { @@ -2168,7 +2168,7 @@ class FakeMatrixApi extends MockClient { 'keys': { 'ed25519:self_signing': 'self_signing', }, - 'signatures': {}, + 'signatures': {}, }, }, 'user_signing_keys': { @@ -2192,7 +2192,7 @@ class FakeMatrixApi extends MockClient { 'keys': { 'ed25519:user_signing': 'user_signing', }, - 'signatures': {}, + 'signatures': {}, }, }, }, @@ -2232,64 +2232,64 @@ class FakeMatrixApi extends MockClient { }, '/media/v3/upload?filename=file.jpeg': (var req) => {'content_uri': 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'}, - '/client/v3/logout': (var reqI) => {}, - '/client/v3/pushers/set': (var reqI) => {}, + '/client/v3/logout': (var reqI) => {}, + '/client/v3/pushers/set': (var reqI) => {}, '/client/v3/join/1234': (var reqI) => {'room_id': '1234'}, - '/client/v3/logout/all': (var reqI) => {}, + '/client/v3/logout/all': (var reqI) => {}, '/client/v3/createRoom': (var reqI) => { 'room_id': '!1234:fakeServer.notExisting', }, '/client/v3/rooms/!localpart%3Aserver.abc/read_markers': (var reqI) => - {}, + {}, '/client/v3/rooms/!localpart:server.abc/kick': (var reqI) => - {}, + {}, '/client/v3/rooms/!localpart%3Aserver.abc/ban': (var reqI) => - {}, + {}, '/client/v3/rooms/!localpart%3Aserver.abc/unban': (var reqI) => - {}, + {}, '/client/v3/rooms/!localpart%3Aserver.abc/invite': (var reqI) => - {}, + {}, '/client/v3/keys/device_signing/upload': (var reqI) { - return {}; + return {}; }, '/client/v3/keys/signatures/upload': (var reqI) => - {'failures': {}}, + {'failures': {}}, '/client/v3/room_keys/version': (var reqI) => {'version': '5'}, }, 'PUT': { '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/m.ignored_user_list': - (var req) => {}, + (var req) => {}, '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status': - (var req) => {}, + (var req) => {}, '/client/v3/pushrules/global/content/nocake/enabled': (var req) => - {}, + {}, '/client/v3/pushrules/global/content/nocake/actions': (var req) => - {}, + {}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.history_visibility': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.join_rules': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.guest_access': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.invite/1234': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.answer/1234': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.candidates/1234': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.call.hangup/1234': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!1234%3Aexample.com/redact/1143273582443PhrSn%3Aexample.org/1234': (var req) => {'event_id': '1234'}, '/client/v3/pushrules/global/room/!localpart%3Aserver.abc': (var req) => - {}, + {}, '/client/v3/pushrules/global/override/.m.rule.master/enabled': - (var req) => {}, + (var req) => {}, '/client/v3/pushrules/global/content/nocake?before=1&after=2': - (var req) => {}, - '/client/v3/devices/QBUAZIFURK': (var req) => {}, + (var req) => {}, + '/client/v3/devices/QBUAZIFURK': (var req) => {}, '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => - {}, + {}, '/client/v3/rooms/!localpart%3Aserver.abc/send/m.room.message/testtxid': (var reqI) => { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', @@ -2299,7 +2299,7 @@ class FakeMatrixApi extends MockClient { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', }, '/client/v3/rooms/!localpart%3Aexample.com/typing/%40alice%3Aexample.com': - (var req) => {}, + (var req) => {}, '/client/v3/rooms/!1234%3Aexample.com/send/m.room.message/1234': (var reqI) => { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', @@ -2309,27 +2309,27 @@ class FakeMatrixApi extends MockClient { 'event_id': '\$event${FakeMatrixApi.eventCounter++}', }, '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40alice%3Aexample.com/account_data/test.account.data': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/best%20animal': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/account_data/com.famedly.marked_unread': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/m.direct': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40othertest%3AfakeServer.notExisting/account_data/m.direct': - (var req) => {}, + (var req) => {}, '/client/v3/profile/%40alice%3Aexample.com/displayname': (var reqI) => - {}, + {}, '/client/v3/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => - {}, + {}, '/client/v3/profile/%40test%3AfakeServer.notExisting/avatar_url': - (var reqI) => {}, + (var reqI) => {}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.encryption': (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, '/client/v3/rooms/!localpart%3Aserver.abc/state/m.room.avatar': @@ -2355,8 +2355,8 @@ class FakeMatrixApi extends MockClient { 'event_id': '42', }, '/client/v3/directory/list/room/!localpart%3Aexample.com': (var req) => - {}, - '/client/v3/room_keys/version/5': (var req) => {}, + {}, + '/client/v3/room_keys/version/5': (var req) => {}, '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': (var req) => { 'etag': 'asdf', @@ -2374,18 +2374,18 @@ class FakeMatrixApi extends MockClient { }, 'DELETE': { '/unknown/token': (var req) => {'errcode': 'M_UNKNOWN_TOKEN'}, - '/client/v3/devices/QBUAZIFURK': (var req) => {}, + '/client/v3/devices/QBUAZIFURK': (var req) => {}, '/client/v3/directory/room/%23testalias%3Aexample.com': (var reqI) => - {}, + {}, '/client/v3/pushrules/global/content/nocake': (var req) => - {}, + {}, '/client/v3/pushrules/global/override/!localpart%3Aserver.abc': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40test%3AfakeServer.notExisting/rooms/!localpart%3Aserver.abc/tags/m.favourite': - (var req) => {}, + (var req) => {}, '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags/testtag': - (var req) => {}, - '/client/v3/room_keys/version/5': (var req) => {}, + (var req) => {}, + '/client/v3/room_keys/version/5': (var req) => {}, '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5': (var req) => { 'etag': 'asdf', diff --git a/lib/src/matrix_api.dart b/lib/src/matrix_api.dart index 772fc58d..605b4932 100644 --- a/lib/src/matrix_api.dart +++ b/lib/src/matrix_api.dart @@ -48,7 +48,7 @@ class MatrixApi extends Api { Never unexpectedResponse(http.BaseResponse response, Uint8List body) { if (response.statusCode >= 400 && response.statusCode < 500) { final resp = json.decode(utf8.decode(body)); - if (resp is Map) { + if (resp is Map) { throw MatrixException.fromJson(resp); } } @@ -82,12 +82,12 @@ class MatrixApi extends Api { /// ); /// ``` /// - Future> request( + Future> request( RequestType type, String action, { dynamic data = '', String contentType = 'application/json', - Map? query, + Map? query, }) async { if (homeserver == null) { throw ('No homeserver specified.'); @@ -108,7 +108,7 @@ class MatrixApi extends Api { } late http.Response resp; - Map? jsonResp = {}; + Map? jsonResp = {}; try { switch (type) { case RequestType.GET: @@ -138,7 +138,7 @@ class MatrixApi extends Api { jsonString = '{"chunk":$jsonString}'; } jsonResp = jsonDecode(jsonString) - as Map?; // May throw FormatException + as Map?; // May throw FormatException } catch (e, s) { throw MatrixConnectionException(e, s); } @@ -153,8 +153,8 @@ class MatrixApi extends Api { /// https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query Future> uploadKeys( {MatrixDeviceKeys? deviceKeys, - Map? oneTimeKeys, - Map? fallbackKeys}) async { + Map? oneTimeKeys, + Map? fallbackKeys}) async { final response = await request( RequestType.POST, '/client/v3/keys/upload', diff --git a/lib/src/model/auth/authentication_data.dart b/lib/src/model/auth/authentication_data.dart index a01faafc..27eae960 100644 --- a/lib/src/model/auth/authentication_data.dart +++ b/lib/src/model/auth/authentication_data.dart @@ -29,12 +29,12 @@ class AuthenticationData { AuthenticationData({this.type, this.session}); - AuthenticationData.fromJson(Map json) + AuthenticationData.fromJson(Map json) : type = json['type'] as String?, session = json['session'] as String?; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (type != null) data['type'] = type; if (session != null) data['session'] = session; return data; diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/src/model/auth/authentication_identifier.dart index e02cf840..06ead12d 100644 --- a/lib/src/model/auth/authentication_identifier.dart +++ b/lib/src/model/auth/authentication_identifier.dart @@ -31,10 +31,10 @@ class AuthenticationIdentifier { AuthenticationIdentifier({required this.type}); - AuthenticationIdentifier.fromJson(Map json) + AuthenticationIdentifier.fromJson(Map json) : type = json['type'] as String; - factory AuthenticationIdentifier.subFromJson(Map json) { + factory AuthenticationIdentifier.subFromJson(Map json) { switch (json['type']) { case AuthenticationIdentifierTypes.userId: return AuthenticationUserIdentifier.fromJson(json); @@ -47,8 +47,8 @@ class AuthenticationIdentifier { } } - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['type'] = type; return data; } diff --git a/lib/src/model/auth/authentication_password.dart b/lib/src/model/auth/authentication_password.dart index 4135a535..a9033445 100644 --- a/lib/src/model/auth/authentication_password.dart +++ b/lib/src/model/auth/authentication_password.dart @@ -40,14 +40,14 @@ class AuthenticationPassword extends AuthenticationData { session: session, ); - AuthenticationPassword.fromJson(Map json) + AuthenticationPassword.fromJson(Map json) : password = json['password'] as String, identifier = AuthenticationIdentifier.subFromJson( - json['identifier'] as Map), + json['identifier'] as Map), super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['password'] = password; data['identifier'] = identifier.toJson(); diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/src/model/auth/authentication_phone_identifier.dart index 0c79d7d3..e12b510e 100644 --- a/lib/src/model/auth/authentication_phone_identifier.dart +++ b/lib/src/model/auth/authentication_phone_identifier.dart @@ -31,13 +31,13 @@ class AuthenticationPhoneIdentifier extends AuthenticationIdentifier { AuthenticationPhoneIdentifier({required this.country, required this.phone}) : super(type: AuthenticationIdentifierTypes.phone); - AuthenticationPhoneIdentifier.fromJson(Map json) + AuthenticationPhoneIdentifier.fromJson(Map json) : country = json['country'] as String, phone = json['phone'] as String, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['country'] = country; data['phone'] = phone; diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/src/model/auth/authentication_recaptcha.dart index 5244e16d..33009b31 100644 --- a/lib/src/model/auth/authentication_recaptcha.dart +++ b/lib/src/model/auth/authentication_recaptcha.dart @@ -33,12 +33,12 @@ class AuthenticationRecaptcha extends AuthenticationData { session: session, ); - AuthenticationRecaptcha.fromJson(Map json) + AuthenticationRecaptcha.fromJson(Map json) : response = json['response'] as String, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['response'] = response; return data; diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/src/model/auth/authentication_third_party_identifier.dart index f40fd98b..55bc8c40 100644 --- a/lib/src/model/auth/authentication_third_party_identifier.dart +++ b/lib/src/model/auth/authentication_third_party_identifier.dart @@ -32,13 +32,13 @@ class AuthenticationThirdPartyIdentifier extends AuthenticationIdentifier { {required this.medium, required this.address}) : super(type: AuthenticationIdentifierTypes.thirdParty); - AuthenticationThirdPartyIdentifier.fromJson(Map json) + AuthenticationThirdPartyIdentifier.fromJson(Map json) : medium = json['medium'] as String, address = json['address'] as String, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['medium'] = medium; data['address'] = address; diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/src/model/auth/authentication_three_pid_creds.dart index a1a119de..89e5784a 100644 --- a/lib/src/model/auth/authentication_three_pid_creds.dart +++ b/lib/src/model/auth/authentication_three_pid_creds.dart @@ -37,16 +37,16 @@ class AuthenticationThreePidCreds extends AuthenticationData { session: session, ); - AuthenticationThreePidCreds.fromJson(Map json) + AuthenticationThreePidCreds.fromJson(Map json) : super.fromJson(json) { final creds = json['threepid_creds']; - if (creds is Map) { + if (creds is Map) { threepidCreds = ThreepidCreds.fromJson(creds); } } @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['threepid_creds'] = threepidCreds.toJson(); return data; @@ -65,14 +65,14 @@ class ThreepidCreds { this.idServer, this.idAccessToken}); - ThreepidCreds.fromJson(Map json) + ThreepidCreds.fromJson(Map json) : sid = json['sid'] as String, clientSecret = json['client_secret'] as String, idServer = json['id_server'] as String?, idAccessToken = json['id_access_token'] as String?; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['sid'] = sid; data['client_secret'] = clientSecret; if (idServer != null) data['id_server'] = idServer; diff --git a/lib/src/model/auth/authentication_token.dart b/lib/src/model/auth/authentication_token.dart index 7c86bd45..fc375f5d 100644 --- a/lib/src/model/auth/authentication_token.dart +++ b/lib/src/model/auth/authentication_token.dart @@ -36,13 +36,13 @@ class AuthenticationToken extends AuthenticationData { session: session, ); - AuthenticationToken.fromJson(Map json) + AuthenticationToken.fromJson(Map json) : token = json['token'] as String, txnId = json['txn_id'] as String?, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['token'] = token; data['txn_id'] = txnId; diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/src/model/auth/authentication_user_identifier.dart index 1736c47a..232cafe6 100644 --- a/lib/src/model/auth/authentication_user_identifier.dart +++ b/lib/src/model/auth/authentication_user_identifier.dart @@ -30,12 +30,12 @@ class AuthenticationUserIdentifier extends AuthenticationIdentifier { AuthenticationUserIdentifier({required this.user}) : super(type: AuthenticationIdentifierTypes.userId); - AuthenticationUserIdentifier.fromJson(Map json) + AuthenticationUserIdentifier.fromJson(Map json) : user = json['user'] as String, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['user'] = user; return data; diff --git a/lib/src/model/basic_event.dart b/lib/src/model/basic_event.dart index e91c2e80..9700fc02 100644 --- a/lib/src/model/basic_event.dart +++ b/lib/src/model/basic_event.dart @@ -25,19 +25,19 @@ import '../utils/map_copy_extension.dart'; class BasicEvent { String type; - Map content; + Map content; BasicEvent({ required this.type, required this.content, }); - BasicEvent.fromJson(Map json) + BasicEvent.fromJson(Map json) : type = json['type'] as String, - content = (json['content'] as Map).copy(); + content = (json['content'] as Map).copy(); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['type'] = type; data['content'] = content; return data; diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/src/model/basic_event_with_sender.dart index cb3a6486..7da96bf8 100644 --- a/lib/src/model/basic_event_with_sender.dart +++ b/lib/src/model/basic_event_with_sender.dart @@ -28,16 +28,16 @@ class BasicEventWithSender extends BasicEvent { BasicEventWithSender( {required String type, - required Map content, + required Map content, required this.senderId}) : super(type: type, content: content); - BasicEventWithSender.fromJson(Map json) + BasicEventWithSender.fromJson(Map json) : senderId = json['sender'] as String, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['sender'] = senderId; return data; diff --git a/lib/src/model/basic_room_event.dart b/lib/src/model/basic_room_event.dart index 1771e2ca..97f242ea 100644 --- a/lib/src/model/basic_room_event.dart +++ b/lib/src/model/basic_room_event.dart @@ -28,19 +28,19 @@ class BasicRoomEvent extends BasicEvent { BasicRoomEvent({ this.roomId, - required Map content, + required Map content, required String type, }) : super( content: content, type: type, ); - BasicRoomEvent.fromJson(Map json) + BasicRoomEvent.fromJson(Map json) : roomId = json['room_id'] as String?, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); if (roomId != null) data['room_id'] = roomId; return data; diff --git a/lib/src/model/children_state.dart b/lib/src/model/children_state.dart index 03b0688b..f5ae40de 100644 --- a/lib/src/model/children_state.dart +++ b/lib/src/model/children_state.dart @@ -28,7 +28,7 @@ class ChildrenState extends StrippedStateEvent { ChildrenState({ required String type, - required Map content, + required Map content, required String senderId, required String stateKey, required this.originServerTs, @@ -38,13 +38,13 @@ class ChildrenState extends StrippedStateEvent { senderId: senderId, stateKey: stateKey); - ChildrenState.fromJson(Map json) + ChildrenState.fromJson(Map json) : originServerTs = DateTime.fromMillisecondsSinceEpoch( json['origin_server_ts'] as int), super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['origin_server_ts'] = originServerTs.millisecondsSinceEpoch; return data; diff --git a/lib/src/model/events/forwarded_room_key_content.dart b/lib/src/model/events/forwarded_room_key_content.dart index 46196692..8fbf4311 100644 --- a/lib/src/model/events/forwarded_room_key_content.dart +++ b/lib/src/model/events/forwarded_room_key_content.dart @@ -35,7 +35,7 @@ class ForwardedRoomKeyContent extends RoomKeyContent { String senderClaimedEd25519Key; List forwardingCurve25519KeyChain; - ForwardedRoomKeyContent.fromJson(Map json) + ForwardedRoomKeyContent.fromJson(Map json) : senderKey = json.tryGet('sender_key', TryGet.required) ?? '', senderClaimedEd25519Key = json.tryGet('sender_claimed_ed25519_key', TryGet.required) ?? '', @@ -45,7 +45,7 @@ class ForwardedRoomKeyContent extends RoomKeyContent { super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['sender_key'] = senderKey; data['sender_claimed_ed25519_key'] = senderClaimedEd25519Key; diff --git a/lib/src/model/events/image_pack_content.dart b/lib/src/model/events/image_pack_content.dart index 4365f0ea..ff465df2 100644 --- a/lib/src/model/events/image_pack_content.dart +++ b/lib/src/model/events/image_pack_content.dart @@ -66,31 +66,31 @@ List imagePackUsageToJson( class ImagePackContent { // we want to preserve potential custom keys in this object - final Map _json; + final Map _json; Map images; ImagePackPackContent pack; ImagePackContent({required this.images, required this.pack}) : _json = {}; - ImagePackContent.fromJson(Map json) + ImagePackContent.fromJson(Map json) : _json = Map.fromEntries(json.entries.where( (e) => !['images', 'pack', 'emoticons', 'short'].contains(e.key))), pack = ImagePackPackContent.fromJson( - json.tryGetMap('pack') ?? {}), - images = json.tryGetMap('images')?.catchMap((k, v) => + json.tryGetMap('pack') ?? {}), + images = json.tryGetMap('images')?.catchMap((k, v) => MapEntry( k, ImagePackImageContent.fromJson( - v as Map))) ?? + v as Map))) ?? // the "emoticons" key needs a small migration on the key, ":string:" --> "string" - json.tryGetMap('emoticons')?.catchMap((k, v) => + json.tryGetMap('emoticons')?.catchMap((k, v) => MapEntry( k.startsWith(':') && k.endsWith(':') ? k.substring(1, k.length - 1) : k, ImagePackImageContent.fromJson( - v as Map))) ?? + v as Map))) ?? // the "short" key was still just a map from shortcode to mxc uri json.tryGetMap('short')?.catchMap((k, v) => MapEntry( @@ -100,7 +100,7 @@ class ImagePackContent { ImagePackImageContent(url: Uri.parse(v)))) ?? {}; - Map toJson() => { + Map toJson() => { ..._json, 'images': images.map((k, v) => MapEntry(k, v.toJson())), 'pack': pack.toJson(), @@ -109,25 +109,25 @@ class ImagePackContent { class ImagePackImageContent { // we want to preserve potential custom keys in this object - final Map _json; + final Map _json; Uri url; String? body; - Map? info; + Map? info; List? usage; ImagePackImageContent({required this.url, this.body, this.info, this.usage}) : _json = {}; - ImagePackImageContent.fromJson(Map json) + ImagePackImageContent.fromJson(Map json) : _json = Map.fromEntries(json.entries .where((e) => !['url', 'body', 'info'].contains(e.key))), url = Uri.parse(json['url'] as String), body = json.tryGet('body'), - info = json.tryGetMap('info'), + info = json.tryGetMap('info'), usage = imagePackUsageFromJson(json.tryGetList('usage')); - Map toJson() { + Map toJson() { return { ...Map.from(_json)..remove('usage'), 'url': url.toString(), @@ -141,7 +141,7 @@ class ImagePackImageContent { class ImagePackPackContent { // we want to preserve potential custom keys in this object - final Map _json; + final Map _json; String? displayName; Uri? avatarUrl; @@ -152,7 +152,7 @@ class ImagePackPackContent { {this.displayName, this.avatarUrl, this.usage, this.attribution}) : _json = {}; - ImagePackPackContent.fromJson(Map json) + ImagePackPackContent.fromJson(Map json) : _json = Map.fromEntries(json.entries.where((e) => !['display_name', 'avatar_url', 'attribution'].contains(e.key))), displayName = json.tryGet('display_name'), @@ -161,7 +161,7 @@ class ImagePackPackContent { usage = imagePackUsageFromJson(json.tryGetList('usage')), attribution = json.tryGet('attribution'); - Map toJson() { + Map toJson() { return { ...Map.from(_json)..remove('usage'), if (displayName != null) 'display_name': displayName, diff --git a/lib/src/model/events/olm_plaintext_payload.dart b/lib/src/model/events/olm_plaintext_payload.dart index fe7e0611..11ec26c7 100644 --- a/lib/src/model/events/olm_plaintext_payload.dart +++ b/lib/src/model/events/olm_plaintext_payload.dart @@ -25,7 +25,7 @@ import '../../utils/try_get_map_extension.dart'; class OlmPlaintextPayload { String? type; - Map? content; + Map? content; String? sender; String? recipient; Map? recipientKeys; @@ -40,7 +40,7 @@ class OlmPlaintextPayload { this.keys, }) : super(); - factory OlmPlaintextPayload.fromJson(Map json) => + factory OlmPlaintextPayload.fromJson(Map json) => OlmPlaintextPayload( sender: json.tryGet('sender', TryGet.required), type: json.tryGet('type', TryGet.required), @@ -50,8 +50,8 @@ class OlmPlaintextPayload { keys: json.tryGetMap('keys', TryGet.required), ); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (type != null) data['type'] = type; if (sender != null) data['sender'] = sender; if (content != null) data['content'] = content; diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/src/model/events/room_encrypted_content.dart index 7d4ef4b0..c92ed261 100644 --- a/lib/src/model/events/room_encrypted_content.dart +++ b/lib/src/model/events/room_encrypted_content.dart @@ -39,7 +39,7 @@ class RoomEncryptedContent { String? ciphertextMegolm; Map? ciphertextOlm; - RoomEncryptedContent.fromJson(Map json) + RoomEncryptedContent.fromJson(Map json) : algorithm = json.tryGet('algorithm', TryGet.required) ?? '', senderKey = json.tryGet('sender_key', TryGet.required) ?? '', deviceId = json.tryGet('device_id'), @@ -47,12 +47,12 @@ class RoomEncryptedContent { ciphertextMegolm = json.tryGet('ciphertext', TryGet.silent), // filter out invalid/incomplete CiphertextInfos ciphertextOlm = json - .tryGet>('ciphertext', TryGet.silent) + .tryGet>('ciphertext', TryGet.silent) ?.catchMap((k, v) => MapEntry( - k, CiphertextInfo.fromJson(v as Map))); + k, CiphertextInfo.fromJson(v as Map))); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['algorithm'] = algorithm; data['sender_key'] = senderKey; if (deviceId != null) { @@ -80,12 +80,12 @@ class CiphertextInfo { String body; int type; - CiphertextInfo.fromJson(Map json) + CiphertextInfo.fromJson(Map json) : body = json['body'] as String, type = json['type'] as int; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['body'] = body; data['type'] = type; return data; diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/src/model/events/room_encryption_content.dart index 24262320..15ed3763 100644 --- a/lib/src/model/events/room_encryption_content.dart +++ b/lib/src/model/events/room_encryption_content.dart @@ -34,13 +34,13 @@ class RoomEncryptionContent { int? rotationPeriodMs; int? rotationPeriodMsgs; - RoomEncryptionContent.fromJson(Map json) + RoomEncryptionContent.fromJson(Map json) : algorithm = json.tryGet('algorithm', TryGet.required) ?? '', rotationPeriodMs = json.tryGet('rotation_period_ms'), rotationPeriodMsgs = json.tryGet('rotation_period_msgs'); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['algorithm'] = algorithm; if (rotationPeriodMs != null) { data['rotation_period_ms'] = rotationPeriodMs; diff --git a/lib/src/model/events/room_key_content.dart b/lib/src/model/events/room_key_content.dart index e8c69893..a710523b 100644 --- a/lib/src/model/events/room_key_content.dart +++ b/lib/src/model/events/room_key_content.dart @@ -40,14 +40,14 @@ class RoomKeyContent { required this.sessionId, required this.sessionKey}); - RoomKeyContent.fromJson(Map json) + RoomKeyContent.fromJson(Map json) : algorithm = json.tryGet('algorithm', TryGet.required) ?? '', roomId = json.tryGet('room_id', TryGet.required) ?? '', sessionId = json.tryGet('session_id', TryGet.required) ?? '', sessionKey = json.tryGet('session_key', TryGet.required) ?? ''; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['algorithm'] = algorithm; data['room_id'] = roomId; data['session_id'] = sessionId; diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/src/model/events/room_key_request_content.dart index bddaeff3..ec6162d4 100644 --- a/lib/src/model/events/room_key_request_content.dart +++ b/lib/src/model/events/room_key_request_content.dart @@ -35,8 +35,8 @@ class RoomKeyRequestContent { String requestingDeviceId; String requestId; - RoomKeyRequestContent.fromJson(Map json) - : body = ((Map? x) => x != null + RoomKeyRequestContent.fromJson(Map json) + : body = ((Map? x) => x != null ? RequestedKeyInfo.fromJson(x) : null)(json.tryGet('body')), action = json.tryGet('action', TryGet.required) ?? '', @@ -44,8 +44,8 @@ class RoomKeyRequestContent { json.tryGet('requesting_device_id', TryGet.required) ?? '', requestId = json.tryGet('request_id', TryGet.required) ?? ''; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (body != null) data['body'] = body!.toJson(); data['action'] = action; data['requesting_device_id'] = requestingDeviceId; @@ -66,14 +66,14 @@ class RequestedKeyInfo { required this.sessionId, required this.senderKey}); - RequestedKeyInfo.fromJson(Map json) + RequestedKeyInfo.fromJson(Map json) : algorithm = json.tryGet('algorithm', TryGet.required) ?? '', roomId = json.tryGet('room_id', TryGet.required) ?? '', sessionId = json.tryGet('session_id', TryGet.required) ?? '', senderKey = json.tryGet('sender_key', TryGet.required) ?? ''; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['algorithm'] = algorithm; data['room_id'] = roomId; data['session_id'] = sessionId; diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/src/model/events/secret_storage_default_key_content.dart index 198f6e7d..7623bcdd 100644 --- a/lib/src/model/events/secret_storage_default_key_content.dart +++ b/lib/src/model/events/secret_storage_default_key_content.dart @@ -35,11 +35,11 @@ class SecretStorageDefaultKeyContent { SecretStorageDefaultKeyContent({required this.key}); - SecretStorageDefaultKeyContent.fromJson(Map json) + SecretStorageDefaultKeyContent.fromJson(Map json) : key = json.tryGet('key', TryGet.required); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (key != null) data['key'] = key; return data; } diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/src/model/events/secret_storage_key_content.dart index 5f3529e3..42019615 100644 --- a/lib/src/model/events/secret_storage_key_content.dart +++ b/lib/src/model/events/secret_storage_key_content.dart @@ -37,16 +37,16 @@ class SecretStorageKeyContent { SecretStorageKeyContent(); - SecretStorageKeyContent.fromJson(Map json) - : passphrase = ((Map? x) => x != null + SecretStorageKeyContent.fromJson(Map json) + : passphrase = ((Map? x) => x != null ? PassphraseInfo.fromJson(x) : null)(json.tryGet('passphrase')), iv = json.tryGet('iv'), mac = json.tryGet('mac'), algorithm = json.tryGet('algorithm'); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (passphrase != null) data['passphrase'] = passphrase!.toJson(); if (iv != null) data['iv'] = iv; if (mac != null) data['mac'] = mac; @@ -69,14 +69,14 @@ class PassphraseInfo { required this.iterations, this.bits}); - PassphraseInfo.fromJson(Map json) + PassphraseInfo.fromJson(Map json) : algorithm = json.tryGet('algorithm', TryGet.required), salt = json.tryGet('salt', TryGet.required), iterations = json.tryGet('iterations', TryGet.required), bits = json.tryGet('bits'); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['algorithm'] = algorithm; data['salt'] = salt; data['iterations'] = iterations; diff --git a/lib/src/model/events/tombstone_content.dart b/lib/src/model/events/tombstone_content.dart index 926db2fc..b3dccbec 100644 --- a/lib/src/model/events/tombstone_content.dart +++ b/lib/src/model/events/tombstone_content.dart @@ -33,13 +33,13 @@ class TombstoneContent { String body; String replacementRoom; - TombstoneContent.fromJson(Map json) + TombstoneContent.fromJson(Map json) : body = json.tryGet('body', TryGet.required) ?? '', replacementRoom = json.tryGet('replacement_room', TryGet.required) ?? ''; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['body'] = body; data['replacement_room'] = replacementRoom; return data; diff --git a/lib/src/model/matrix_event.dart b/lib/src/model/matrix_event.dart index b0ed6ee7..6d3c6cc9 100644 --- a/lib/src/model/matrix_event.dart +++ b/lib/src/model/matrix_event.dart @@ -28,13 +28,13 @@ class MatrixEvent extends StrippedStateEvent { String eventId; String? roomId; DateTime originServerTs; - Map? unsigned; - Map? prevContent; + Map? unsigned; + Map? prevContent; String? redacts; MatrixEvent({ required String type, - required Map content, + required Map content, required String senderId, String? stateKey, required this.eventId, @@ -49,18 +49,18 @@ class MatrixEvent extends StrippedStateEvent { senderId: senderId, stateKey: stateKey); - MatrixEvent.fromJson(Map json) + MatrixEvent.fromJson(Map json) : eventId = json['event_id'] as String, roomId = json['room_id'] as String?, originServerTs = DateTime.fromMillisecondsSinceEpoch( json['origin_server_ts'] as int), - unsigned = (json['unsigned'] as Map?)?.copy(), - prevContent = (json['prev_content'] as Map?)?.copy(), + unsigned = (json['unsigned'] as Map?)?.copy(), + prevContent = (json['prev_content'] as Map?)?.copy(), redacts = json['redacts'] as String?, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['event_id'] = eventId; data['origin_server_ts'] = originServerTs.millisecondsSinceEpoch; diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 0f20c674..811b1e13 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -63,7 +63,7 @@ enum MatrixError { /// Represents a special response from the Homeserver for errors. class MatrixException implements Exception { - final Map raw; + final Map raw; /// The unique identifier for this error. String get errcode => @@ -81,9 +81,9 @@ class MatrixException implements Exception { http.Response? response; MatrixException(http.Response this.response) - : raw = json.decode(response.body) as Map; + : raw = json.decode(response.body) as Map; - MatrixException.fromJson(Map content) : raw = content; + MatrixException.fromJson(Map content) : raw = content; @override String toString() => '$errcode: $errorMessage'; @@ -110,7 +110,7 @@ class MatrixException implements Exception { /// doesn't need additional authentication, then this is null. List? get authenticationFlows => raw .tryGet>('flows') - ?.whereType>() + ?.whereType>() .map((flow) => flow['stages']) .whereType>() .map((stages) => @@ -120,8 +120,8 @@ class MatrixException implements Exception { /// This section contains any information that the client will need to know in order to use a given type /// of authentication. For each authentication type presented, that type may be present as a key in this /// dictionary. For example, the public part of an OAuth client ID could be given here. - Map? get authenticationParams => - raw.tryGetMap('params'); + Map? get authenticationParams => + raw.tryGetMap('params'); /// Returns the list of already completed authentication flows from previous requests. List get completedAuthenticationFlows => diff --git a/lib/src/model/matrix_keys.dart b/lib/src/model/matrix_keys.dart index ca25a197..d6a8fde8 100644 --- a/lib/src/model/matrix_keys.dart +++ b/lib/src/model/matrix_keys.dart @@ -30,25 +30,25 @@ abstract class MatrixSignableKey { Map keys; Map>? signatures; - Map? unsigned; + Map? unsigned; MatrixSignableKey(this.userId, this.keys, this.signatures, {this.unsigned}); // This object is used for signing so we need the raw json too - Map? _json; + Map? _json; - MatrixSignableKey.fromJson(Map json) + MatrixSignableKey.fromJson(Map json) : _json = json, userId = json['user_id'] as String, - keys = Map.from(json['keys'] as Map), + keys = Map.from(json['keys'] as Map), // we need to manually copy to ensure that our map is Map> signatures = (() { - final orig = json.tryGetMap('signatures'); + final orig = json.tryGetMap('signatures'); final res = >{}; for (final entry - in (orig?.entries ?? >[])) { + in (orig?.entries ?? >[])) { final deviceSigs = entry.value; - if (deviceSigs is Map) { + if (deviceSigs is Map) { for (final nestedEntry in deviceSigs.entries) { final nestedValue = nestedEntry.value; if (nestedValue is String) { @@ -60,10 +60,10 @@ abstract class MatrixSignableKey { } return res; }()), - unsigned = json.tryGetMap('unsigned')?.copy(); + unsigned = json.tryGetMap('unsigned')?.copy(); - Map toJson() { - final data = _json ?? {}; + Map toJson() { + final data = _json ?? {}; data['user_id'] = userId; data['keys'] = keys; @@ -87,19 +87,19 @@ class MatrixCrossSigningKey extends MatrixSignableKey { this.usage, Map keys, Map> signatures, { - Map? unsigned, + Map? unsigned, }) : super(userId, keys, signatures, unsigned: unsigned); @override String? get identifier => keys.values.first; @override - MatrixCrossSigningKey.fromJson(Map json) + MatrixCrossSigningKey.fromJson(Map json) : usage = json.tryGetList('usage') ?? [], super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['usage'] = usage; return data; @@ -119,20 +119,20 @@ class MatrixDeviceKeys extends MatrixSignableKey { this.algorithms, Map keys, Map> signatures, { - Map? unsigned, + Map? unsigned, }) : super(userId, keys, signatures, unsigned: unsigned); @override String? get identifier => deviceId; @override - MatrixDeviceKeys.fromJson(Map json) + MatrixDeviceKeys.fromJson(Map json) : algorithms = json.tryGetList('algorithms') ?? [], deviceId = json['device_id'] as String, super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['device_id'] = deviceId; data['algorithms'] = algorithms; diff --git a/lib/src/model/presence.dart b/lib/src/model/presence.dart index 37b33f3d..90e42cc5 100644 --- a/lib/src/model/presence.dart +++ b/lib/src/model/presence.dart @@ -27,8 +27,8 @@ import 'presence_content.dart'; class Presence extends BasicEventWithSender { PresenceContent presence; - Presence.fromJson(Map json) + Presence.fromJson(Map json) : presence = - PresenceContent.fromJson(json['content'] as Map), + PresenceContent.fromJson(json['content'] as Map), super.fromJson(json); } diff --git a/lib/src/model/presence_content.dart b/lib/src/model/presence_content.dart index 8f80851e..25665960 100644 --- a/lib/src/model/presence_content.dart +++ b/lib/src/model/presence_content.dart @@ -29,15 +29,15 @@ class PresenceContent { String? statusMsg; bool? currentlyActive; - PresenceContent.fromJson(Map json) + PresenceContent.fromJson(Map json) : presence = PresenceType.values.firstWhere( (p) => p.toString().split('.').last == json['presence']), lastActiveAgo = json.tryGet('last_active_ago'), statusMsg = json.tryGet('status_msg'), currentlyActive = json.tryGet('currently_active'); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['presence'] = presence.toString().split('.').last; if (lastActiveAgo != null) { data['last_active_ago'] = lastActiveAgo; diff --git a/lib/src/model/room_keys_keys.dart b/lib/src/model/room_keys_keys.dart index ce148bc1..6a3762ef 100644 --- a/lib/src/model/room_keys_keys.dart +++ b/lib/src/model/room_keys_keys.dart @@ -27,7 +27,7 @@ class RoomKeysSingleKey { int firstMessageIndex; int forwardedCount; bool isVerified; - Map sessionData; + Map sessionData; RoomKeysSingleKey( {required this.firstMessageIndex, @@ -35,14 +35,14 @@ class RoomKeysSingleKey { required this.isVerified, required this.sessionData}); - RoomKeysSingleKey.fromJson(Map json) + RoomKeysSingleKey.fromJson(Map json) : firstMessageIndex = json['first_message_index'] as int, forwardedCount = json['forwarded_count'] as int, isVerified = json['is_verified'] as bool, - sessionData = json['session_data'] as Map; + sessionData = json['session_data'] as Map; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['first_message_index'] = firstMessageIndex; data['forwarded_count'] = forwardedCount; data['is_verified'] = isVerified; @@ -56,12 +56,12 @@ class RoomKeysRoom { RoomKeysRoom({required this.sessions}); - RoomKeysRoom.fromJson(Map json) - : sessions = (json['sessions'] as Map).map((k, v) => - MapEntry(k, RoomKeysSingleKey.fromJson(v as Map))); + RoomKeysRoom.fromJson(Map json) + : sessions = (json['sessions'] as Map).map((k, v) => + MapEntry(k, RoomKeysSingleKey.fromJson(v as Map))); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['sessions'] = sessions.map((k, v) => MapEntry(k, v.toJson())); return data; } @@ -71,13 +71,13 @@ class RoomKeysUpdateResponse { String etag; int count; - RoomKeysUpdateResponse.fromJson(Map json) + RoomKeysUpdateResponse.fromJson(Map json) : etag = json.tryGet('etag') ?? '', // synapse replies an int but docs say string? count = json.tryGet('count') ?? 0; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['etag'] = etag; data['count'] = count; return data; diff --git a/lib/src/model/room_summary.dart b/lib/src/model/room_summary.dart index 0f19836d..d0300b89 100644 --- a/lib/src/model/room_summary.dart +++ b/lib/src/model/room_summary.dart @@ -26,15 +26,15 @@ class RoomSummary { int? mJoinedMemberCount; int? mInvitedMemberCount; - RoomSummary.fromJson(Map json) + RoomSummary.fromJson(Map json) : mHeroes = json['m.heroes'] != null ? List.from(json['m.heroes'] as List) : null, mJoinedMemberCount = json['m.joined_member_count'] as int?, mInvitedMemberCount = json['m.invited_member_count'] as int?; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (mHeroes != null) { data['m.heroes'] = mHeroes; } diff --git a/lib/src/model/stripped_state_event.dart b/lib/src/model/stripped_state_event.dart index 9fbabb37..dd78184d 100644 --- a/lib/src/model/stripped_state_event.dart +++ b/lib/src/model/stripped_state_event.dart @@ -28,17 +28,17 @@ class StrippedStateEvent extends BasicEventWithSender { StrippedStateEvent( {required String type, - required Map content, + required Map content, required String senderId, this.stateKey}) : super(type: type, content: content, senderId: senderId); - StrippedStateEvent.fromJson(Map json) + StrippedStateEvent.fromJson(Map json) : stateKey = json.tryGet('state_key'), super.fromJson(json); @override - Map toJson() { + Map toJson() { final data = super.toJson(); data['state_key'] = stateKey; return data; diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index a435894a..176379f0 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -44,27 +44,27 @@ class SyncUpdate { this.deviceUnusedFallbackKeyTypes, }); - SyncUpdate.fromJson(Map json) + SyncUpdate.fromJson(Map json) : nextBatch = json['next_batch'] as String, rooms = (() { - final temp = json.tryGetMap('rooms'); + final temp = json.tryGetMap('rooms'); return temp != null ? RoomsUpdate.fromJson(temp) : null; }()), presence = json .tryGetMap>('presence')?['events'] - ?.map((i) => Presence.fromJson(i as Map)) + ?.map((i) => Presence.fromJson(i as Map)) .toList(), accountData = json .tryGetMap>('account_data')?['events'] - ?.map((i) => BasicEvent.fromJson(i as Map)) + ?.map((i) => BasicEvent.fromJson(i as Map)) .toList(), toDevice = json .tryGetMap>('to_device')?['events'] ?.map( - (i) => BasicEventWithSender.fromJson(i as Map)) + (i) => BasicEventWithSender.fromJson(i as Map)) .toList(), deviceLists = (() { - final temp = json.tryGetMap('device_lists'); + final temp = json.tryGetMap('device_lists'); return temp != null ? DeviceListsUpdate.fromJson(temp) : null; }()), deviceOneTimeKeysCount = @@ -74,8 +74,8 @@ class SyncUpdate { json.tryGetList( 'org.matrix.msc2732.device_unused_fallback_key_types'); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; data['next_batch'] = nextBatch; if (rooms != null) { data['rooms'] = rooms!.toJson(); @@ -121,17 +121,17 @@ class RoomsUpdate { this.leave, }); - RoomsUpdate.fromJson(Map json) { - join = json.tryGetMap('join')?.catchMap((k, v) => - MapEntry(k, JoinedRoomUpdate.fromJson(v as Map))); - invite = json.tryGetMap('invite')?.catchMap((k, v) => - MapEntry(k, InvitedRoomUpdate.fromJson(v as Map))); - leave = json.tryGetMap('leave')?.catchMap((k, v) => - MapEntry(k, LeftRoomUpdate.fromJson(v as Map))); + RoomsUpdate.fromJson(Map json) { + join = json.tryGetMap('join')?.catchMap((k, v) => + MapEntry(k, JoinedRoomUpdate.fromJson(v as Map))); + invite = json.tryGetMap('invite')?.catchMap((k, v) => + MapEntry(k, InvitedRoomUpdate.fromJson(v as Map))); + leave = json.tryGetMap('leave')?.catchMap((k, v) => + MapEntry(k, LeftRoomUpdate.fromJson(v as Map))); } - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (join != null) { data['join'] = join!.map((k, v) => MapEntry(k, v.toJson())); } @@ -164,26 +164,26 @@ class JoinedRoomUpdate extends SyncRoomUpdate { this.unreadNotifications, }); - JoinedRoomUpdate.fromJson(Map json) + JoinedRoomUpdate.fromJson(Map json) : summary = json.tryGetFromJson('summary', RoomSummary.fromJson), state = json .tryGetMap>('state')?['events'] - ?.map((i) => MatrixEvent.fromJson(i as Map)) + ?.map((i) => MatrixEvent.fromJson(i as Map)) .toList(), timeline = json.tryGetFromJson('timeline', TimelineUpdate.fromJson), ephemeral = json .tryGetMap>('ephemeral')?['events'] - ?.map((i) => BasicRoomEvent.fromJson(i as Map)) + ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(), accountData = json .tryGetMap>('account_data')?['events'] - ?.map((i) => BasicRoomEvent.fromJson(i as Map)) + ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(), unreadNotifications = json.tryGetFromJson( 'unread_notifications', UnreadNotificationCounts.fromJson); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (summary != null) { data['summary'] = summary!.toJson(); } @@ -217,14 +217,14 @@ class InvitedRoomUpdate extends SyncRoomUpdate { InvitedRoomUpdate({this.inviteState}); - InvitedRoomUpdate.fromJson(Map json) + InvitedRoomUpdate.fromJson(Map json) : inviteState = json .tryGetMap>('invite_state')?['events'] - ?.map((i) => StrippedStateEvent.fromJson(i as Map)) + ?.map((i) => StrippedStateEvent.fromJson(i as Map)) .toList(); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (inviteState != null) { data['invite_state'] = { 'events': inviteState!.map((i) => i.toJson()).toList(), @@ -245,19 +245,19 @@ class LeftRoomUpdate extends SyncRoomUpdate { this.accountData, }); - LeftRoomUpdate.fromJson(Map json) + LeftRoomUpdate.fromJson(Map json) : state = json .tryGetMap>('state')?['events'] - ?.map((i) => MatrixEvent.fromJson(i as Map)) + ?.map((i) => MatrixEvent.fromJson(i as Map)) .toList(), timeline = json.tryGetFromJson('timeline', TimelineUpdate.fromJson), accountData = json .tryGetMap>('account_data')?['events'] - ?.map((i) => BasicRoomEvent.fromJson(i as Map)) + ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (state != null) { data['state'] = { 'events': state!.map((i) => i.toJson()).toList(), @@ -286,16 +286,16 @@ class TimelineUpdate { this.prevBatch, }); - TimelineUpdate.fromJson(Map json) + TimelineUpdate.fromJson(Map json) : events = json - .tryGetList>('events') + .tryGetList>('events') ?.map((v) => MatrixEvent.fromJson(v)) .toList(), limited = json.tryGet('limited'), prevBatch = json.tryGet('prev_batch'); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (events != null) { data['events'] = events!.map((i) => i.toJson()).toList(); } @@ -318,12 +318,12 @@ class UnreadNotificationCounts { this.highlightCount, }); - UnreadNotificationCounts.fromJson(Map json) + UnreadNotificationCounts.fromJson(Map json) : highlightCount = json.tryGet('highlight_count'), notificationCount = json.tryGet('notification_count'); - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (highlightCount != null) { data['highlight_count'] = highlightCount; } @@ -343,12 +343,12 @@ class DeviceListsUpdate { this.left, }); - DeviceListsUpdate.fromJson(Map json) + DeviceListsUpdate.fromJson(Map json) : changed = json.tryGetList('changed') ?? [], left = json.tryGetList('left') ?? []; - Map toJson() { - final data = {}; + Map toJson() { + final data = {}; if (changed != null) { data['changed'] = changed; } diff --git a/lib/src/utils/map_copy_extension.dart b/lib/src/utils/map_copy_extension.dart index 2cf95989..6ece67d3 100644 --- a/lib/src/utils/map_copy_extension.dart +++ b/lib/src/utils/map_copy_extension.dart @@ -21,9 +21,9 @@ * SOFTWARE. */ -extension MapCopyExtension on Map { +extension MapCopyExtension on Map { dynamic _copyValue(dynamic value) { - if (value is Map) { + if (value is Map) { return value.copy(); } if (value is List) { @@ -33,8 +33,8 @@ extension MapCopyExtension on Map { } /// Deep-copies a given json map - Map copy() { - final copy = Map.from(this); + Map copy() { + final copy = Map.from(this); for (final entry in copy.entries) { copy[entry.key] = _copyValue(entry.value); } diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/src/utils/try_get_map_extension.dart index 02dc2743..5a9cf7a8 100644 --- a/lib/src/utils/try_get_map_extension.dart +++ b/lib/src/utils/try_get_map_extension.dart @@ -59,7 +59,7 @@ class _SilentLog implements TryGet { void call(String key, Type expected, Type actual) {} } -extension TryGetMapExtension on Map { +extension TryGetMapExtension on Map { T? tryGet(String key, [TryGet log = TryGet.optional]) { final Object? value = this[key]; if (value is! T) { @@ -101,9 +101,9 @@ extension TryGetMapExtension on Map { } } - A? tryGetFromJson(String key, A Function(Map) fromJson, + A? tryGetFromJson(String key, A Function(Map) fromJson, [TryGet log = TryGet.optional]) { - final value = tryGetMap(key, log); + final value = tryGetMap(key, log); return value != null ? fromJson(value) : null; } diff --git a/test/event_content_test.dart b/test/event_content_test.dart index b6124ce7..6b769ba0 100644 --- a/test/event_content_test.dart +++ b/test/event_content_test.dart @@ -30,7 +30,7 @@ import 'package:matrix_api_lite/matrix_api_lite.dart'; void main() { group('Event Content tests', () { test('Room Encryption Content', () { - Map? json = { + Map? json = { 'content': { 'algorithm': 'm.megolm.v1.aes-sha2', 'rotation_period_ms': 604800000, @@ -44,12 +44,12 @@ void main() { 'type': 'm.room.encryption', 'unsigned': {'age': 1234} }; - json = jsonDecode(jsonEncode(json)) as Map?; + json = jsonDecode(jsonEncode(json)) as Map?; expect(MatrixEvent.fromJson(json!).parsedRoomEncryptionContent.toJson(), json['content']); }); test('Room Encrypted Content', () { - Map? json = { + Map? json = { 'content': { 'algorithm': 'm.megolm.v1.aes-sha2', 'ciphertext': 'AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...', @@ -64,10 +64,10 @@ void main() { 'type': 'm.room.encrypted', 'unsigned': {'age': 1234} }; - json = jsonDecode(jsonEncode(json)) as Map?; + json = jsonDecode(jsonEncode(json)) as Map?; expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), json['content']); - json = { + json = { 'content': { 'algorithm': 'm.olm.v1.curve25519-aes-sha2', 'ciphertext': { @@ -85,12 +85,12 @@ void main() { 'type': 'm.room.encrypted', 'unsigned': {'age': 1234} }; - json = jsonDecode(jsonEncode(json)) as Map?; + json = jsonDecode(jsonEncode(json)) as Map?; expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), json['content']); }); test('Room Key Content', () { - Map? json = { + Map? json = { 'content': { 'algorithm': 'm.megolm.v1.aes-sha2', 'room_id': '!Cuyf34gef24t:localhost', @@ -99,12 +99,12 @@ void main() { }, 'type': 'm.room_key' }; - json = jsonDecode(jsonEncode(json)) as Map?; + json = jsonDecode(jsonEncode(json)) as Map?; expect(BasicEvent.fromJson(json!).parsedRoomKeyContent.toJson(), json['content']); }); test('Room Key Request Content', () { - Map? json = { + Map? json = { 'content': { 'action': 'request_cancellation', 'request_id': '1495474790150.19', @@ -112,10 +112,10 @@ void main() { }, 'type': 'm.room_key_request' }; - json = jsonDecode(jsonEncode(json)) as Map?; + json = jsonDecode(jsonEncode(json)) as Map?; expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), json['content']); - json = { + json = { 'content': { 'action': 'request', 'body': { @@ -129,12 +129,12 @@ void main() { }, 'type': 'm.room_key_request' }; - json = jsonDecode(jsonEncode(json)) as Map?; + json = jsonDecode(jsonEncode(json)) as Map?; expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), json['content']); }); test('Forwarded Room Key Content', () { - Map? json = { + Map? json = { 'content': { 'algorithm': 'm.megolm.v1.aes-sha2', 'forwarding_curve25519_key_chain': [ @@ -149,14 +149,14 @@ void main() { }, 'type': 'm.forwarded_room_key' }; - json = jsonDecode(jsonEncode(json)) as Map?; + json = jsonDecode(jsonEncode(json)) as Map?; expect(BasicEvent.fromJson(json!).parsedForwardedRoomKeyContent.toJson(), json['content']); }); test('OLM Plaintext Payload', () { - Map? json = { + Map? json = { 'type': '', - 'content': { + 'content': { 'msgtype': 'm.text', 'body': 'Hello world', }, @@ -165,12 +165,12 @@ void main() { 'recipient_keys': {'ed25519': ''}, 'keys': {'ed25519': ''} }; - json = jsonDecode(jsonEncode(json)) as Map?; + json = jsonDecode(jsonEncode(json)) as Map?; expect(OlmPlaintextPayload.fromJson(json!).toJson(), json); }); test('Image Pack Content', () { // basic parse / unparse - var json = { + var json = { 'type': 'some type', 'content': { 'images': { @@ -191,12 +191,12 @@ void main() { 'org.custom': 'blah', }, }; - json = jsonDecode(jsonEncode(json)) as Map; + json = jsonDecode(jsonEncode(json)) as Map; expect(BasicEvent.fromJson(json).parsedImagePackContent.toJson(), json['content']); // emoticons migration - json = { + json = { 'type': 'some type', 'content': { 'emoticons': { @@ -206,7 +206,7 @@ void main() { }, }, }; - json = jsonDecode(jsonEncode(json)) as Map; + json = jsonDecode(jsonEncode(json)) as Map; expect( BasicEvent.fromJson(json) .parsedImagePackContent @@ -216,7 +216,7 @@ void main() { 'url': 'mxc://example.org/beep', }); - json = { + json = { 'type': 'some type', 'content': { 'short': { @@ -224,7 +224,7 @@ void main() { }, }, }; - json = jsonDecode(jsonEncode(json)) as Map; + json = jsonDecode(jsonEncode(json)) as Map; expect( BasicEvent.fromJson(json) .parsedImagePackContent @@ -235,15 +235,15 @@ void main() { }); // invalid url for image - json = { + json = { 'type': 'some type', 'content': { 'images': { - 'emote': {}, + 'emote': {}, }, }, }; - json = jsonDecode(jsonEncode(json)) as Map; + json = jsonDecode(jsonEncode(json)) as Map; expect(BasicEvent.fromJson(json).parsedImagePackContent.images['emote'], null); }); diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart index 188a18ee..d20b61e8 100644 --- a/test/map_copy_extension_test.dart +++ b/test/map_copy_extension_test.dart @@ -28,21 +28,21 @@ import 'package:matrix_api_lite/matrix_api_lite.dart'; void main() { group('Map-copy-extension', () { test('it should work', () { - final original = { + final original = { 'attr': 'fox', - 'child': { + 'child': { 'attr': 'bunny', 'list': [1, 2], }, }; final copy = original.copy(); - (original['child'] as Map)['attr'] = 'raccoon'; - expect((copy['child'] as Map)['attr'], 'bunny'); - ((original['child'] as Map)['list'] as List).add(3); - expect((copy['child'] as Map)['list'], [1, 2]); + (original['child'] as Map)['attr'] = 'raccoon'; + expect((copy['child'] as Map)['attr'], 'bunny'); + ((original['child'] as Map)['list'] as List).add(3); + expect((copy['child'] as Map)['list'], [1, 2]); }); test('should do arrays', () { - final original = { + final original = { 'arr': [ [1, 2], {'beep': 'boop'}, @@ -51,9 +51,9 @@ void main() { final copy = original.copy(); ((original['arr'] as List)[0] as List).add(3); expect((copy['arr'] as List)[0], [1, 2]); - ((original['arr'] as List)[1] as Map)['beep'] = 'blargh'; + ((original['arr'] as List)[1] as Map)['beep'] = 'blargh'; expect( - ((copy['arr'] as List)[1] as Map)['beep'], 'boop'); + ((copy['arr'] as List)[1] as Map)['beep'], 'boop'); }); }); } diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart index 0306ad28..9b6943c0 100644 --- a/test/matrix_api_test.dart +++ b/test/matrix_api_test.dart @@ -28,7 +28,7 @@ import 'package:test/test.dart'; import 'package:matrix_api_lite/fake_matrix_api.dart'; import 'package:matrix_api_lite/matrix_api_lite.dart'; -const emptyRequest = {}; +const emptyRequest = {}; void main() { /// All Tests related to device keys @@ -435,8 +435,8 @@ void main() { 'types': ['type1'], }, 'include_leave': true, - 'state': {}, - 'timeline': {}, + 'state': {}, + 'timeline': {}, }, 'presence': { 'limit': 10, @@ -1082,7 +1082,7 @@ void main() { final devices = await matrixApi.getDevices(); expect( (FakeMatrixApi.api['GET']!['/client/v3/devices']!.call(emptyRequest) - as Map?)?['devices'], + as Map?)?['devices'], devices?.map((i) => i.toJson()).toList()); matrixApi.homeserver = matrixApi.accessToken = null; @@ -1229,7 +1229,7 @@ void main() { final response = await matrixApi.getPushers(); expect( FakeMatrixApi.api['GET']!['/client/v3/pushers']! - .call({}), + .call({}), {'pushers': response?.map((i) => i.toJson()).toList()}, ); @@ -1268,7 +1268,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/notifications?from=1234&limit=10&only=1234']! - .call({}), + .call({}), response.toJson(), ); @@ -1281,7 +1281,7 @@ void main() { final response = await matrixApi.getPushRules(); expect( FakeMatrixApi.api['GET']!['/client/v3/pushrules']! - .call({}), + .call({}), {'global': response.toJson()}, ); @@ -1295,7 +1295,7 @@ void main() { await matrixApi.getPushRule('global', PushRuleKind.content, 'nocake'); expect( FakeMatrixApi.api['GET']!['/client/v3/pushrules/global/content/nocake']! - .call({}), + .call({}), response.toJson(), ); @@ -1396,7 +1396,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/events?from=1234&timeout=10&room_id=%211234']! - .call({}), + .call({}), response.toJson(), ); @@ -1411,7 +1411,7 @@ void main() { expect( FakeMatrixApi.api['GET']![ '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']! - .call({}), + .call({}), {'tags': response?.map((k, v) => MapEntry(k, v.toJson()))}, ); @@ -1636,14 +1636,14 @@ void main() { matrixApi.accessToken = '1234'; final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; - final authData = { + final authData = { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', 'signatures': >{}, }; final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); expect( (FakeMatrixApi.api['POST']!['/client/v3/room_keys/version']! - .call(emptyRequest) as Map)['version'], + .call(emptyRequest) as Map)['version'], ret); }); test('getRoomKeysVersionCurrent', () async { @@ -1661,7 +1661,7 @@ void main() { matrixApi.accessToken = '1234'; final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; - final authData = { + final authData = { 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', 'signatures': >{}, }; diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart index 13e60c51..9f1a51d2 100644 --- a/test/try_get_map_extension_test.dart +++ b/test/try_get_map_extension_test.dart @@ -29,11 +29,11 @@ void main() { group('Try-get-map-extension', () { Logs().level = Level.verbose; test('it should work', () { - final data = { + final data = { 'str': 'foxies', 'int': 42, 'list': [2, 3, 4], - 'map': { + 'map': { 'beep': 'boop', }, }; @@ -41,12 +41,12 @@ void main() { expect(data.tryGet('str'), null); expect(data.tryGet('int'), 42); expect(data.tryGet>('list'), [2, 3, 4]); - expect(data.tryGetMap('map')?.tryGet('beep'), + expect(data.tryGetMap('map')?.tryGet('beep'), 'boop'); expect( - data.tryGetMap('map')?.tryGet('meep'), null); + data.tryGetMap('map')?.tryGet('meep'), null); expect( - data.tryGetMap('pam')?.tryGet('beep'), null); + data.tryGetMap('pam')?.tryGet('beep'), null); }); }); } From 9699b2823eb0f1d5be61e460bf611c95f3506f54 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Mon, 12 Jun 2023 15:42:51 +0200 Subject: [PATCH 159/174] chore: Remove tags for CI test stage --- .gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0997dd7a..93385c28 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,8 +3,6 @@ include: file: "all.yml" test: - tags: - - linux stage: test image: dart script: From 4953784be4f982d1bf9df7f184cf9aca67a9bda0 Mon Sep 17 00:00:00 2001 From: Krille Date: Fri, 9 Jun 2023 09:49:41 +0200 Subject: [PATCH 160/174] docs: Add regenerate code instructions to readme --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c2710d87..51df5698 100644 --- a/README.md +++ b/README.md @@ -23,4 +23,23 @@ void main() async { ## Generated code The files in `lib/src/generated` are generated by [dart_openapi_codegen](https://gitlab.com/famedly/company/frontend/dart_openapi_codegen/) -from [matrix-spec](https://github.com/matrix-org/matrix-spec/). See the README.md in dart_openapi_codegen for more information. +from [matrix-spec](https://github.com/matrix-org/matrix-spec/). + +To regenerate the code, follow these steps: + +1. Clone both repositories next to each other + 1.1 `git clone git@gitlab.com:famedly/company/frontend/dart_openapi_codegen.git` + 1.2 `git clone git@gitlab.com:famedly/company/frontend/libraries/matrix_api_lite.git` +2. Execute the script in the dart_openapi_codegen directory: +```sh +cd dart_openapi_codegen +./scripts/matrix.sh ../matrix_api_lite/lib/src/generated +cd .. +``` +3. Run the build_runner in the matrix_api_lite directory: +```sh +cd matrix_api_lite +dart pub get +dart run build_runner build +``` +4. Check lints and tests and create a merge request \ No newline at end of file From e81898ef7faa589d202a3efe292952ff0dd08db7 Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 13 Jun 2023 07:59:20 +0200 Subject: [PATCH 161/174] refactor: Get rid of dynamic lists --- lib/fake_matrix_api.dart | 4 ++-- lib/src/model/matrix_exception.dart | 4 ++-- lib/src/model/sync_update.dart | 18 +++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 76002f73..76e9da9c 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -44,7 +44,7 @@ T? tryCast(dynamic object) => object is T ? object : null; /// A mock http client for testing purposes. class FakeMatrixApi extends MockClient { - static final calledEndpoints = >{}; + static final calledEndpoints = >{}; static int eventCounter = 0; FakeMatrixApi() @@ -82,7 +82,7 @@ class FakeMatrixApi extends MockClient { // Call API if (!calledEndpoints.containsKey(action)) { - calledEndpoints[action] = []; + calledEndpoints[action] = []; } calledEndpoints[action]!.add(data); if (api.containsKey(method) && api[method]!.containsKey(action)) { diff --git a/lib/src/model/matrix_exception.dart b/lib/src/model/matrix_exception.dart index 811b1e13..1c10b55c 100644 --- a/lib/src/model/matrix_exception.dart +++ b/lib/src/model/matrix_exception.dart @@ -109,10 +109,10 @@ class MatrixException implements Exception { /// to authenticate itself. Each flow comprises a series of stages. If this request /// doesn't need additional authentication, then this is null. List? get authenticationFlows => raw - .tryGet>('flows') + .tryGet>('flows') ?.whereType>() .map((flow) => flow['stages']) - .whereType>() + .whereType>() .map((stages) => AuthenticationFlow(List.from(stages.whereType()))) .toList(); diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index 176379f0..f78fb566 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -51,15 +51,15 @@ class SyncUpdate { return temp != null ? RoomsUpdate.fromJson(temp) : null; }()), presence = json - .tryGetMap>('presence')?['events'] + .tryGetMap>('presence')?['events'] ?.map((i) => Presence.fromJson(i as Map)) .toList(), accountData = json - .tryGetMap>('account_data')?['events'] + .tryGetMap>('account_data')?['events'] ?.map((i) => BasicEvent.fromJson(i as Map)) .toList(), toDevice = json - .tryGetMap>('to_device')?['events'] + .tryGetMap>('to_device')?['events'] ?.map( (i) => BasicEventWithSender.fromJson(i as Map)) .toList(), @@ -167,16 +167,16 @@ class JoinedRoomUpdate extends SyncRoomUpdate { JoinedRoomUpdate.fromJson(Map json) : summary = json.tryGetFromJson('summary', RoomSummary.fromJson), state = json - .tryGetMap>('state')?['events'] + .tryGetMap>('state')?['events'] ?.map((i) => MatrixEvent.fromJson(i as Map)) .toList(), timeline = json.tryGetFromJson('timeline', TimelineUpdate.fromJson), ephemeral = json - .tryGetMap>('ephemeral')?['events'] + .tryGetMap>('ephemeral')?['events'] ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(), accountData = json - .tryGetMap>('account_data')?['events'] + .tryGetMap>('account_data')?['events'] ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(), unreadNotifications = json.tryGetFromJson( @@ -219,7 +219,7 @@ class InvitedRoomUpdate extends SyncRoomUpdate { InvitedRoomUpdate.fromJson(Map json) : inviteState = json - .tryGetMap>('invite_state')?['events'] + .tryGetMap>('invite_state')?['events'] ?.map((i) => StrippedStateEvent.fromJson(i as Map)) .toList(); @@ -247,12 +247,12 @@ class LeftRoomUpdate extends SyncRoomUpdate { LeftRoomUpdate.fromJson(Map json) : state = json - .tryGetMap>('state')?['events'] + .tryGetMap>('state')?['events'] ?.map((i) => MatrixEvent.fromJson(i as Map)) .toList(), timeline = json.tryGetFromJson('timeline', TimelineUpdate.fromJson), accountData = json - .tryGetMap>('account_data')?['events'] + .tryGetMap>('account_data')?['events'] ?.map((i) => BasicRoomEvent.fromJson(i as Map)) .toList(); From e45dbd169d638e2db7a8e8e123f137df9e68c32a Mon Sep 17 00:00:00 2001 From: td Date: Tue, 13 Jun 2023 11:45:27 +0530 Subject: [PATCH 162/174] chore: add qr releated eventTypes --- lib/src/model/event_types.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/src/model/event_types.dart b/lib/src/model/event_types.dart index f0f49edd..700a1882 100644 --- a/lib/src/model/event_types.dart +++ b/lib/src/model/event_types.dart @@ -67,6 +67,7 @@ abstract class EventTypes { static const String RoomKeyRequest = 'm.room_key_request'; static const String KeyVerificationRequest = 'm.key.verification.request'; static const String KeyVerificationStart = 'm.key.verification.start'; + static const String KeyVerificationReady = 'm.key.verification.ready'; static const String KeyVerificationDone = 'm.key.verification.done'; static const String KeyVerificationCancel = 'm.key.verification.cancel'; static const String KeyVerificationAccept = 'm.key.verification.accept'; @@ -74,6 +75,12 @@ abstract class EventTypes { static const String SecretSend = 'm.secret.send'; static const String Dummy = 'm.dummy'; + // QR + static const String QRShow = 'm.qr_code.show.v1'; + static const String QRScan = 'm.qr_code.scan.v1'; + static const String Reciprocate = 'm.reciprocate.v1'; + static const String Sas = 'm.sas.v1'; + // Account data event types static const String CrossSigningSelfSigning = 'm.cross_signing.self_signing'; static const String CrossSigningUserSigning = 'm.cross_signing.user_signing'; From 3dbcc120e5c649042039876414edb3bf709ad2d1 Mon Sep 17 00:00:00 2001 From: td Date: Tue, 13 Jun 2023 11:48:54 +0530 Subject: [PATCH 163/174] chore: bump version to 1.7.0 --- CHANGELOG.md | 16 ++++++++++++++++ pubspec.yaml | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a40bf5ff..99f55d50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## [1.7.0] - 12th Jun 2023 + +Breaking Change: +Refactoring from Map to Map makes some +type casts neccessary + +- chore: add qr releated eventTypes (td) +- refactor: Get rid of dynamic lists (Krille) +- chore: bump version (Malin Errenst) +- docs: Add regenerate code instructions to readme (Krille) +- chore: Remove tags for CI test stage (Malin Errenst) +- refactor: Changed Map to Map (Malin Errenst) +- chore: generated folder from recent dart_openapi_codegen (Malin Errenst) +- chore: sort imports (Nicolas Werner) +- ci: Use the ci template (Nicolas Werner) + ## [1.6.1] - 17th Apr 2023 Fixes a small issue in the last release, where some enhanced enums were not diff --git a/pubspec.yaml b/pubspec.yaml index 594d94c9..91dc4a63 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.6.1 +version: 1.7.0 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From 3bd36aa19f13d24b3e24bbea66936859d38637c0 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Thu, 22 Jun 2023 13:57:53 +0200 Subject: [PATCH 164/174] fix: Fix type cast to fix test in matrix-fhir-dart-sdk --- lib/src/model/sync_update.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/model/sync_update.dart b/lib/src/model/sync_update.dart index f78fb566..806c9c52 100644 --- a/lib/src/model/sync_update.dart +++ b/lib/src/model/sync_update.dart @@ -45,7 +45,7 @@ class SyncUpdate { }); SyncUpdate.fromJson(Map json) - : nextBatch = json['next_batch'] as String, + : nextBatch = json.tryGet('next_batch') ?? '', rooms = (() { final temp = json.tryGetMap('rooms'); return temp != null ? RoomsUpdate.fromJson(temp) : null; From 5d8a82aefa0c745ed7bf2a5cbfe2f2f34fec722d Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Thu, 22 Jun 2023 18:05:04 +0200 Subject: [PATCH 165/174] fix: Fixed fake_matrix_api.dart signedOneTimeKeys upload --- lib/fake_matrix_api.dart | 11 ++++++----- pubspec.yaml | 5 +++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 76e9da9c..006d0862 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -2006,11 +2006,12 @@ class FakeMatrixApi extends MockClient { '/client/v3/keys/upload': (var req) => { 'one_time_key_counts': { 'curve25519': 10, - 'signed_curve25519': tryCast>>( - decodeJson(req))?['one_time_keys'] - ?.keys - .length ?? - 0, + 'signed_curve25519': + tryCast>(decodeJson(req)) + ?.tryGetMap('one_time_keys') + ?.keys + .length ?? + 0, } }, '/client/v3/keys/query': (var req) => { diff --git a/pubspec.yaml b/pubspec.yaml index 91dc4a63..c9fe9212 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,3 +19,8 @@ dev_dependencies: import_sorter: ^4.6.0 lints: ^2.0.0 test: ^1.14.4 + +dependency_overrides: +# uncomment for local development +# matrix: +# path: '../famedlysdk' From 79fe358a49a0c80f6cff9369acf78a1eb53795e3 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Thu, 22 Jun 2023 18:11:59 +0200 Subject: [PATCH 166/174] chore: Bump version --- CHANGELOG.md | 5 +++++ pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99f55d50..b110d938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [1.7.1] - 22nd Jun 2023 + +- fix: Fixed fake_matrix_api.dart signedOneTimeKeys upload (Malin Errenst) +- fix: Fix type cast to fix test in matrix-fhir-dart-sdk (Malin Errenst) + ## [1.7.0] - 12th Jun 2023 Breaking Change: diff --git a/pubspec.yaml b/pubspec.yaml index c9fe9212..7db559bf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.7.0 +version: 1.7.1 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From aa07a0e77739a262781f045ee0790510219c728b Mon Sep 17 00:00:00 2001 From: Niklas Zender <33399346+nikzen@users.noreply.github.com> Date: Sat, 8 Jul 2023 16:12:56 +0200 Subject: [PATCH 167/174] chore: add github action --- .github/workflows/main.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..92a7abd1 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,18 @@ +name: Add issues to Product Management Project. + +on: + issues: + types: + - opened + +jobs: + add-to-project: + name: Add issue to project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v0.5.0 + with: + # You can target a repository in a different organization + # to the issue + project-url: https://github.com/orgs/famedly/projects/4 + github-token: ${{ secrets.ADD_ISSUE_TO_PROJECT_PAT }} From fd584ff28e54f993a5a8758dc5317d4ade5f3f13 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 20 Sep 2023 19:42:45 +0200 Subject: [PATCH 168/174] chore: make dependencies compatible with dart 3 --- pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 7db559bf..f49f66a7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,11 +6,11 @@ repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lit issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues environment: - sdk: ">=2.17.0 <3.0.0" + sdk: ">=2.17.0 <4.0.0" dependencies: enhanced_enum: ^0.2.4 - http: ^0.13.0 + http: ">=0.13.0 <2.0.0" mime: ^1.0.0 dev_dependencies: @@ -19,7 +19,7 @@ dev_dependencies: import_sorter: ^4.6.0 lints: ^2.0.0 test: ^1.14.4 - + dependency_overrides: # uncomment for local development # matrix: From 8541d4d67866a3c6297bcc91f19c1a4549333aa4 Mon Sep 17 00:00:00 2001 From: Malin Errenst Date: Fri, 22 Sep 2023 14:06:09 +0200 Subject: [PATCH 169/174] chore: Add adjusted issue templates from product-management --- .github/ISSUE_TEMPLATE/bug-report.yml | 71 ++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 1 + .github/ISSUE_TEMPLATE/epic.yml | 32 ++++++++++++ .github/ISSUE_TEMPLATE/feature.yml | 47 +++++++++++++++++ .github/ISSUE_TEMPLATE/improvement.yml | 47 +++++++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/epic.yml create mode 100644 .github/ISSUE_TEMPLATE/feature.yml create mode 100644 .github/ISSUE_TEMPLATE/improvement.yml diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 00000000..f029de76 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,71 @@ +name: 🐛 Bug Report +description: Report a bug to the product team +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! This will help us to improve the product :) + - type: checkboxes + attributes: + label: Checklist + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I could not find a solution in the documentation, the existing issues or discussions. + required: true + - label: I already asked for help in the chat + - type: dropdown + attributes: + label: In which Project did the bug appear? + multiple: true + options: + - Famedly App + - Pharmacy Portal + - Flutter Admin Interface + - Other + - type: input + attributes: + label: If you selected \"Other\" as Project, please enter in which project the bug occurred. + - type: dropdown + attributes: + label: On which platform did the bug appear? + multiple: true + options: + - Android + - iOS + - Chrome + - Safari + - Firefox + - Edge + validations: + required: true + - type: input + attributes: + label: Matrix API Version + description: Which version of the Matrix Api (this Repo) are you using? + - type: textarea + attributes: + label: Describe the problem caused by this bug + description: | + A clear and concise description of the problem you have and what the bug is. + validations: + required: true + - type: textarea + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. In this step... + 1. With this device... + 1. Run '...' + 1. See error... + validations: + required: false + - type: textarea + attributes: + label: Screenshots or Logs + description: If applicable, add screenshots or Logs to help explain your problem. + - type: textarea + attributes: + label: Security related + description: If there is something related to security, please add it here diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..3ba13e0c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/epic.yml b/.github/ISSUE_TEMPLATE/epic.yml new file mode 100644 index 00000000..83de96b5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/epic.yml @@ -0,0 +1,32 @@ +name: 🥸 [Product only] Create epic +description: "Creates a new epic which is used to build the Famedly Roadmap" +labels: ["epic"] +body: + - type: markdown + attributes: + value: | + This should be filled out by product. + - type: textarea + id: summary + attributes: + label: summary + description: Please write a summary + validations: + required: true + - type: textarea + id: intended-outcome + attributes: + label: Intended Outcome + description: What is the outcome for the user? + validations: + required: true + - type: textarea + id: technical-solution + attributes: + label: How will it work? + description: Please write down, how it will work + - type: textarea + id: additional + attributes: + label: Additional Context + description: Please add any other infos that could be useful. diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 00000000..51f47a89 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,47 @@ +name: 🛠️ Feature +description: "Create an new issue for a new Feature in Famedly" +labels: ["feature"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this feature request + - type: checkboxes + id: preflight + attributes: + label: Preflight Checklist + options: + - label: + I could not find a solution in the existing issues, docs, nor discussions + required: true + - type: textarea + id: problem + attributes: + label: Describe your problem + description: Please describe your problem this new feature is supposed to solve. + placeholder: Describe the problem you have + validations: + required: true + - type: textarea + id: solution + attributes: + label: Describe your ideal solution + description: Which solution do you propose? + placeholder: As a [type of user], I want [some goal] so that [some reason]. + validations: + required: true + - type: input + id: version + attributes: + label: Version + description: Which version of the Famedly are you using. + - type: textarea + id: security + attributes: + label: Security requirements + description: Plese add more information in terms of security requirements. + - type: textarea + id: additional + attributes: + label: Additional Context + description: Please add any other infos that could be useful. diff --git a/.github/ISSUE_TEMPLATE/improvement.yml b/.github/ISSUE_TEMPLATE/improvement.yml new file mode 100644 index 00000000..a9964478 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/improvement.yml @@ -0,0 +1,47 @@ +name: 🛠️ Improvement +description: "Create an new issue for an improvment in Famedly" +labels: ["improvement"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this improvement request + - type: checkboxes + id: preflight + attributes: + label: Preflight Checklist + options: + - label: + I could not find a solution in the existing issues, docs, nor discussions + required: true + - type: textarea + id: problem + attributes: + label: Describe your problem + description: Please describe your problem this improvement is supposed to solve. + placeholder: Describe the problem you have + validations: + required: true + - type: textarea + id: solution + attributes: + label: Describe your ideal solution + description: Which solution do you propose? + placeholder: As a [type of user], I want [some goal] so that [some reason]. + validations: + required: true + - type: input + id: version + attributes: + label: Version + description: Which version of the Famedly are you using. + - type: textarea + id: security + attributes: + label: Security requirements + description: Plese add more information in terms of security requirements. + - type: textarea + id: additional + attributes: + label: Additional Context + description: Please add any other infos that could be useful. From 281e67086757af44f6ab42606943519b79ad263c Mon Sep 17 00:00:00 2001 From: td Date: Wed, 4 Oct 2023 15:38:39 +0530 Subject: [PATCH 170/174] chore: add general and publish ci --- .github/workflows/general.yml | 25 +++++++++++++++++++ .../workflows/{main.yml => issue-triage.yml} | 0 .github/workflows/publish.yml | 13 ++++++++++ .github/workflows/versions.env | 2 ++ 4 files changed, 40 insertions(+) create mode 100644 .github/workflows/general.yml rename .github/workflows/{main.yml => issue-triage.yml} (100%) create mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/versions.env diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml new file mode 100644 index 00000000..284e4236 --- /dev/null +++ b/.github/workflows/general.yml @@ -0,0 +1,25 @@ +name: General CI + +on: + push: + branches: + - main + pull_request: + merge_group: + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + dart: + permissions: + contents: read + uses: famedly/frontend-ci-templates/.github/workflows/dart.yml@main + with: + env_file: ".github/workflows/versions.env" + + general: + permissions: + contents: read + uses: famedly/frontend-ci-templates/.github/workflows/general.yml@main diff --git a/.github/workflows/main.yml b/.github/workflows/issue-triage.yml similarity index 100% rename from .github/workflows/main.yml rename to .github/workflows/issue-triage.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..d0401d8f --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,13 @@ +name: Publish CI + +on: + push: + tags: + - v[0-9]+.[0-9]+.[0-9]+ + +jobs: + publish: + permissions: + contents: read + id-token: write + uses: famedly/frontend-ci-templates/.github/workflows/publish-pub.yml@main diff --git a/.github/workflows/versions.env b/.github/workflows/versions.env new file mode 100644 index 00000000..66280f74 --- /dev/null +++ b/.github/workflows/versions.env @@ -0,0 +1,2 @@ +flutter_version=3.13.6 +dart_version=3.1.3 From d1d023d45b5bcabc86301df147bf5b51d38f5e9b Mon Sep 17 00:00:00 2001 From: td Date: Wed, 4 Oct 2023 15:55:01 +0530 Subject: [PATCH 171/174] chore: release v1.7.2 --- CHANGELOG.md | 7 +++++++ pubspec.yaml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b110d938..44844476 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.7.2] - 4th Oct 2023 + +- chore: add general and publish ci (td) +- chore: Add adjusted issue templates from product-management (Malin Errenst) +- chore: make dependencies compatible with dart 3 (Nicolas Werner) +- chore: add github action (Niklas Zender) + ## [1.7.1] - 22nd Jun 2023 - fix: Fixed fake_matrix_api.dart signedOneTimeKeys upload (Malin Errenst) diff --git a/pubspec.yaml b/pubspec.yaml index f49f66a7..a584bcdd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.7.1 +version: 1.7.2 homepage: https://famedly.com repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues From c57c75bc1a449120f8a4aceb4365da59cdb4c030 Mon Sep 17 00:00:00 2001 From: Mohammad Reza Moradi Date: Wed, 27 Dec 2023 12:17:32 +0100 Subject: [PATCH 172/174] chore: update readme and pubspec --- README.md | 8 ++++---- pubspec.yaml | 12 +++++------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 51df5698..59a53710 100644 --- a/README.md +++ b/README.md @@ -28,17 +28,17 @@ from [matrix-spec](https://github.com/matrix-org/matrix-spec/). To regenerate the code, follow these steps: 1. Clone both repositories next to each other - 1.1 `git clone git@gitlab.com:famedly/company/frontend/dart_openapi_codegen.git` - 1.2 `git clone git@gitlab.com:famedly/company/frontend/libraries/matrix_api_lite.git` + 1.1 `git clone git@github.com:famedly/dart_openapi_codegen.git` + 1.2 `git clone git@github.com:famedly/dart_matrix_api_lite.git` 2. Execute the script in the dart_openapi_codegen directory: ```sh cd dart_openapi_codegen -./scripts/matrix.sh ../matrix_api_lite/lib/src/generated +./scripts/matrix.sh ../dart_matrix_api_lite/lib/src/generated cd .. ``` 3. Run the build_runner in the matrix_api_lite directory: ```sh -cd matrix_api_lite +cd dart_matrix_api_lite dart pub get dart run build_runner build ``` diff --git a/pubspec.yaml b/pubspec.yaml index a584bcdd..9d51305f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,8 +2,8 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. version: 1.7.2 homepage: https://famedly.com -repository: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/ -issues: https://gitlab.com/famedly/company/frontend/libraries/matrix_api_lite/-/issues +repository: https://github.com/famedly/dart_matrix_api_lite +issues: https://github.com/famedly/dart_matrix_api_lite/issues environment: sdk: ">=2.17.0 <4.0.0" @@ -19,8 +19,6 @@ dev_dependencies: import_sorter: ^4.6.0 lints: ^2.0.0 test: ^1.14.4 - -dependency_overrides: -# uncomment for local development -# matrix: -# path: '../famedlysdk' +# dependency_overrides: # uncomment for local development +# matrix: +# path: "../matrix-dart-sdk" From 67aebfaf4dd2a69737ea1959949a07b1cefdd045 Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 9 Jan 2024 12:44:21 +0100 Subject: [PATCH 173/174] build: Update changelog and readme for 1.7.3 --- CHANGELOG.md | 3 +++ README.md | 4 ++++ pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44844476..11dfec70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [1.7.3] - 9th Jan 2023 +Mark package as discontinued. + ## [1.7.2] - 4th Oct 2023 - chore: add general and publish ci (td) diff --git a/README.md b/README.md index 59a53710..3fa7bdb8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +# Deprecation Notice: + +This package will soon be merged with the [Matrix Dart SDK](https://pub.dev/packages/matrix) and from there be available as a library, not a stand alone package anymore. We hope that this will save us some overhead when maintaining the code. If you rely on this package as stand alone and importing the whole Matrix Dart SDK just to use this library is not an option for you, please open an issue here: https://github.com/famedly/dart_matrix_api_lite/issues + # Matrix API Lite This package is a dead simple data model over the client-server specification of https://matrix.org and is mostly used as a base for a more complete Matrix SDK. diff --git a/pubspec.yaml b/pubspec.yaml index 9d51305f..6f80e07b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: matrix_api_lite description: Dead simple data model for the matrix.org client-server API. -version: 1.7.2 +version: 1.7.3 homepage: https://famedly.com repository: https://github.com/famedly/dart_matrix_api_lite issues: https://github.com/famedly/dart_matrix_api_lite/issues From b7befd781e95694108a6317a58c60ffb7a7a5af4 Mon Sep 17 00:00:00 2001 From: td Date: Fri, 22 Mar 2024 21:24:21 +0530 Subject: [PATCH 174/174] chore: git mv --- .github/ISSUE_TEMPLATE/bug-report.yml | 71 - .github/ISSUE_TEMPLATE/config.yml | 1 - .github/ISSUE_TEMPLATE/epic.yml | 32 - .github/ISSUE_TEMPLATE/feature.yml | 47 - .github/ISSUE_TEMPLATE/improvement.yml | 47 - .github/workflows/general.yml | 25 - .github/workflows/issue-triage.yml | 18 - .github/workflows/publish.yml | 13 - .github/workflows/versions.env | 2 - .gitignore | 80 - .gitlab-ci.yml | 38 - CHANGELOG.md | 242 --- CONTRIBUTING.md | 37 - LICENSE | 21 - README.md | 49 - analysis_options.yaml | 21 - example/matrix_api_lite_example.dart | 8 - .../generated/api.dart | 0 .../generated/fixed_model.dart | 0 .../generated/internal.dart | 0 .../generated/model.dart | 0 .../generated/model.g.dart | 0 lib/{src => matrix_api_lite}/matrix_api.dart | 0 .../model/algorithm_types.dart | 0 .../model/auth/authentication_data.dart | 0 .../model/auth/authentication_identifier.dart | 0 .../model/auth/authentication_password.dart | 0 .../auth/authentication_phone_identifier.dart | 0 .../model/auth/authentication_recaptcha.dart | 0 ...authentication_third_party_identifier.dart | 0 .../auth/authentication_three_pid_creds.dart | 0 .../model/auth/authentication_token.dart | 0 .../model/auth/authentication_types.dart | 0 .../auth/authentication_user_identifier.dart | 0 .../model/basic_event.dart | 0 .../model/basic_event_with_sender.dart | 0 .../model/basic_room_event.dart | 0 .../model/children_state.dart | 0 .../model/event_types.dart | 0 .../events/forwarded_room_key_content.dart | 0 .../model/events/image_pack_content.dart | 0 .../model/events/olm_plaintext_payload.dart | 0 .../model/events/room_encrypted_content.dart | 0 .../model/events/room_encryption_content.dart | 0 .../model/events/room_key_content.dart | 0 .../events/room_key_request_content.dart | 0 .../secret_storage_default_key_content.dart | 0 .../events/secret_storage_key_content.dart | 0 .../model/events/tombstone_content.dart | 0 .../model/matrix_connection_exception.dart | 0 .../model/matrix_event.dart | 0 .../model/matrix_exception.dart | 0 .../model/matrix_keys.dart | 0 .../model/message_types.dart | 0 .../model/presence.dart | 0 .../model/presence_content.dart | 0 .../model/room_creation_types.dart | 0 .../model/room_keys_keys.dart | 0 .../model/room_summary.dart | 0 .../model/room_types.dart | 0 .../model/stripped_state_event.dart | 0 .../model/sync_update.dart | 0 .../utils/filter_map_extension.dart | 0 lib/{src => matrix_api_lite}/utils/logs.dart | 0 .../utils/map_copy_extension.dart | 0 .../utils/print_logs_native.dart | 0 .../utils/print_logs_web.dart | 0 .../utils/try_get_map_extension.dart | 0 lib/{src => matrix_api_lite}/values.dart | 0 pubspec.yaml | 24 - test/event_content_test.dart | 251 --- test/map_copy_extension_test.dart | 59 - test/matrix_api_test.dart | 1934 ----------------- test/try_get_map_extension_test.dart | 52 - 74 files changed, 3072 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml delete mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/epic.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature.yml delete mode 100644 .github/ISSUE_TEMPLATE/improvement.yml delete mode 100644 .github/workflows/general.yml delete mode 100644 .github/workflows/issue-triage.yml delete mode 100644 .github/workflows/publish.yml delete mode 100644 .github/workflows/versions.env delete mode 100644 .gitignore delete mode 100644 .gitlab-ci.yml delete mode 100644 CHANGELOG.md delete mode 100644 CONTRIBUTING.md delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 analysis_options.yaml delete mode 100644 example/matrix_api_lite_example.dart rename lib/{src => matrix_api_lite}/generated/api.dart (100%) rename lib/{src => matrix_api_lite}/generated/fixed_model.dart (100%) rename lib/{src => matrix_api_lite}/generated/internal.dart (100%) rename lib/{src => matrix_api_lite}/generated/model.dart (100%) rename lib/{src => matrix_api_lite}/generated/model.g.dart (100%) rename lib/{src => matrix_api_lite}/matrix_api.dart (100%) rename lib/{src => matrix_api_lite}/model/algorithm_types.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_data.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_identifier.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_password.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_phone_identifier.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_recaptcha.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_third_party_identifier.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_three_pid_creds.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_token.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_types.dart (100%) rename lib/{src => matrix_api_lite}/model/auth/authentication_user_identifier.dart (100%) rename lib/{src => matrix_api_lite}/model/basic_event.dart (100%) rename lib/{src => matrix_api_lite}/model/basic_event_with_sender.dart (100%) rename lib/{src => matrix_api_lite}/model/basic_room_event.dart (100%) rename lib/{src => matrix_api_lite}/model/children_state.dart (100%) rename lib/{src => matrix_api_lite}/model/event_types.dart (100%) rename lib/{src => matrix_api_lite}/model/events/forwarded_room_key_content.dart (100%) rename lib/{src => matrix_api_lite}/model/events/image_pack_content.dart (100%) rename lib/{src => matrix_api_lite}/model/events/olm_plaintext_payload.dart (100%) rename lib/{src => matrix_api_lite}/model/events/room_encrypted_content.dart (100%) rename lib/{src => matrix_api_lite}/model/events/room_encryption_content.dart (100%) rename lib/{src => matrix_api_lite}/model/events/room_key_content.dart (100%) rename lib/{src => matrix_api_lite}/model/events/room_key_request_content.dart (100%) rename lib/{src => matrix_api_lite}/model/events/secret_storage_default_key_content.dart (100%) rename lib/{src => matrix_api_lite}/model/events/secret_storage_key_content.dart (100%) rename lib/{src => matrix_api_lite}/model/events/tombstone_content.dart (100%) rename lib/{src => matrix_api_lite}/model/matrix_connection_exception.dart (100%) rename lib/{src => matrix_api_lite}/model/matrix_event.dart (100%) rename lib/{src => matrix_api_lite}/model/matrix_exception.dart (100%) rename lib/{src => matrix_api_lite}/model/matrix_keys.dart (100%) rename lib/{src => matrix_api_lite}/model/message_types.dart (100%) rename lib/{src => matrix_api_lite}/model/presence.dart (100%) rename lib/{src => matrix_api_lite}/model/presence_content.dart (100%) rename lib/{src => matrix_api_lite}/model/room_creation_types.dart (100%) rename lib/{src => matrix_api_lite}/model/room_keys_keys.dart (100%) rename lib/{src => matrix_api_lite}/model/room_summary.dart (100%) rename lib/{src => matrix_api_lite}/model/room_types.dart (100%) rename lib/{src => matrix_api_lite}/model/stripped_state_event.dart (100%) rename lib/{src => matrix_api_lite}/model/sync_update.dart (100%) rename lib/{src => matrix_api_lite}/utils/filter_map_extension.dart (100%) rename lib/{src => matrix_api_lite}/utils/logs.dart (100%) rename lib/{src => matrix_api_lite}/utils/map_copy_extension.dart (100%) rename lib/{src => matrix_api_lite}/utils/print_logs_native.dart (100%) rename lib/{src => matrix_api_lite}/utils/print_logs_web.dart (100%) rename lib/{src => matrix_api_lite}/utils/try_get_map_extension.dart (100%) rename lib/{src => matrix_api_lite}/values.dart (100%) delete mode 100644 pubspec.yaml delete mode 100644 test/event_content_test.dart delete mode 100644 test/map_copy_extension_test.dart delete mode 100644 test/matrix_api_test.dart delete mode 100644 test/try_get_map_extension_test.dart diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml deleted file mode 100644 index f029de76..00000000 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: 🐛 Bug Report -description: Report a bug to the product team -labels: ["bug"] -body: - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this bug report! This will help us to improve the product :) - - type: checkboxes - attributes: - label: Checklist - description: Please search to see if an issue already exists for the bug you encountered. - options: - - label: I could not find a solution in the documentation, the existing issues or discussions. - required: true - - label: I already asked for help in the chat - - type: dropdown - attributes: - label: In which Project did the bug appear? - multiple: true - options: - - Famedly App - - Pharmacy Portal - - Flutter Admin Interface - - Other - - type: input - attributes: - label: If you selected \"Other\" as Project, please enter in which project the bug occurred. - - type: dropdown - attributes: - label: On which platform did the bug appear? - multiple: true - options: - - Android - - iOS - - Chrome - - Safari - - Firefox - - Edge - validations: - required: true - - type: input - attributes: - label: Matrix API Version - description: Which version of the Matrix Api (this Repo) are you using? - - type: textarea - attributes: - label: Describe the problem caused by this bug - description: | - A clear and concise description of the problem you have and what the bug is. - validations: - required: true - - type: textarea - attributes: - label: Steps To Reproduce - description: Steps to reproduce the behavior. - placeholder: | - 1. In this step... - 1. With this device... - 1. Run '...' - 1. See error... - validations: - required: false - - type: textarea - attributes: - label: Screenshots or Logs - description: If applicable, add screenshots or Logs to help explain your problem. - - type: textarea - attributes: - label: Security related - description: If there is something related to security, please add it here diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 3ba13e0c..00000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1 +0,0 @@ -blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/epic.yml b/.github/ISSUE_TEMPLATE/epic.yml deleted file mode 100644 index 83de96b5..00000000 --- a/.github/ISSUE_TEMPLATE/epic.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: 🥸 [Product only] Create epic -description: "Creates a new epic which is used to build the Famedly Roadmap" -labels: ["epic"] -body: - - type: markdown - attributes: - value: | - This should be filled out by product. - - type: textarea - id: summary - attributes: - label: summary - description: Please write a summary - validations: - required: true - - type: textarea - id: intended-outcome - attributes: - label: Intended Outcome - description: What is the outcome for the user? - validations: - required: true - - type: textarea - id: technical-solution - attributes: - label: How will it work? - description: Please write down, how it will work - - type: textarea - id: additional - attributes: - label: Additional Context - description: Please add any other infos that could be useful. diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml deleted file mode 100644 index 51f47a89..00000000 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: 🛠️ Feature -description: "Create an new issue for a new Feature in Famedly" -labels: ["feature"] -body: - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this feature request - - type: checkboxes - id: preflight - attributes: - label: Preflight Checklist - options: - - label: - I could not find a solution in the existing issues, docs, nor discussions - required: true - - type: textarea - id: problem - attributes: - label: Describe your problem - description: Please describe your problem this new feature is supposed to solve. - placeholder: Describe the problem you have - validations: - required: true - - type: textarea - id: solution - attributes: - label: Describe your ideal solution - description: Which solution do you propose? - placeholder: As a [type of user], I want [some goal] so that [some reason]. - validations: - required: true - - type: input - id: version - attributes: - label: Version - description: Which version of the Famedly are you using. - - type: textarea - id: security - attributes: - label: Security requirements - description: Plese add more information in terms of security requirements. - - type: textarea - id: additional - attributes: - label: Additional Context - description: Please add any other infos that could be useful. diff --git a/.github/ISSUE_TEMPLATE/improvement.yml b/.github/ISSUE_TEMPLATE/improvement.yml deleted file mode 100644 index a9964478..00000000 --- a/.github/ISSUE_TEMPLATE/improvement.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: 🛠️ Improvement -description: "Create an new issue for an improvment in Famedly" -labels: ["improvement"] -body: - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this improvement request - - type: checkboxes - id: preflight - attributes: - label: Preflight Checklist - options: - - label: - I could not find a solution in the existing issues, docs, nor discussions - required: true - - type: textarea - id: problem - attributes: - label: Describe your problem - description: Please describe your problem this improvement is supposed to solve. - placeholder: Describe the problem you have - validations: - required: true - - type: textarea - id: solution - attributes: - label: Describe your ideal solution - description: Which solution do you propose? - placeholder: As a [type of user], I want [some goal] so that [some reason]. - validations: - required: true - - type: input - id: version - attributes: - label: Version - description: Which version of the Famedly are you using. - - type: textarea - id: security - attributes: - label: Security requirements - description: Plese add more information in terms of security requirements. - - type: textarea - id: additional - attributes: - label: Additional Context - description: Please add any other infos that could be useful. diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml deleted file mode 100644 index 284e4236..00000000 --- a/.github/workflows/general.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: General CI - -on: - push: - branches: - - main - pull_request: - merge_group: - -concurrency: - group: ${{ github.ref }} - cancel-in-progress: true - -jobs: - dart: - permissions: - contents: read - uses: famedly/frontend-ci-templates/.github/workflows/dart.yml@main - with: - env_file: ".github/workflows/versions.env" - - general: - permissions: - contents: read - uses: famedly/frontend-ci-templates/.github/workflows/general.yml@main diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml deleted file mode 100644 index 92a7abd1..00000000 --- a/.github/workflows/issue-triage.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Add issues to Product Management Project. - -on: - issues: - types: - - opened - -jobs: - add-to-project: - name: Add issue to project - runs-on: ubuntu-latest - steps: - - uses: actions/add-to-project@v0.5.0 - with: - # You can target a repository in a different organization - # to the issue - project-url: https://github.com/orgs/famedly/projects/4 - github-token: ${{ secrets.ADD_ISSUE_TO_PROJECT_PAT }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index d0401d8f..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Publish CI - -on: - push: - tags: - - v[0-9]+.[0-9]+.[0-9]+ - -jobs: - publish: - permissions: - contents: read - id-token: write - uses: famedly/frontend-ci-templates/.github/workflows/publish-pub.yml@main diff --git a/.github/workflows/versions.env b/.github/workflows/versions.env deleted file mode 100644 index 66280f74..00000000 --- a/.github/workflows/versions.env +++ /dev/null @@ -1,2 +0,0 @@ -flutter_version=3.13.6 -dart_version=3.1.3 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 40dcabc2..00000000 --- a/.gitignore +++ /dev/null @@ -1,80 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.sw* -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -native/ -test/.test_coverage.dart -coverage/ -coverage_badge.svg - -# codegen related -*.bak -*.bakmacoscompat - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# Visual Studio Code related -.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -build/ -pubspec.lock - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 93385c28..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,38 +0,0 @@ -include: - project: "famedly/company/frontend/ci-templates" - file: "all.yml" - -test: - stage: test - image: dart - script: - - dart pub get - - dart pub run test - -dry-run: - stage: deploy - image: dart - script: - - rm -rf ./docs - - dart pub get - - dart pub publish --dry-run - -pub-dev: - stage: deploy - image: dart - dependencies: [dry-run] - script: - - rm -rf ./docs - - | - if [ -z "${PUB_DEV_CREDENTIALS}" ]; then - echo "Missing PUB_DEV_CREDENTIALS environment variable" - exit 1 - fi - - mkdir -p ~/.config/dart/ - cp "${PUB_DEV_CREDENTIALS}" ~/.config/dart/pub-credentials.json - - - dart pub get - - dart pub publish --force - rules: - - if: $CI_COMMIT_TAG diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 11dfec70..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,242 +0,0 @@ -## [1.7.3] - 9th Jan 2023 -Mark package as discontinued. - -## [1.7.2] - 4th Oct 2023 - -- chore: add general and publish ci (td) -- chore: Add adjusted issue templates from product-management (Malin Errenst) -- chore: make dependencies compatible with dart 3 (Nicolas Werner) -- chore: add github action (Niklas Zender) - -## [1.7.1] - 22nd Jun 2023 - -- fix: Fixed fake_matrix_api.dart signedOneTimeKeys upload (Malin Errenst) -- fix: Fix type cast to fix test in matrix-fhir-dart-sdk (Malin Errenst) - -## [1.7.0] - 12th Jun 2023 - -Breaking Change: -Refactoring from Map to Map makes some -type casts neccessary - -- chore: add qr releated eventTypes (td) -- refactor: Get rid of dynamic lists (Krille) -- chore: bump version (Malin Errenst) -- docs: Add regenerate code instructions to readme (Krille) -- chore: Remove tags for CI test stage (Malin Errenst) -- refactor: Changed Map to Map (Malin Errenst) -- chore: generated folder from recent dart_openapi_codegen (Malin Errenst) -- chore: sort imports (Nicolas Werner) -- ci: Use the ci template (Nicolas Werner) - -## [1.6.1] - 17th Apr 2023 - -Fixes a small issue in the last release, where some enhanced enums were not -updated and as such missing a few members. - -- fix: Update the generated enum files - -## [1.6.0] - 17th Apr 2023 - -This release updates to version 1.6 of the Matrix specification. Users might -need to update their read receipt calls to the API changes. - -- feat: Upgrade to spec 1.6 - -## [1.1.10] - 27th Jan 2023 - -- chore: Update enhanced_enum to 0.2.4 - -## [1.1.9] - 7th Nov 2022 - -- feat: Allow converting of stacktraces in logs - -## [1.1.8] - 29th Aug 2022 - -- fix: Edge case where MatrixException.error differs from errcode -- chore: add pushrules to the event types - -## [1.1.7] - 29th Aug 2022 - -- fix: Parsing of MatrixException parameters - -## [1.1.6] - 26th Aug 2022 - -- fix: Fixed missing .pub-cache folder creation in .gitlab-ci.yml - -## [1.1.5] - 25th Aug 2022 - -- fix: Fixed dysfunctional key-verification (Emoji+manual) - -## [1.1.4] - 25th Aug 2022 - -- Revert "fix: Secret storage keys are used as account data but are not uri encoded" -- chore: disable dynamic calls (Nicolas Werner) -- chore: export filter map extension (Nicolas Werner) -- chore: strict casts (Nicolas Werner) -- chore: strict inference (Nicolas Werner) -- chore: strict raw types (Nicolas Werner) -- chore: upgrade from pedantic to lints (Nicolas Werner) - -## [1.1.3] - 2nd Aug 2022 - -- fix: Secret storage keys are used as account data but are not uri encoded -- chore: export filter map extension - -## [1.1.2] - 2nd Aug 2022 - -- feat: Add a flag to disable colors in logs - -## 1.1.1 - -- fix: wrong type for children_state in spaces hierarchy API -- fix: Missing trailing slash on pushrules endpoint -- tests: added tests for spaces hierarchy - -## 1.1.0 - -- fix: wrong types in spaces hierarchy API -- fix: Add missing versions to fake matrix api -- feat: Authenticate media downloads - -## 1.0.0 - -This release should be compatible with version 1.2 of the Matrix specification. - -- feat: Migrate to Matrix v1.2 spec -- feat: Add GroupCallPrefix/GroupCallMemberPrefix to EventTypes. - -## 0.5.3 - -- chore: Add missing matrix error types as per spec -- feat: add additionalProperties in PusherData -- feat: deletePusher - -## 0.5.2 - -- feat: Colored logs on native and web -- chore: Make some tryGet errors verbose and display line - -## 0.5.1 - -- feat: Add constructors to SyncUpdate classes - -## 0.5.0 - -- fix: threepidCreds should be threepid_creds and an object - -## 0.4.4 - -- chore: workaround for invalid getTurnServer responses from synapse - -## 0.4.3 - -- fix: Make type in AuthenticationData nullable -- refactor: remove uploadKeySignatures (use uploadCrossSigningSignatures) - -## 0.4.2 - -- feat: Add more call event for improve voip. - -## 0.4.1 - -- fix: change tryGet default loglevel to Optional - -## 0.4.0 - -- refactor: Migrate to null safety -- refactor: Use openAPI code generation to create most of the methods -- refactor: remove timeouts in matrix_api_lite - -## 0.3.5 - -- feat: Add image pack event content models - -## 0.3.3 - -- fix: Log filter in wrong direction - -## 0.3.2 - -- fix: Logs should only printed if loglevel is high enough - -## 0.3.1 - -- change: Remove logger package - -## 0.3.0 - -- feat: operation names from OpenAPI spec - -## 0.2.6 - -- fix: Missing RoomCreationTypes - -## 0.2.5 - -- fix: Request aliases - -## 0.2.3 - -- feat: Add room and event types for spaces - -## 0.2.2 - -- chore: upgrade logger to 1.0.0 -- refactor: upgrade to http 0.13 - -## 0.2.1 - -- fix: Update dependency mime - -## 0.2.0 - -- refactor: login method AuthenticationIdentifier - -This is a breaking change for the login method to use the correct format. -It makes it possible to login with email or phone. -Also this does some housekeeping stuff while -upgrading to pedantic 1.11.0 which doesnt -allow curly braces in Strings where not needed -anymore. - -## 0.1.9 - -- feat: Add support for fallback keys - -## 0.1.8 - -- fix: Wrong parameters use - -## 0.1.7 - -- change: Less noisy one-line logs - -## 0.1.6 - -- fix: well-known in fake_matrix_api - -## 0.1.5 - -- Add m.dummy event -- fix: Deep-copy arrays correctly - -## 0.1.4 - -- Fix creating shallow copies all the time - -## 0.1.3 - -- Set Content-Length on upload - -## 0.1.2 - -- Add more encryption and decryption content parsing - -## 0.1.1 - -- Add RoomEncryptedContent and RoomEncryptionContent - -## 0.1.0 - -- Initial version diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index bdbe67d9..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,37 +0,0 @@ -# Contributing code to Matrix API Lite - -Everyone is welcome to contribute code to Matrix API Lite, provided that they are willing to license their contributions under the same license as the project itself. -Please follow these rules when contributing code to Matrix API Lite: - -## Merge Requests: -- Never ever just push something directly to the main branch! -- Create a new branch or fork this project and send a Merge Request. -- Only Merge Requests with a working CI can be merged. -- Only Merge Requests with at least one code reviewer can be merged. -- Merge Requests may be refused if they don't follow the rules below. -- A new Merge Request SHOULD never decrease the test coverage. - -## Branches -### Naming - -Branches should get named by this pattern: `[Author]/[Description]`. - -## Commit Messages - -Please use [conventional commit messages](https://www.conventionalcommits.org/en/v1.0.0-beta.2/). - -## File structure: -- Every file must be named by the class and must be capitalized in the beginning. -- Directories need to be lowercase. - -## Code style: -Please use code formatting. You can use VSCode or Android Studio. On other editors you need to run: -``` -flutter format lib/**/*/*.dart -``` - -## Code quality: -- Don't repeat yourself! Use local variables, functions, classes. -- Write tests for new classes, functions and widgets. -- Keep it simple stupid: https://en.wikipedia.org/wiki/KISS_principle -- Describe all of your classes, methods and attributes using **dartdoc** comments. Read this for more information: https://dart.dev/guides/language/effective-dart/documentation \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 2c086bbb..00000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (C) 2021 Famedly GmbH - -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. diff --git a/README.md b/README.md deleted file mode 100644 index 3fa7bdb8..00000000 --- a/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# Deprecation Notice: - -This package will soon be merged with the [Matrix Dart SDK](https://pub.dev/packages/matrix) and from there be available as a library, not a stand alone package anymore. We hope that this will save us some overhead when maintaining the code. If you rely on this package as stand alone and importing the whole Matrix Dart SDK just to use this library is not an option for you, please open an issue here: https://github.com/famedly/dart_matrix_api_lite/issues - -# Matrix API Lite - -This package is a dead simple data model over the client-server specification of https://matrix.org and is mostly used as a base for a more complete Matrix SDK. -It doesn't contain any logic and just provides methods for all API endpoints and json parser for all objects. It is intended to be as close to the specificaton -as possible so we get a 1:1 relationship with the API. More complex logic like a sync loop or a data model for rooms should be implemented in a more complete -Matrix SDK. - -## Usage - -A simple usage example: - -```dart -import 'package:matrix_api_lite/src/matrix_api.dart'; - -void main() async { - final api = MatrixApi(homeserver: Uri.parse('https://matrix.org')); - final capabilities = await api.requestServerCapabilities(); - print(capabilities.toJson()); -} - -``` - -## Generated code - -The files in `lib/src/generated` are generated by [dart_openapi_codegen](https://gitlab.com/famedly/company/frontend/dart_openapi_codegen/) -from [matrix-spec](https://github.com/matrix-org/matrix-spec/). - -To regenerate the code, follow these steps: - -1. Clone both repositories next to each other - 1.1 `git clone git@github.com:famedly/dart_openapi_codegen.git` - 1.2 `git clone git@github.com:famedly/dart_matrix_api_lite.git` -2. Execute the script in the dart_openapi_codegen directory: -```sh -cd dart_openapi_codegen -./scripts/matrix.sh ../dart_matrix_api_lite/lib/src/generated -cd .. -``` -3. Run the build_runner in the matrix_api_lite directory: -```sh -cd dart_matrix_api_lite -dart pub get -dart run build_runner build -``` -4. Check lints and tests and create a merge request \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml deleted file mode 100644 index 58ead17c..00000000 --- a/analysis_options.yaml +++ /dev/null @@ -1,21 +0,0 @@ -include: package:lints/recommended.yaml - -linter: - rules: - camel_case_types: true - avoid_print: true - constant_identifier_names: false - prefer_final_locals: true - prefer_final_in_for_each: true - avoid_dynamic_calls: true - -analyzer: - language: - strict-casts: true - strict-inference: true - strict-raw-types: true - errors: - todo: ignore - exclude: - - example/matrix_api_lite_example.dart - - lib/src/generated/**.dart diff --git a/example/matrix_api_lite_example.dart b/example/matrix_api_lite_example.dart deleted file mode 100644 index 70876234..00000000 --- a/example/matrix_api_lite_example.dart +++ /dev/null @@ -1,8 +0,0 @@ -// @dart=2.9 -import 'package:matrix_api_lite/src/matrix_api.dart'; - -void main() async { - final api = MatrixApi(homeserver: Uri.parse('https://matrix.org')); - final capabilities = await api.requestServerCapabilities(); - print(capabilities.toJson()); -} diff --git a/lib/src/generated/api.dart b/lib/matrix_api_lite/generated/api.dart similarity index 100% rename from lib/src/generated/api.dart rename to lib/matrix_api_lite/generated/api.dart diff --git a/lib/src/generated/fixed_model.dart b/lib/matrix_api_lite/generated/fixed_model.dart similarity index 100% rename from lib/src/generated/fixed_model.dart rename to lib/matrix_api_lite/generated/fixed_model.dart diff --git a/lib/src/generated/internal.dart b/lib/matrix_api_lite/generated/internal.dart similarity index 100% rename from lib/src/generated/internal.dart rename to lib/matrix_api_lite/generated/internal.dart diff --git a/lib/src/generated/model.dart b/lib/matrix_api_lite/generated/model.dart similarity index 100% rename from lib/src/generated/model.dart rename to lib/matrix_api_lite/generated/model.dart diff --git a/lib/src/generated/model.g.dart b/lib/matrix_api_lite/generated/model.g.dart similarity index 100% rename from lib/src/generated/model.g.dart rename to lib/matrix_api_lite/generated/model.g.dart diff --git a/lib/src/matrix_api.dart b/lib/matrix_api_lite/matrix_api.dart similarity index 100% rename from lib/src/matrix_api.dart rename to lib/matrix_api_lite/matrix_api.dart diff --git a/lib/src/model/algorithm_types.dart b/lib/matrix_api_lite/model/algorithm_types.dart similarity index 100% rename from lib/src/model/algorithm_types.dart rename to lib/matrix_api_lite/model/algorithm_types.dart diff --git a/lib/src/model/auth/authentication_data.dart b/lib/matrix_api_lite/model/auth/authentication_data.dart similarity index 100% rename from lib/src/model/auth/authentication_data.dart rename to lib/matrix_api_lite/model/auth/authentication_data.dart diff --git a/lib/src/model/auth/authentication_identifier.dart b/lib/matrix_api_lite/model/auth/authentication_identifier.dart similarity index 100% rename from lib/src/model/auth/authentication_identifier.dart rename to lib/matrix_api_lite/model/auth/authentication_identifier.dart diff --git a/lib/src/model/auth/authentication_password.dart b/lib/matrix_api_lite/model/auth/authentication_password.dart similarity index 100% rename from lib/src/model/auth/authentication_password.dart rename to lib/matrix_api_lite/model/auth/authentication_password.dart diff --git a/lib/src/model/auth/authentication_phone_identifier.dart b/lib/matrix_api_lite/model/auth/authentication_phone_identifier.dart similarity index 100% rename from lib/src/model/auth/authentication_phone_identifier.dart rename to lib/matrix_api_lite/model/auth/authentication_phone_identifier.dart diff --git a/lib/src/model/auth/authentication_recaptcha.dart b/lib/matrix_api_lite/model/auth/authentication_recaptcha.dart similarity index 100% rename from lib/src/model/auth/authentication_recaptcha.dart rename to lib/matrix_api_lite/model/auth/authentication_recaptcha.dart diff --git a/lib/src/model/auth/authentication_third_party_identifier.dart b/lib/matrix_api_lite/model/auth/authentication_third_party_identifier.dart similarity index 100% rename from lib/src/model/auth/authentication_third_party_identifier.dart rename to lib/matrix_api_lite/model/auth/authentication_third_party_identifier.dart diff --git a/lib/src/model/auth/authentication_three_pid_creds.dart b/lib/matrix_api_lite/model/auth/authentication_three_pid_creds.dart similarity index 100% rename from lib/src/model/auth/authentication_three_pid_creds.dart rename to lib/matrix_api_lite/model/auth/authentication_three_pid_creds.dart diff --git a/lib/src/model/auth/authentication_token.dart b/lib/matrix_api_lite/model/auth/authentication_token.dart similarity index 100% rename from lib/src/model/auth/authentication_token.dart rename to lib/matrix_api_lite/model/auth/authentication_token.dart diff --git a/lib/src/model/auth/authentication_types.dart b/lib/matrix_api_lite/model/auth/authentication_types.dart similarity index 100% rename from lib/src/model/auth/authentication_types.dart rename to lib/matrix_api_lite/model/auth/authentication_types.dart diff --git a/lib/src/model/auth/authentication_user_identifier.dart b/lib/matrix_api_lite/model/auth/authentication_user_identifier.dart similarity index 100% rename from lib/src/model/auth/authentication_user_identifier.dart rename to lib/matrix_api_lite/model/auth/authentication_user_identifier.dart diff --git a/lib/src/model/basic_event.dart b/lib/matrix_api_lite/model/basic_event.dart similarity index 100% rename from lib/src/model/basic_event.dart rename to lib/matrix_api_lite/model/basic_event.dart diff --git a/lib/src/model/basic_event_with_sender.dart b/lib/matrix_api_lite/model/basic_event_with_sender.dart similarity index 100% rename from lib/src/model/basic_event_with_sender.dart rename to lib/matrix_api_lite/model/basic_event_with_sender.dart diff --git a/lib/src/model/basic_room_event.dart b/lib/matrix_api_lite/model/basic_room_event.dart similarity index 100% rename from lib/src/model/basic_room_event.dart rename to lib/matrix_api_lite/model/basic_room_event.dart diff --git a/lib/src/model/children_state.dart b/lib/matrix_api_lite/model/children_state.dart similarity index 100% rename from lib/src/model/children_state.dart rename to lib/matrix_api_lite/model/children_state.dart diff --git a/lib/src/model/event_types.dart b/lib/matrix_api_lite/model/event_types.dart similarity index 100% rename from lib/src/model/event_types.dart rename to lib/matrix_api_lite/model/event_types.dart diff --git a/lib/src/model/events/forwarded_room_key_content.dart b/lib/matrix_api_lite/model/events/forwarded_room_key_content.dart similarity index 100% rename from lib/src/model/events/forwarded_room_key_content.dart rename to lib/matrix_api_lite/model/events/forwarded_room_key_content.dart diff --git a/lib/src/model/events/image_pack_content.dart b/lib/matrix_api_lite/model/events/image_pack_content.dart similarity index 100% rename from lib/src/model/events/image_pack_content.dart rename to lib/matrix_api_lite/model/events/image_pack_content.dart diff --git a/lib/src/model/events/olm_plaintext_payload.dart b/lib/matrix_api_lite/model/events/olm_plaintext_payload.dart similarity index 100% rename from lib/src/model/events/olm_plaintext_payload.dart rename to lib/matrix_api_lite/model/events/olm_plaintext_payload.dart diff --git a/lib/src/model/events/room_encrypted_content.dart b/lib/matrix_api_lite/model/events/room_encrypted_content.dart similarity index 100% rename from lib/src/model/events/room_encrypted_content.dart rename to lib/matrix_api_lite/model/events/room_encrypted_content.dart diff --git a/lib/src/model/events/room_encryption_content.dart b/lib/matrix_api_lite/model/events/room_encryption_content.dart similarity index 100% rename from lib/src/model/events/room_encryption_content.dart rename to lib/matrix_api_lite/model/events/room_encryption_content.dart diff --git a/lib/src/model/events/room_key_content.dart b/lib/matrix_api_lite/model/events/room_key_content.dart similarity index 100% rename from lib/src/model/events/room_key_content.dart rename to lib/matrix_api_lite/model/events/room_key_content.dart diff --git a/lib/src/model/events/room_key_request_content.dart b/lib/matrix_api_lite/model/events/room_key_request_content.dart similarity index 100% rename from lib/src/model/events/room_key_request_content.dart rename to lib/matrix_api_lite/model/events/room_key_request_content.dart diff --git a/lib/src/model/events/secret_storage_default_key_content.dart b/lib/matrix_api_lite/model/events/secret_storage_default_key_content.dart similarity index 100% rename from lib/src/model/events/secret_storage_default_key_content.dart rename to lib/matrix_api_lite/model/events/secret_storage_default_key_content.dart diff --git a/lib/src/model/events/secret_storage_key_content.dart b/lib/matrix_api_lite/model/events/secret_storage_key_content.dart similarity index 100% rename from lib/src/model/events/secret_storage_key_content.dart rename to lib/matrix_api_lite/model/events/secret_storage_key_content.dart diff --git a/lib/src/model/events/tombstone_content.dart b/lib/matrix_api_lite/model/events/tombstone_content.dart similarity index 100% rename from lib/src/model/events/tombstone_content.dart rename to lib/matrix_api_lite/model/events/tombstone_content.dart diff --git a/lib/src/model/matrix_connection_exception.dart b/lib/matrix_api_lite/model/matrix_connection_exception.dart similarity index 100% rename from lib/src/model/matrix_connection_exception.dart rename to lib/matrix_api_lite/model/matrix_connection_exception.dart diff --git a/lib/src/model/matrix_event.dart b/lib/matrix_api_lite/model/matrix_event.dart similarity index 100% rename from lib/src/model/matrix_event.dart rename to lib/matrix_api_lite/model/matrix_event.dart diff --git a/lib/src/model/matrix_exception.dart b/lib/matrix_api_lite/model/matrix_exception.dart similarity index 100% rename from lib/src/model/matrix_exception.dart rename to lib/matrix_api_lite/model/matrix_exception.dart diff --git a/lib/src/model/matrix_keys.dart b/lib/matrix_api_lite/model/matrix_keys.dart similarity index 100% rename from lib/src/model/matrix_keys.dart rename to lib/matrix_api_lite/model/matrix_keys.dart diff --git a/lib/src/model/message_types.dart b/lib/matrix_api_lite/model/message_types.dart similarity index 100% rename from lib/src/model/message_types.dart rename to lib/matrix_api_lite/model/message_types.dart diff --git a/lib/src/model/presence.dart b/lib/matrix_api_lite/model/presence.dart similarity index 100% rename from lib/src/model/presence.dart rename to lib/matrix_api_lite/model/presence.dart diff --git a/lib/src/model/presence_content.dart b/lib/matrix_api_lite/model/presence_content.dart similarity index 100% rename from lib/src/model/presence_content.dart rename to lib/matrix_api_lite/model/presence_content.dart diff --git a/lib/src/model/room_creation_types.dart b/lib/matrix_api_lite/model/room_creation_types.dart similarity index 100% rename from lib/src/model/room_creation_types.dart rename to lib/matrix_api_lite/model/room_creation_types.dart diff --git a/lib/src/model/room_keys_keys.dart b/lib/matrix_api_lite/model/room_keys_keys.dart similarity index 100% rename from lib/src/model/room_keys_keys.dart rename to lib/matrix_api_lite/model/room_keys_keys.dart diff --git a/lib/src/model/room_summary.dart b/lib/matrix_api_lite/model/room_summary.dart similarity index 100% rename from lib/src/model/room_summary.dart rename to lib/matrix_api_lite/model/room_summary.dart diff --git a/lib/src/model/room_types.dart b/lib/matrix_api_lite/model/room_types.dart similarity index 100% rename from lib/src/model/room_types.dart rename to lib/matrix_api_lite/model/room_types.dart diff --git a/lib/src/model/stripped_state_event.dart b/lib/matrix_api_lite/model/stripped_state_event.dart similarity index 100% rename from lib/src/model/stripped_state_event.dart rename to lib/matrix_api_lite/model/stripped_state_event.dart diff --git a/lib/src/model/sync_update.dart b/lib/matrix_api_lite/model/sync_update.dart similarity index 100% rename from lib/src/model/sync_update.dart rename to lib/matrix_api_lite/model/sync_update.dart diff --git a/lib/src/utils/filter_map_extension.dart b/lib/matrix_api_lite/utils/filter_map_extension.dart similarity index 100% rename from lib/src/utils/filter_map_extension.dart rename to lib/matrix_api_lite/utils/filter_map_extension.dart diff --git a/lib/src/utils/logs.dart b/lib/matrix_api_lite/utils/logs.dart similarity index 100% rename from lib/src/utils/logs.dart rename to lib/matrix_api_lite/utils/logs.dart diff --git a/lib/src/utils/map_copy_extension.dart b/lib/matrix_api_lite/utils/map_copy_extension.dart similarity index 100% rename from lib/src/utils/map_copy_extension.dart rename to lib/matrix_api_lite/utils/map_copy_extension.dart diff --git a/lib/src/utils/print_logs_native.dart b/lib/matrix_api_lite/utils/print_logs_native.dart similarity index 100% rename from lib/src/utils/print_logs_native.dart rename to lib/matrix_api_lite/utils/print_logs_native.dart diff --git a/lib/src/utils/print_logs_web.dart b/lib/matrix_api_lite/utils/print_logs_web.dart similarity index 100% rename from lib/src/utils/print_logs_web.dart rename to lib/matrix_api_lite/utils/print_logs_web.dart diff --git a/lib/src/utils/try_get_map_extension.dart b/lib/matrix_api_lite/utils/try_get_map_extension.dart similarity index 100% rename from lib/src/utils/try_get_map_extension.dart rename to lib/matrix_api_lite/utils/try_get_map_extension.dart diff --git a/lib/src/values.dart b/lib/matrix_api_lite/values.dart similarity index 100% rename from lib/src/values.dart rename to lib/matrix_api_lite/values.dart diff --git a/pubspec.yaml b/pubspec.yaml deleted file mode 100644 index 6f80e07b..00000000 --- a/pubspec.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: matrix_api_lite -description: Dead simple data model for the matrix.org client-server API. -version: 1.7.3 -homepage: https://famedly.com -repository: https://github.com/famedly/dart_matrix_api_lite -issues: https://github.com/famedly/dart_matrix_api_lite/issues - -environment: - sdk: ">=2.17.0 <4.0.0" - -dependencies: - enhanced_enum: ^0.2.4 - http: ">=0.13.0 <2.0.0" - mime: ^1.0.0 - -dev_dependencies: - build_runner: ^2.1.8 - enhanced_enum_generator: ^0.2.4 - import_sorter: ^4.6.0 - lints: ^2.0.0 - test: ^1.14.4 -# dependency_overrides: # uncomment for local development -# matrix: -# path: "../matrix-dart-sdk" diff --git a/test/event_content_test.dart b/test/event_content_test.dart deleted file mode 100644 index 6b769ba0..00000000 --- a/test/event_content_test.dart +++ /dev/null @@ -1,251 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'dart:convert'; - -import 'package:test/test.dart'; - -import 'package:matrix_api_lite/matrix_api_lite.dart'; - -void main() { - group('Event Content tests', () { - test('Room Encryption Content', () { - Map? json = { - 'content': { - 'algorithm': 'm.megolm.v1.aes-sha2', - 'rotation_period_ms': 604800000, - 'rotation_period_msgs': 100 - }, - 'event_id': '\$143273582443PhrSn:example.org', - 'origin_server_ts': 1432735824653, - 'room_id': '!jEsUZKDJdhlrceRyVU:example.org', - 'sender': '@example:example.org', - 'state_key': '', - 'type': 'm.room.encryption', - 'unsigned': {'age': 1234} - }; - json = jsonDecode(jsonEncode(json)) as Map?; - expect(MatrixEvent.fromJson(json!).parsedRoomEncryptionContent.toJson(), - json['content']); - }); - test('Room Encrypted Content', () { - Map? json = { - 'content': { - 'algorithm': 'm.megolm.v1.aes-sha2', - 'ciphertext': 'AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...', - 'device_id': 'RJYKSTBOIE', - 'sender_key': 'IlRMeOPX2e0MurIyfWEucYBRVOEEUMrOHqn/8mLqMjA', - 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ' - }, - 'event_id': '\$143273582443PhrSn:example.org', - 'origin_server_ts': 1432735824653, - 'room_id': '!jEsUZKDJdhlrceRyVU:example.org', - 'sender': '@example:example.org', - 'type': 'm.room.encrypted', - 'unsigned': {'age': 1234} - }; - json = jsonDecode(jsonEncode(json)) as Map?; - expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), - json['content']); - json = { - 'content': { - 'algorithm': 'm.olm.v1.curve25519-aes-sha2', - 'ciphertext': { - '7qZcfnBmbEGzxxaWfBjElJuvn7BZx+lSz/SvFrDF/z8': { - 'body': 'AwogGJJzMhf/S3GQFXAOrCZ3iKyGU5ZScVtjI0KypTYrW...', - 'type': 0 - } - }, - 'sender_key': 'Szl29ksW/L8yZGWAX+8dY1XyFi+i5wm+DRhTGkbMiwU' - }, - 'event_id': '\$143273582443PhrSn:example.org', - 'origin_server_ts': 1432735824653, - 'room_id': '!jEsUZKDJdhlrceRyVU:example.org', - 'sender': '@example:example.org', - 'type': 'm.room.encrypted', - 'unsigned': {'age': 1234} - }; - json = jsonDecode(jsonEncode(json)) as Map?; - expect(MatrixEvent.fromJson(json!).parsedRoomEncryptedContent.toJson(), - json['content']); - }); - test('Room Key Content', () { - Map? json = { - 'content': { - 'algorithm': 'm.megolm.v1.aes-sha2', - 'room_id': '!Cuyf34gef24t:localhost', - 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ', - 'session_key': 'AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8LlfJL7qNBEY...' - }, - 'type': 'm.room_key' - }; - json = jsonDecode(jsonEncode(json)) as Map?; - expect(BasicEvent.fromJson(json!).parsedRoomKeyContent.toJson(), - json['content']); - }); - test('Room Key Request Content', () { - Map? json = { - 'content': { - 'action': 'request_cancellation', - 'request_id': '1495474790150.19', - 'requesting_device_id': 'RJYKSTBOIE' - }, - 'type': 'm.room_key_request' - }; - json = jsonDecode(jsonEncode(json)) as Map?; - expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), - json['content']); - json = { - 'content': { - 'action': 'request', - 'body': { - 'algorithm': 'm.megolm.v1.aes-sha2', - 'room_id': '!Cuyf34gef24t:localhost', - 'sender_key': 'RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU', - 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ' - }, - 'request_id': '1495474790150.19', - 'requesting_device_id': 'RJYKSTBOIE' - }, - 'type': 'm.room_key_request' - }; - json = jsonDecode(jsonEncode(json)) as Map?; - expect(BasicEvent.fromJson(json!).parsedRoomKeyRequestContent.toJson(), - json['content']); - }); - test('Forwarded Room Key Content', () { - Map? json = { - 'content': { - 'algorithm': 'm.megolm.v1.aes-sha2', - 'forwarding_curve25519_key_chain': [ - 'hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw' - ], - 'room_id': '!Cuyf34gef24t:localhost', - 'sender_claimed_ed25519_key': - 'aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y', - 'sender_key': 'RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU', - 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ', - 'session_key': 'AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf...' - }, - 'type': 'm.forwarded_room_key' - }; - json = jsonDecode(jsonEncode(json)) as Map?; - expect(BasicEvent.fromJson(json!).parsedForwardedRoomKeyContent.toJson(), - json['content']); - }); - test('OLM Plaintext Payload', () { - Map? json = { - 'type': '', - 'content': { - 'msgtype': 'm.text', - 'body': 'Hello world', - }, - 'sender': '', - 'recipient': '', - 'recipient_keys': {'ed25519': ''}, - 'keys': {'ed25519': ''} - }; - json = jsonDecode(jsonEncode(json)) as Map?; - expect(OlmPlaintextPayload.fromJson(json!).toJson(), json); - }); - test('Image Pack Content', () { - // basic parse / unparse - var json = { - 'type': 'some type', - 'content': { - 'images': { - 'emote': { - 'url': 'mxc://example.org/beep', - 'usage': ['emoticon'], - 'org.custom': 'beep', - }, - 'sticker': { - 'url': 'mxc://example.org/boop', - 'usage': ['org.custom', 'sticker', 'org.other.custom'], - }, - }, - 'pack': { - 'display_name': 'Awesome Pack', - 'org.custom': 'boop', - }, - 'org.custom': 'blah', - }, - }; - json = jsonDecode(jsonEncode(json)) as Map; - expect(BasicEvent.fromJson(json).parsedImagePackContent.toJson(), - json['content']); - - // emoticons migration - json = { - 'type': 'some type', - 'content': { - 'emoticons': { - ':emote:': { - 'url': 'mxc://example.org/beep', - }, - }, - }, - }; - json = jsonDecode(jsonEncode(json)) as Map; - expect( - BasicEvent.fromJson(json) - .parsedImagePackContent - .images['emote'] - ?.toJson(), - { - 'url': 'mxc://example.org/beep', - }); - - json = { - 'type': 'some type', - 'content': { - 'short': { - ':emote:': 'mxc://example.org/beep', - }, - }, - }; - json = jsonDecode(jsonEncode(json)) as Map; - expect( - BasicEvent.fromJson(json) - .parsedImagePackContent - .images['emote'] - ?.toJson(), - { - 'url': 'mxc://example.org/beep', - }); - - // invalid url for image - json = { - 'type': 'some type', - 'content': { - 'images': { - 'emote': {}, - }, - }, - }; - json = jsonDecode(jsonEncode(json)) as Map; - expect(BasicEvent.fromJson(json).parsedImagePackContent.images['emote'], - null); - }); - }); -} diff --git a/test/map_copy_extension_test.dart b/test/map_copy_extension_test.dart deleted file mode 100644 index d20b61e8..00000000 --- a/test/map_copy_extension_test.dart +++ /dev/null @@ -1,59 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'package:test/test.dart'; - -import 'package:matrix_api_lite/matrix_api_lite.dart'; - -void main() { - group('Map-copy-extension', () { - test('it should work', () { - final original = { - 'attr': 'fox', - 'child': { - 'attr': 'bunny', - 'list': [1, 2], - }, - }; - final copy = original.copy(); - (original['child'] as Map)['attr'] = 'raccoon'; - expect((copy['child'] as Map)['attr'], 'bunny'); - ((original['child'] as Map)['list'] as List).add(3); - expect((copy['child'] as Map)['list'], [1, 2]); - }); - test('should do arrays', () { - final original = { - 'arr': [ - [1, 2], - {'beep': 'boop'}, - ], - }; - final copy = original.copy(); - ((original['arr'] as List)[0] as List).add(3); - expect((copy['arr'] as List)[0], [1, 2]); - ((original['arr'] as List)[1] as Map)['beep'] = 'blargh'; - expect( - ((copy['arr'] as List)[1] as Map)['beep'], 'boop'); - }); - }); -} diff --git a/test/matrix_api_test.dart b/test/matrix_api_test.dart deleted file mode 100644 index 9b6943c0..00000000 --- a/test/matrix_api_test.dart +++ /dev/null @@ -1,1934 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'dart:typed_data'; - -import 'package:test/test.dart'; - -import 'package:matrix_api_lite/fake_matrix_api.dart'; -import 'package:matrix_api_lite/matrix_api_lite.dart'; - -const emptyRequest = {}; - -void main() { - /// All Tests related to device keys - group('Matrix API', () { - test('Logger', () async { - Logs().level = Level.verbose; - Logs().v('Test log'); - Logs().d('Test log'); - Logs().w('Test log'); - Logs().e('Test log'); - Logs().wtf('Test log'); - Logs().v('Test log', Exception('There has been a verbose')); - Logs().d('Test log', Exception('Test')); - Logs().w('Test log', Exception('Very bad error')); - Logs().e('Test log', Exception('Test'), StackTrace.current); - Logs().wtf('Test log', Exception('Test'), StackTrace.current); - }); - Logs().level = Level.error; - final matrixApi = MatrixApi( - httpClient: FakeMatrixApi(), - ); - test('MatrixException test', () async { - final exception = MatrixException.fromJson({ - 'flows': [ - { - 'stages': ['example.type.foo'] - } - ], - 'params': { - 'example.type.baz': {'example_key': 'foobar'} - }, - 'session': 'xxxxxxyz', - 'completed': ['example.type.foo'] - }); - expect(exception.authenticationFlows!.first.stages.first, - 'example.type.foo'); - expect(exception.authenticationParams!['example.type.baz'], - {'example_key': 'foobar'}); - expect(exception.session, 'xxxxxxyz'); - expect(exception.completedAuthenticationFlows, ['example.type.foo']); - expect(exception.requireAdditionalAuthentication, true); - expect(exception.retryAfterMs, null); - expect(exception.error, MatrixError.M_FORBIDDEN); - expect(exception.errcode, 'M_FORBIDDEN'); - expect(exception.errorMessage, 'Require additional authentication'); - }); - test('triggerNotFoundError', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - bool error; - error = false; - try { - await matrixApi.request(RequestType.GET, '/fake/path'); - } catch (_) { - error = true; - } - expect(error, true); - error = false; - try { - await matrixApi.request(RequestType.POST, '/fake/path'); - } catch (_) { - error = true; - } - expect(error, true); - error = false; - try { - await matrixApi.request(RequestType.PUT, '/fake/path'); - } catch (_) { - error = true; - } - expect(error, true); - error = false; - try { - await matrixApi.request(RequestType.DELETE, '/fake/path'); - } catch (_) { - error = true; - } - expect(error, true); - error = false; - try { - await matrixApi.request(RequestType.GET, '/path/to/auth/error/'); - } catch (exception) { - expect(exception is MatrixException, true); - expect((exception as MatrixException).errcode, 'M_FORBIDDEN'); - expect(exception.error, MatrixError.M_FORBIDDEN); - expect(exception.errorMessage, 'Blabla'); - expect(exception.requireAdditionalAuthentication, false); - expect(exception.toString(), 'M_FORBIDDEN: Blabla'); - error = true; - } - expect(error, true); - matrixApi.homeserver = null; - }); - test('getSupportedVersions', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final supportedVersions = await matrixApi.getVersions(); - expect(supportedVersions.versions.contains('r0.5.0'), true); - expect(supportedVersions.unstableFeatures!['m.lazy_load_members'], true); - expect(FakeMatrixApi.api['GET']!['/client/versions']!.call(emptyRequest), - supportedVersions.toJson()); - matrixApi.homeserver = null; - }); - test('getWellKnownInformation', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final wellKnownInformation = await matrixApi.getWellknown(); - expect(wellKnownInformation.mHomeserver.baseUrl, - Uri.parse('https://fakeserver.notexisting')); - expect(wellKnownInformation.toJson(), { - 'm.homeserver': {'base_url': 'https://fakeserver.notexisting'}, - 'm.identity_server': { - 'base_url': 'https://identity.fakeserver.notexisting' - }, - 'org.example.custom.property': { - 'app_url': 'https://custom.app.fakeserver.notexisting' - } - }); - }); - test('getLoginTypes', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final loginTypes = await matrixApi.getLoginFlows(); - expect(loginTypes?.first.type, 'm.login.password'); - expect(FakeMatrixApi.api['GET']!['/client/v3/login']!.call(emptyRequest), - {'flows': loginTypes?.map((x) => x.toJson()).toList()}); - matrixApi.homeserver = null; - }); - test('login', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final loginResponse = await matrixApi.login( - LoginType.mLoginPassword, - identifier: AuthenticationUserIdentifier(user: 'username'), - ); - expect(FakeMatrixApi.api['POST']!['/client/v3/login']!.call(emptyRequest), - loginResponse.toJson()); - matrixApi.homeserver = null; - }); - test('logout', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.logout(); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('logoutAll', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.logoutAll(); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('register', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final registerResponse = - await matrixApi.register(kind: AccountKind.guest, username: 'test'); - expect( - FakeMatrixApi.api['POST']!['/client/v3/register?kind=guest']! - .call(emptyRequest), - registerResponse.toJson()); - matrixApi.homeserver = null; - }); - test('requestTokenToRegisterEmail', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.requestTokenToRegisterEmail( - 'alice@example.com', - '1234', - 1, - nextLink: 'https://example.com', - idServer: 'https://example.com', - idAccessToken: '1234', - ); - expect( - FakeMatrixApi.api['POST']!['/client/v3/register/email/requestToken']! - .call(emptyRequest), - response.toJson()); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestTokenToRegisterMSISDN', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.requestTokenToRegisterMSISDN( - 'en', - '1234', - '1234', - 1, - nextLink: 'https://example.com', - idServer: 'https://example.com', - idAccessToken: '1234', - ); - expect( - FakeMatrixApi.api['POST']!['/client/v3/register/email/requestToken']! - .call(emptyRequest), - response.toJson()); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('changePassword', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.changePassword( - '1234', - auth: AuthenticationData.fromJson({ - 'type': 'example.type.foo', - 'session': 'xxxxx', - 'example_credential': 'verypoorsharedsecret' - }), - ); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestTokenToResetPasswordEmail', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.requestTokenToResetPasswordEmail( - 'alice@example.com', - '1234', - 1, - nextLink: 'https://example.com', - idServer: 'https://example.com', - idAccessToken: '1234', - ); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestTokenToResetPasswordMSISDN', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.requestTokenToResetPasswordMSISDN( - 'en', - '1234', - '1234', - 1, - nextLink: 'https://example.com', - idServer: 'https://example.com', - idAccessToken: '1234', - ); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('deactivateAccount', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.deactivateAccount( - idServer: 'https://example.com', - auth: AuthenticationData.fromJson({ - 'type': 'example.type.foo', - 'session': 'xxxxx', - 'example_credential': 'verypoorsharedsecret' - }), - ); - expect(response, IdServerUnbindResult.success); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('usernameAvailable', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - final loginResponse = - await matrixApi.checkUsernameAvailability('testuser'); - expect(loginResponse, true); - matrixApi.homeserver = null; - }); - test('getThirdPartyIdentifiers', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.getAccount3PIDs(); - expect( - FakeMatrixApi.api['GET']!['/client/v3/account/3pid']! - .call(emptyRequest), - {'threepids': response?.map((t) => t.toJson()).toList()}); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('addThirdPartyIdentifier', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.add3PID('1234', '1234', - auth: AuthenticationData.fromJson({'type': 'm.login.dummy'})); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('bindThirdPartyIdentifier', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.bind3PID( - '1234', - '1234', - 'https://example.com', - '1234', - ); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('deleteThirdPartyIdentifier', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.delete3pidFromAccount( - 'alice@example.com', - ThirdPartyIdentifierMedium.email, - idServer: 'https://example.com', - ); - expect(response, IdServerUnbindResult.success); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('unbindThirdPartyIdentifier', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.unbind3pidFromAccount( - 'alice@example.com', - ThirdPartyIdentifierMedium.email, - idServer: 'https://example.com', - ); - expect(response, IdServerUnbindResult.success); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestTokenTo3PIDEmail', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.requestTokenTo3PIDEmail( - 'alice@example.com', - '1234', - 1, - nextLink: 'https://example.com', - idServer: 'https://example.com', - idAccessToken: '1234', - ); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestTokenTo3PIDMSISDN', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.requestTokenTo3PIDMSISDN( - 'en', - '1234', - '1234', - 1, - nextLink: 'https://example.com', - idServer: 'https://example.com', - idAccessToken: '1234', - ); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestTokenTo3PIDMSISDN', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.getTokenOwner(); - expect(response.userId, 'alice@example.com'); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('getCapabilities', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.getCapabilities(); - expect( - FakeMatrixApi.api['GET']!['/client/v3/capabilities']! - .call(emptyRequest), - {'capabilities': response.toJson()}); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('uploadFilter', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = - await matrixApi.defineFilter('alice@example.com', Filter()); - expect(response, '1234'); - final filter = Filter( - room: RoomFilter( - notRooms: ['!1234'], - rooms: ['!1234'], - ephemeral: StateFilter( - limit: 10, - senders: ['@alice:example.com'], - types: ['type1'], - notTypes: ['type2'], - notRooms: ['!1234'], - notSenders: ['@bob:example.com'], - lazyLoadMembers: true, - includeRedundantMembers: false, - containsUrl: true, - ), - includeLeave: true, - state: StateFilter(), - timeline: StateFilter(), - accountData: StateFilter(limit: 10, types: ['type1']), - ), - presence: StateFilter( - limit: 10, - senders: ['@alice:example.com'], - types: ['type1'], - notRooms: ['!1234'], - notSenders: ['@bob:example.com'], - ), - eventFormat: EventFormat.client, - eventFields: ['type', 'content', 'sender'], - accountData: EventFilter( - types: ['m.accountdatatest'], - notSenders: ['@alice:example.com'], - ), - ); - expect(filter.toJson(), { - 'room': { - 'not_rooms': ['!1234'], - 'rooms': ['!1234'], - 'ephemeral': { - 'limit': 10, - 'senders': ['@alice:example.com'], - 'types': ['type1'], - 'not_rooms': ['!1234'], - 'not_senders': ['@bob:example.com'], - 'not_types': ['type2'], - 'lazy_load_members': true, - 'include_redundant_members': false, - 'contains_url': true, - }, - 'account_data': { - 'limit': 10, - 'types': ['type1'], - }, - 'include_leave': true, - 'state': {}, - 'timeline': {}, - }, - 'presence': { - 'limit': 10, - 'senders': ['@alice:example.com'], - 'types': ['type1'], - 'not_rooms': ['!1234'], - 'not_senders': ['@bob:example.com'] - }, - 'event_format': 'client', - 'event_fields': ['type', 'content', 'sender'], - 'account_data': { - 'types': ['m.accountdatatest'], - 'not_senders': ['@alice:example.com'] - }, - }); - await matrixApi.defineFilter( - 'alice@example.com', - filter, - ); - final filterMap = { - 'room': { - 'state': { - 'types': ['m.room.*'], - 'not_rooms': ['!726s6s6q:example.com'] - }, - 'timeline': { - 'limit': 10, - 'types': ['m.room.message'], - 'not_rooms': ['!726s6s6q:example.com'], - 'not_senders': ['@spam:example.com'] - }, - 'ephemeral': { - 'types': ['m.receipt', 'm.typing'], - 'not_rooms': ['!726s6s6q:example.com'], - 'not_senders': ['@spam:example.com'] - } - }, - 'presence': { - 'types': ['m.presence'], - 'not_senders': ['@alice:example.com'] - }, - 'account_data': { - 'types': ['m.accountdatatest'], - 'not_senders': ['@alice:example.com'] - }, - 'event_format': 'client', - 'event_fields': ['type', 'content', 'sender'] - }; - expect(filterMap, Filter.fromJson(filterMap).toJson()); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('downloadFilter', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - await matrixApi.getFilter('alice@example.com', '1234'); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('sync', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = await matrixApi.sync( - filter: '{}', - since: '1234', - fullState: false, - setPresence: PresenceType.unavailable, - timeout: 15, - ); - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/sync?filter=%7B%7D&since=1234&full_state=false&set_presence=unavailable&timeout=15']! - .call(emptyRequest) as Map?, - response.toJson()); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestEvent', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final event = - await matrixApi.getOneRoomEvent('!localpart:server.abc', '1234'); - expect(event.eventId, '143273582443PhrSn:example.org'); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('getRoomStateWithKey', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.getRoomStateWithKey( - '!localpart:server.abc', - 'm.room.member', - '@getme:example.com', - ); - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestStates', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final states = await matrixApi.getRoomState('!localpart:server.abc'); - expect(states.length, 4); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestMembers', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final states = await matrixApi.getMembersByRoom( - '!localpart:server.abc', - at: '1234', - membership: Membership.join, - notMembership: Membership.leave, - ); - expect(states?.length, 1); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestJoinedMembers', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final states = await matrixApi.getJoinedMembersByRoom( - '!localpart:server.abc', - ); - expect(states?.length, 1); - expect(states?['@bar:example.com']?.toJson(), { - 'display_name': 'Bar', - 'avatar_url': 'mxc://riot.ovh/printErCATzZijQsSDWorRaK' - }); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestMessages', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final timelineHistoryResponse = await matrixApi.getRoomEvents( - '!localpart:server.abc', - Direction.b, - from: '1234', - limit: 10, - filter: '{"lazy_load_members":true}', - to: '1234', - ); - - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/rooms/!localpart%3Aserver.abc/messages?from=1234&to=1234&dir=b&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D']! - .call(emptyRequest) as Map?, - timelineHistoryResponse.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('sendState', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final eventId = await matrixApi.setRoomStateWithKey( - '!localpart:server.abc', 'm.room.avatar', '', {'url': 'mxc://1234'}); - - expect(eventId, 'YUwRidLecu:example.com'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('sendMessage', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final eventId = await matrixApi.sendMessage( - '!localpart:server.abc', - 'm.room.message', - '1234', - {'body': 'hello world', 'msgtype': 'm.text'}, - ); - - expect(eventId, 'YUwRidLecu:example.com'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('redact', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final eventId = await matrixApi.redactEvent( - '!localpart:server.abc', - '1234', - '1234', - reason: 'hello world', - ); - - expect(eventId, 'YUwRidLecu:example.com'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('createRoom', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = await matrixApi.createRoom( - visibility: Visibility.public, - roomAliasName: '#testroom:example.com', - name: 'testroom', - topic: 'just for testing', - invite: ['@bob:example.com'], - invite3pid: [], - roomVersion: '2', - creationContent: {}, - initialState: [], - preset: CreateRoomPreset.publicChat, - isDirect: false, - powerLevelContentOverride: {}, - ); - - expect(roomId, '!1234:fakeServer.notExisting'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('createRoomAlias', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setRoomAlias( - '#testalias:example.com', - '!1234:example.com', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestRoomAliasInformation', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomAliasInformation = await matrixApi.getRoomIdByAlias( - '#testalias:example.com', - ); - - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/directory/room/%23testalias%3Aexample.com']! - .call(emptyRequest), - roomAliasInformation.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('removeRoomAlias', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.deleteRoomAlias('#testalias:example.com'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestRoomAliases', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final list = await matrixApi.getLocalAliases('!localpart:example.com'); - expect(list.length, 3); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestJoinedRooms', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final list = await matrixApi.getJoinedRooms(); - expect(list.length, 1); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('inviteUser', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.inviteUser('!localpart:example.com', '@bob:example.com'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('joinRoom', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!localpart:example.com'; - final response = await matrixApi.joinRoomById( - roomId, - thirdPartySigned: ThirdPartySigned( - sender: '@bob:example.com', - mxid: '@alice:example.com', - token: '1234', - signatures: { - 'example.org': {'ed25519:0': 'some9signature'} - }, - ), - ); - expect(response, roomId); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('joinRoomOrAlias', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!localpart:example.com'; - final response = await matrixApi.joinRoom( - roomId, - serverName: ['example.com', 'example.abc'], - thirdPartySigned: ThirdPartySigned( - sender: '@bob:example.com', - mxid: '@alice:example.com', - token: '1234', - signatures: { - 'example.org': {'ed25519:0': 'some9signature'} - }, - ), - ); - expect(response, roomId); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('leave', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.leaveRoom('!localpart:example.com'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('forget', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.forgetRoom('!localpart:example.com'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('kickFromRoom', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.kick( - '!localpart:example.com', - '@bob:example.com', - reason: 'test', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('banFromRoom', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.ban( - '!localpart:example.com', - '@bob:example.com', - reason: 'test', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('unbanInRoom', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.unban( - '!localpart:example.com', - '@bob:example.com', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestRoomVisibility', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final visibility = await matrixApi - .getRoomVisibilityOnDirectory('!localpart:example.com'); - expect(visibility, Visibility.public); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setRoomVisibility', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setRoomVisibilityOnDirectory('!localpart:example.com', - visibility: Visibility.private); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestPublicRooms', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getPublicRooms( - limit: 10, - since: '1234', - server: 'example.com', - ); - - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/publicRooms?limit=10&since=1234&server=example.com']! - .call(emptyRequest), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('searchPublicRooms', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.queryPublicRooms( - limit: 10, - since: '1234', - server: 'example.com', - filter: PublicRoomQueryFilter( - genericSearchTerm: 'test', - ), - includeAllNetworks: false, - thirdPartyInstanceId: 'id', - ); - - expect( - FakeMatrixApi - .api['POST']!['/client/v3/publicRooms?server=example.com']! - .call(emptyRequest), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('getSpaceHierarchy', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = - await matrixApi.getSpaceHierarchy('!gPxZhKUssFZKZcoCKY:neko.dev'); - - expect( - FakeMatrixApi.api['GET']![ - '/client/v1/rooms/${Uri.encodeComponent('!gPxZhKUssFZKZcoCKY:neko.dev')}/hierarchy']! - .call(emptyRequest), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('searchUser', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.searchUserDirectory( - 'test', - limit: 10, - ); - - expect( - FakeMatrixApi.api['POST']!['/client/v3/user_directory/search']! - .call(emptyRequest), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setDisplayname', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setDisplayName('@alice:example.com', 'Alice M'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestDisplayname', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.getDisplayName('@alice:example.com'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setAvatarUrl', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setAvatarUrl( - '@alice:example.com', - Uri.parse('mxc://test'), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestAvatarUrl', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getAvatarUrl('@alice:example.com'); - expect(response, Uri.parse('mxc://test')); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestProfile', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getUserProfile('@alice:example.com'); - expect( - FakeMatrixApi - .api['GET']!['/client/v3/profile/%40alice%3Aexample.com']! - .call(emptyRequest), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestTurnServerCredentials', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getTurnServer(); - expect( - FakeMatrixApi.api['GET']!['/client/v3/voip/turnServer']! - .call(emptyRequest), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('sendTypingNotification', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setTyping( - '@alice:example.com', - '!localpart:example.com', - true, - timeout: 10, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('sendReceiptMarker', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.postReceipt( - '!localpart:example.com', - ReceiptType.mRead, - '\$1234:example.com', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('sendReadMarker', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setReadMarker( - '!localpart:example.com', - mFullyRead: '\$1234:example.com', - mRead: '\$1234:example.com', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('sendPresence', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setPresence( - '@alice:example.com', - PresenceType.offline, - statusMsg: 'test', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestPresence', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getPresence( - '@alice:example.com', - ); - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/presence/${Uri.encodeComponent('@alice:example.com')}/status']! - .call(emptyRequest), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('upload', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - final response = - await matrixApi.uploadContent(Uint8List(0), filename: 'file.jpeg'); - expect(response, Uri.parse('mxc://example.com/AQwafuaFswefuhsfAFAgsw')); - var throwsException = false; - try { - await matrixApi.uploadContent(Uint8List(0), filename: 'file.jpg'); - } catch (_) { - throwsException = true; - } - expect(throwsException, true); - matrixApi.homeserver = null; - }); - test('requestOpenGraphDataForUrl', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final openGraphData = await matrixApi.getUrlPreview( - Uri.parse('https://matrix.org'), - ts: 10, - ); - expect( - FakeMatrixApi.api['GET']![ - '/media/v3/preview_url?url=https%3A%2F%2Fmatrix.org&ts=10']! - .call(emptyRequest), - openGraphData.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('getConfig', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getConfig(); - expect(response.mUploadSize, 50000000); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('sendToDevice', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.sendToDevice('m.test', '1234', { - '@alice:example.com': { - 'TLLBEANAAG': {'example_content_key': 'value'} - } - }); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestDevices', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final devices = await matrixApi.getDevices(); - expect( - (FakeMatrixApi.api['GET']!['/client/v3/devices']!.call(emptyRequest) - as Map?)?['devices'], - devices?.map((i) => i.toJson()).toList()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestDevice', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.getDevice('QBUAZIFURK'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setDeviceMetadata', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.updateDevice('QBUAZIFURK', displayName: 'test'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('deleteDevice', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.deleteDevice('QBUAZIFURK'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('deleteDevices', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.deleteDevices(['QBUAZIFURK']); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('uploadDeviceKeys', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.uploadKeys( - deviceKeys: MatrixDeviceKeys( - '@alice:example.com', - 'ABCD', - ['caesar-chiffre'], - {}, - {}, - unsigned: {}, - ), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestDeviceKeys', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.queryKeys( - { - '@alice:example.com': [], - }, - timeout: 10, - token: '1234', - ); - expect( - response.deviceKeys!['@alice:example.com']!['JLAFKJWSCS']! - .deviceDisplayName, - 'Alices mobile phone'); - expect( - FakeMatrixApi.api['POST']!['/client/v3/keys/query']! - .call({'device_keys': emptyRequest}), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestOneTimeKeys', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.claimKeys( - { - '@alice:example.com': {'JLAFKJWSCS': 'signed_curve25519'} - }, - timeout: 10, - ); - expect( - FakeMatrixApi.api['POST']!['/client/v3/keys/claim']!.call({ - 'one_time_keys': { - '@alice:example.com': {'JLAFKJWSCS': 'signed_curve25519'} - } - }), - response.toJson()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestDeviceListsUpdate', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.getKeysChanges('1234', '1234'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('uploadCrossSigningKeys', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final masterKey = MatrixCrossSigningKey.fromJson({ - 'user_id': '@test:fakeServer.notExisting', - 'usage': ['master'], - 'keys': { - 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': - '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8', - }, - 'signatures': >{}, - }); - final selfSigningKey = MatrixCrossSigningKey.fromJson({ - 'user_id': '@test:fakeServer.notExisting', - 'usage': ['self_signing'], - 'keys': { - 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': - 'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY', - }, - 'signatures': >{}, - }); - final userSigningKey = MatrixCrossSigningKey.fromJson({ - 'user_id': '@test:fakeServer.notExisting', - 'usage': ['user_signing'], - 'keys': { - 'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g': - '0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g', - }, - 'signatures': >{}, - }); - await matrixApi.uploadCrossSigningKeys( - masterKey: masterKey, - selfSigningKey: selfSigningKey, - userSigningKey: userSigningKey); - }); - test('requestPushers', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getPushers(); - expect( - FakeMatrixApi.api['GET']!['/client/v3/pushers']! - .call({}), - {'pushers': response?.map((i) => i.toJson()).toList()}, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setPusher', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.postPusher( - Pusher( - pushkey: '1234', - appId: 'app.id', - appDisplayName: 'appDisplayName', - deviceDisplayName: 'deviceDisplayName', - lang: 'en', - data: PusherData( - format: 'event_id_only', url: Uri.parse('https://matrix.org')), - profileTag: 'tag', - kind: 'http', - ), - append: true, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestNotifications', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getNotifications( - from: '1234', - limit: 10, - only: '1234', - ); - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/notifications?from=1234&limit=10&only=1234']! - .call({}), - response.toJson(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestPushRules', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getPushRules(); - expect( - FakeMatrixApi.api['GET']!['/client/v3/pushrules']! - .call({}), - {'global': response.toJson()}, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestPushRule', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = - await matrixApi.getPushRule('global', PushRuleKind.content, 'nocake'); - expect( - FakeMatrixApi.api['GET']!['/client/v3/pushrules/global/content/nocake']! - .call({}), - response.toJson(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('deletePushRule', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.deletePushRule('global', PushRuleKind.content, 'nocake'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setPushRule', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setPushRule( - 'global', - PushRuleKind.content, - 'nocake', - [PushRuleAction.notify], - before: '1', - after: '2', - conditions: [ - PushCondition( - kind: 'event_match', - key: 'key', - pattern: 'pattern', - is$: '+', - ) - ], - pattern: 'pattern', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestPushRuleEnabled', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final enabled = await matrixApi.isPushRuleEnabled( - 'global', PushRuleKind.content, 'nocake'); - expect(enabled, true); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('enablePushRule', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setPushRuleEnabled( - 'global', - PushRuleKind.content, - 'nocake', - true, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestPushRuleActions', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final actions = await matrixApi.getPushRuleActions( - 'global', PushRuleKind.content, 'nocake'); - expect(actions.first, PushRuleAction.notify); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setPushRuleActions', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setPushRuleActions( - 'global', - PushRuleKind.content, - 'nocake', - [PushRuleAction.dontNotify], - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('globalSearch', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.search(Categories()); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('globalSearch', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.peekEvents( - from: '1234', roomId: '!1234', timeout: 10); - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/events?from=1234&timeout=10&room_id=%211234']! - .call({}), - response.toJson(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestRoomTags', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getRoomTags( - '@alice:example.com', '!localpart:example.com'); - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/user/%40alice%3Aexample.com/rooms/!localpart%3Aexample.com/tags']! - .call({}), - {'tags': response?.map((k, v) => MapEntry(k, v.toJson()))}, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('addRoomTag', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setRoomTag( - '@alice:example.com', - '!localpart:example.com', - 'testtag', - order: 0.5, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('addRoomTag', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.deleteRoomTag( - '@alice:example.com', - '!localpart:example.com', - 'testtag', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setAccountData', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setAccountData( - '@alice:example.com', - 'test.account.data', - {'foo': 'bar'}, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestAccountData', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.getAccountData( - '@alice:example.com', - 'test.account.data', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('setRoomAccountData', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.setAccountDataPerRoom( - '@alice:example.com', - '1234', - 'test.account.data', - {'foo': 'bar'}, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestRoomAccountData', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.getAccountDataPerRoom( - '@alice:example.com', - '1234', - 'test.account.data', - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestWhoIsInfo', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getWhoIs('@alice:example.com'); - expect( - FakeMatrixApi - .api['GET']!['/client/v3/admin/whois/%40alice%3Aexample.com']! - .call(emptyRequest), - response.toJson(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestEventContext', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getEventContext('1234', '1234', - limit: 10, filter: '{}'); - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/rooms/1234/context/1234?limit=10&filter=%7B%7D']! - .call(emptyRequest), - response.toJson(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('reportEvent', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.reportContent( - '1234', - '1234', - reason: 'test', - score: -100, - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('getProtocols', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getProtocols(); - expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocols']! - .call(emptyRequest), - response.map((k, v) => MapEntry(k, v.toJson())), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('getProtocol', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.getProtocolMetadata('irc'); - expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/protocol/irc']! - .call(emptyRequest), - response.toJson(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('queryLocationByProtocol', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.queryLocationByProtocol('irc'); - expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/location/irc']! - .call(emptyRequest), - response.map((i) => i.toJson()).toList(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('queryUserByProtocol', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.queryUserByProtocol('irc'); - expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user/irc']! - .call(emptyRequest), - response.map((i) => i.toJson()).toList(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('queryLocationByAlias', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.queryLocationByAlias('1234'); - expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/location?alias=1234']! - .call(emptyRequest), - response.map((i) => i.toJson()).toList(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('queryUserByID', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.queryUserByID('1234'); - expect( - FakeMatrixApi.api['GET']!['/client/v3/thirdparty/user?userid=1234']! - .call(emptyRequest), - response.map((i) => i.toJson()).toList(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('requestOpenIdCredentials', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final response = await matrixApi.requestOpenIdToken('1234', {}); - expect( - FakeMatrixApi.api['POST']!['/client/v3/user/1234/openid/request_token']! - .call(emptyRequest), - response.toJson(), - ); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('upgradeRoom', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.upgradeRoom('1234', '2'); - - matrixApi.homeserver = matrixApi.accessToken = null; - }); - test('postRoomKeysVersion', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; - final authData = { - 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', - 'signatures': >{}, - }; - final ret = await matrixApi.postRoomKeysVersion(algorithm, authData); - expect( - (FakeMatrixApi.api['POST']!['/client/v3/room_keys/version']! - .call(emptyRequest) as Map)['version'], - ret); - }); - test('getRoomKeysVersionCurrent', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final ret = await matrixApi.getRoomKeysVersionCurrent(); - expect( - FakeMatrixApi.api['GET']!['/client/v3/room_keys/version']! - .call(emptyRequest), - ret.toJson()); - }); - test('putRoomKeysVersion', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final algorithm = BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2; - final authData = { - 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM', - 'signatures': >{}, - }; - await matrixApi.putRoomKeysVersion('5', algorithm, authData); - }); - test('deleteRoomKeys', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - await matrixApi.deleteRoomKeys('5'); - }); - test('putRoomKeyBySessionId', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final session = KeyBackupData.fromJson({ - 'first_message_index': 0, - 'forwarded_count': 0, - 'is_verified': true, - 'session_data': { - 'ephemeral': 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', - 'ciphertext': - '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', - 'mac': 'QzKV/fgAs4U', - }, - }); - final ret = await matrixApi.putRoomKeyBySessionId( - roomId, sessionId, '5', session); - expect( - FakeMatrixApi.api['PUT']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('getRoomKeyBySessionId', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final ret = await matrixApi.getRoomKeyBySessionId(roomId, sessionId, '5'); - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('deleteRoomKeyBySessionId', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final ret = - await matrixApi.deleteRoomKeyBySessionId(roomId, sessionId, '5'); - expect( - FakeMatrixApi.api['DELETE']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}/${Uri.encodeComponent('ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU')}?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('putRoomKeysByRoomId', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final session = RoomKeyBackup.fromJson({ - 'sessions': { - sessionId: { - 'first_message_index': 0, - 'forwarded_count': 0, - 'is_verified': true, - 'session_data': { - 'ephemeral': 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', - 'ciphertext': - '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', - 'mac': 'QzKV/fgAs4U', - }, - }, - }, - }); - final ret = await matrixApi.putRoomKeysByRoomId(roomId, '5', session); - expect( - FakeMatrixApi.api['PUT']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('getRoomKeysByRoomId', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final ret = await matrixApi.getRoomKeysByRoomId(roomId, '5'); - expect( - FakeMatrixApi.api['GET']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('deleteRoomKeysByRoomId', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final ret = await matrixApi.deleteRoomKeysByRoomId(roomId, '5'); - expect( - FakeMatrixApi.api['DELETE']![ - '/client/v3/room_keys/keys/${Uri.encodeComponent('!726s6s6q:example.com')}?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('putRoomKeys', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final roomId = '!726s6s6q:example.com'; - final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; - final session = RoomKeys.fromJson({ - 'rooms': { - roomId: { - 'sessions': { - sessionId: { - 'first_message_index': 0, - 'forwarded_count': 0, - 'is_verified': true, - 'session_data': { - 'ephemeral': 'fwRxYh+seqLykz5mQCLypJ4/59URdcFJ2s69OU1dGRc', - 'ciphertext': - '19jkQYlbgdP+VL9DH3qY/Dvpk6onJZgf+6frZFl1TinPCm9OMK9AZZLuM1haS9XLAUK1YsREgjBqfl6T+Tq8JlJ5ONZGg2Wttt24sGYc0iTMZJ8rXcNDeKMZhM96ETyjufJSeYoXLqifiVLDw9rrVBmNStF7PskYp040em+0OZ4pF85Cwsdf7l9V7MMynzh9BoXqVUCBiwT03PNYH9AEmNUxXX+6ZwCpe/saONv8MgGt5uGXMZIK29phA3D8jD6uV/WOHsB8NjHNq9FrfSEAsl+dAcS4uiYie4BKSSeQN+zGAQqu1MMW4OAdxGOuf8WpIINx7n+7cKQfxlmc/Cgg5+MmIm2H0oDwQ+Xu7aSxp1OCUzbxQRdjz6+tnbYmZBuH0Ov2RbEvC5tDb261LRqKXpub0llg5fqKHl01D0ahv4OAQgRs5oU+4mq+H2QGTwIFGFqP9tCRo0I+aICawpxYOfoLJpFW6KvEPnM2Lr3sl6Nq2fmkz6RL5F7nUtzxN8OKazLQpv8DOYzXbi7+ayEsqS0/EINetq7RfCqgjrEUgfNWYuFXWqvUT8lnxLdNu+8cyrJqh1UquFjXWTw1kWcJ0pkokVeBtK9YysCnF1UYh/Iv3rl2ZoYSSLNtuvMSYlYHggZ8xV8bz9S3X2/NwBycBiWIy5Ou/OuSX7trIKgkkmda0xjBWEM1a2acVuqu2OFbMn2zFxm2a3YwKP//OlIgMg', - 'mac': 'QzKV/fgAs4U', - }, - }, - }, - }, - }, - }); - final ret = await matrixApi.putRoomKeys('5', session); - expect( - FakeMatrixApi.api['PUT']!['/client/v3/room_keys/keys?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('getRoomKeys', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final ret = await matrixApi.getRoomKeys('5'); - expect( - FakeMatrixApi.api['GET']!['/client/v3/room_keys/keys?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('deleteRoomKeys', () async { - matrixApi.homeserver = Uri.parse('https://fakeserver.notexisting'); - matrixApi.accessToken = '1234'; - - final ret = await matrixApi.deleteRoomKeys('5'); - expect( - FakeMatrixApi.api['DELETE']!['/client/v3/room_keys/keys?version=5']! - .call(emptyRequest), - ret.toJson()); - }); - test('AuthenticationData', () { - final json = {'session': '1234', 'type': 'm.login.dummy'}; - expect(AuthenticationData.fromJson(json).toJson(), json); - expect( - AuthenticationData(session: '1234', type: 'm.login.dummy').toJson(), - json); - }); - test('AuthenticationRecaptcha', () { - final json = { - 'session': '1234', - 'type': 'm.login.recaptcha', - 'response': 'a', - }; - expect(AuthenticationRecaptcha.fromJson(json).toJson(), json); - expect(AuthenticationRecaptcha(session: '1234', response: 'a').toJson(), - json); - }); - test('AuthenticationToken', () { - final json = { - 'session': '1234', - 'type': 'm.login.token', - 'token': 'a', - 'txn_id': '1' - }; - expect(AuthenticationToken.fromJson(json).toJson(), json); - expect( - AuthenticationToken(session: '1234', token: 'a', txnId: '1').toJson(), - json); - }); - test('AuthenticationThreePidCreds', () { - final json = { - 'type': 'm.login.email.identity', - 'threepid_creds': { - 'sid': '1', - 'client_secret': 'a', - 'id_server': 'matrix.org', - 'id_access_token': 'a', - }, - 'session': '1', - }; - expect(AuthenticationThreePidCreds.fromJson(json).toJson(), json); - expect( - AuthenticationThreePidCreds( - session: '1', - type: AuthenticationTypes.emailIdentity, - threepidCreds: ThreepidCreds( - sid: '1', - clientSecret: 'a', - idServer: 'matrix.org', - idAccessToken: 'a', - ), - ).toJson(), - json); - }); - test('AuthenticationIdentifier', () { - final json = {'type': 'm.id.user'}; - expect(AuthenticationIdentifier.fromJson(json).toJson(), json); - expect(AuthenticationIdentifier(type: 'm.id.user').toJson(), json); - }); - test('AuthenticationPassword', () { - final json = { - 'type': 'm.login.password', - 'identifier': {'type': 'm.id.user', 'user': 'a'}, - 'password': 'a', - 'session': '1', - }; - expect(AuthenticationPassword.fromJson(json).toJson(), json); - expect( - AuthenticationPassword( - session: '1', - password: 'a', - identifier: AuthenticationUserIdentifier(user: 'a'), - ).toJson(), - json); - json['identifier'] = { - 'type': 'm.id.thirdparty', - 'medium': 'a', - 'address': 'a', - }; - expect(AuthenticationPassword.fromJson(json).toJson(), json); - expect( - AuthenticationPassword( - session: '1', - password: 'a', - identifier: - AuthenticationThirdPartyIdentifier(medium: 'a', address: 'a'), - ).toJson(), - json); - json['identifier'] = { - 'type': 'm.id.phone', - 'country': 'a', - 'phone': 'a', - }; - expect(AuthenticationPassword.fromJson(json).toJson(), json); - expect( - AuthenticationPassword( - session: '1', - password: 'a', - identifier: AuthenticationPhoneIdentifier(country: 'a', phone: 'a'), - ).toJson(), - json); - }); - }); -} diff --git a/test/try_get_map_extension_test.dart b/test/try_get_map_extension_test.dart deleted file mode 100644 index 9f1a51d2..00000000 --- a/test/try_get_map_extension_test.dart +++ /dev/null @@ -1,52 +0,0 @@ -/* MIT License -* -* Copyright (C) 2019, 2020, 2021 Famedly GmbH -* -* 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. -*/ - -import 'package:test/test.dart'; - -import 'package:matrix_api_lite/matrix_api_lite.dart'; - -void main() { - group('Try-get-map-extension', () { - Logs().level = Level.verbose; - test('it should work', () { - final data = { - 'str': 'foxies', - 'int': 42, - 'list': [2, 3, 4], - 'map': { - 'beep': 'boop', - }, - }; - expect(data.tryGet('str'), 'foxies'); - expect(data.tryGet('str'), null); - expect(data.tryGet('int'), 42); - expect(data.tryGet>('list'), [2, 3, 4]); - expect(data.tryGetMap('map')?.tryGet('beep'), - 'boop'); - expect( - data.tryGetMap('map')?.tryGet('meep'), null); - expect( - data.tryGetMap('pam')?.tryGet('beep'), null); - }); - }); -}