diff options
author | Hubert Chathi <hubert@uhoreg.ca> | 2020-12-26 18:03:58 -0500 |
---|---|---|
committer | Hubert Chathi <hubert@uhoreg.ca> | 2020-12-26 18:03:58 -0500 |
commit | 2834044f508f3210c43cbc116a96f25d047e5069 (patch) | |
tree | 2acb5a0d7cec7b402c969d17efed10028cbb8953 | |
parent | Merge branch 'rooms_read_marker' into 'master' (diff) |
Add methods for creating rooms.
(Manual merge of https://gitlab.com/uhoreg/polyjuice_client/-/merge_requests/3)
Thanks to multi prise.
-rw-r--r-- | lib/polyjuice/client/endpoint/post_create_room.ex | 96 | ||||
-rw-r--r-- | lib/polyjuice/client/endpoint/put_room_alias.ex | 58 | ||||
-rw-r--r-- | lib/polyjuice/client/room.ex | 83 | ||||
-rw-r--r-- | test/polyjuice/client/endpoint/post_create_room_test.exs | 122 | ||||
-rw-r--r-- | test/polyjuice/client/endpoint/put_room_alias.exs | 52 | ||||
-rw-r--r-- | test/polyjuice/client/room_test.exs | 41 |
6 files changed, 452 insertions, 0 deletions
diff --git a/lib/polyjuice/client/endpoint/post_create_room.ex b/lib/polyjuice/client/endpoint/post_create_room.ex new file mode 100644 index 0000000..8da0abd --- /dev/null +++ b/lib/polyjuice/client/endpoint/post_create_room.ex @@ -0,0 +1,96 @@ +# Copyright 2020 Multi Prise <multiestunhappydev@gmail.com> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +defmodule Polyjuice.Client.Endpoint.PostCreateRoom do + @moduledoc """ + Create a room with various configuration options + https://matrix.org/docs/spec/client_server/r0.5.0#post-matrix-client-r0-createroom + """ + + @type invite3pid :: %{ + id_server: String.t(), + id_access_token: String.t(), + medium: String.t() + } + + @type state_event :: %{ + type: String.t(), + state_key: String.t(), + content: map() + } + + @type t :: %__MODULE__{ + visibility: :private | :public, + room_alias_name: String.t() | nil, + name: String.t() | nil, + topic: String.t() | nil, + invite: list(String.t()), + invite_3pid: list(invite3pid()), + room_version: String.t() | nil, + creation_content: map() | nil, + initial_state: list(state_event()), + preset: :private_chat | :public_chat | :trusted_private_chat | nil, + is_direct: boolean(), + power_level_content_override: map() | nil + } + + @enforce_keys [] + + defstruct [ + :visibility, + :room_alias_name, + :name, + :topic, + :creation_content, + :preset, + :is_direct, + :power_level_content_override, + invite: [], + invite_3pid: [], + room_version: nil, + initial_state: [] + ] + + defimpl Polyjuice.Client.Endpoint.Proto do + def http_spec(%Polyjuice.Client.Endpoint.PostCreateRoom{} = create_room_struct) do + body = + create_room_struct + |> Map.from_struct() + |> Enum.reject(fn {_, v} -> is_nil(v) || v == [] end) + |> Map.new() + |> Jason.encode_to_iodata!() + + Polyjuice.Client.Endpoint.HttpSpec.post( + :r0, + "createRoom", + headers: [ + {"Accept", "application/json"}, + {"Content-Type", "application/json"} + ], + body: body, + auth_required: true + ) + end + + def transform_http_result(req, status_code, resp_headers, body) do + Polyjuice.Client.Endpoint.parse_response(req, status_code, resp_headers, body) + end + + defimpl Polyjuice.Client.Endpoint.BodyParser do + def parse(_req, parsed) do + {:ok, Map.get(parsed, "room_id")} + end + end + end +end diff --git a/lib/polyjuice/client/endpoint/put_room_alias.ex b/lib/polyjuice/client/endpoint/put_room_alias.ex new file mode 100644 index 0000000..28ae18f --- /dev/null +++ b/lib/polyjuice/client/endpoint/put_room_alias.ex @@ -0,0 +1,58 @@ +# Copyright 2020 Multi Prise <multiestunhappydev@gmail.com> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +defmodule Polyjuice.Client.Endpoint.PutRoomAlias do + @moduledoc """ + Create a new mapping from room alias to room ID. + https://matrix.org/docs/spec/client_server/latest#put-matrix-client-r0-directory-room-roomalias + """ + + @type t :: %__MODULE__{ + room_id: String.t(), + room_alias: String.t() + } + + @enforce_keys [] + + defstruct [ + :room_id, + :room_alias + ] + + defimpl Polyjuice.Client.Endpoint.Proto do + def http_spec(%Polyjuice.Client.Endpoint.PutRoomAlias{ + room_id: room_id, + room_alias: room_alias + }) do + body = + %{room_id: room_id} + |> Jason.encode!() + + Polyjuice.Client.Endpoint.HttpSpec.put( + :r0, + "directory/room/#{URI.encode_www_form(room_alias)}", + headers: [ + {"Accept", "application/json"}, + {"Content-Type", "application/json"} + ], + body: body, + auth_required: false + ) + end + + def transform_http_result(req, status_code, resp_headers, body) do + Polyjuice.Client.Endpoint.parse_response(req, status_code, resp_headers, body) + end + end +end diff --git a/lib/polyjuice/client/room.ex b/lib/polyjuice/client/room.ex index 7435244..26317ae 100644 --- a/lib/polyjuice/client/room.ex +++ b/lib/polyjuice/client/room.ex @@ -362,4 +362,87 @@ defmodule Polyjuice.Client.Room do } ) end + + @doc """ + Create a new room with various configuration options and return a room_id on + success. + `options` is a keyword list of options. Recognized options are: + - `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. + - `room_alias_name`: The desired room alias local part. + - `name`: If this is included, an m.room.name event will be sent into the room + to indicate the name of the room. + - `topic`: if this is included, an m.room.topic event will be sent into the + room to indicate the topic for the room + - `invite`: a list of user IDs to invite to the room + - `invite_3pid`: a list of objects representing third party IDs to invite into + the room. Map made of + - `id_server`: 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 + - `address`: The invitee's third party identifier + - `room_version`: 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. + - `creation_content`: extra keys, such as m.federate, to be added to the + content of the m.room.create event + - `initial_state`: 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 + - `type`: the type of event to send + - `state_key`: The state_key of the state event. Defaults to an empty string. + - `content`: the content of the event + - `preset`: the preset corresponding to the join rules. There are three options: + `:private_chat` which means that only invited users (including guest users) + may join, `:trusted_private_chat` works as the previous but all invited + users have the same power level as the room creator, and `:public_chat` is + for public access, with guest access forbidden. + - `is_direct`: 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` + - `power_level_content_override`: 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` event content prior to it being sent to the room. + Defaults to overriding nothing. + + """ + @spec create_room( + client_api :: Polyjuice.Client.API.t(), + options :: Keyword.t() + ) :: {:ok, String.t()} | Any + def create_room(client_api, options \\ []) do + Polyjuice.Client.API.call( + client_api, + struct(%Polyjuice.Client.Endpoint.PostCreateRoom{}, options) + ) + end + + @doc """ + This function allow to five a alias to a room + it takes: + `room`: a string representing the room id + `room_alias`: a string representing the new room alias + """ + @spec create_alias( + client_api :: Polyjuice.Client.API.t(), + room :: String.t(), + room_alias :: String.t() + ) :: {:ok, String.t()} | Any + def create_alias(client_api, room, room_alias) do + room_alias = + case String.at(room_alias, 0) do + "#" -> room_alias + _ -> "#" <> room_alias + end + + Polyjuice.Client.API.call( + client_api, + %Polyjuice.Client.Endpoint.PutRoomAlias{ + room_id: room, + room_alias: room_alias + } + ) + end end diff --git a/test/polyjuice/client/endpoint/post_create_room_test.exs b/test/polyjuice/client/endpoint/post_create_room_test.exs new file mode 100644 index 0000000..c42ee25 --- /dev/null +++ b/test/polyjuice/client/endpoint/post_create_room_test.exs @@ -0,0 +1,122 @@ +# Copyright 2020 Multi Prise <multiestunhappydev@gmail.com> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +defmodule Polyjuice.Client.Endpoint.PostCreateRoomTest do + use ExUnit.Case + + test "POST /_matrix/client/r0/createRoom with empty variables" do + endpoint = %Polyjuice.Client.Endpoint.PostCreateRoom{} + + http_spec = Polyjuice.Client.Endpoint.Proto.http_spec(endpoint) + + assert %{http_spec | body: nil} == %Polyjuice.Client.Endpoint.HttpSpec{ + auth_required: true, + body: nil, + headers: [ + {"Accept", "application/json"}, + {"Content-Type", "application/json"} + ], + method: :post, + path: "_matrix/client/r0/createRoom" + } + + assert Polyjuice.Client.Endpoint.Proto.transform_http_result( + endpoint, + 200, + [{"Content-Type", "application/json"}], + ~s({"room_id":"!room"}) + ) == {:ok, %{"room_id" => "!room"}} + + assert Polyjuice.Client.Endpoint.Proto.transform_http_result( + endpoint, + 500, + [], + "Aaah!" + ) == + {:error, 500, %{"body" => "Aaah!", "errcode" => "CA_UHOREG_POLYJUICE_BAD_RESPONSE"}} + end + + test "POST /_matrix/client/r0/createRoom with all variables" do + endpoint = %Polyjuice.Client.Endpoint.PostCreateRoom{ + visibility: "public", + room_alias_name: "#foo", + name: "super fofo", + topic: "about foo", + invite: [], + invite_3pid: [], + room_version: "3", + creation_content: %{ + "m.federate": false + }, + initial_state: [], + preset: :private_chat, + is_direct: true, + power_level_content_override: %{ + ban: 50, + events: %{ + "m.room.name": 100, + "m.room.power_levels": 100 + } + } + } + + http_spec = Polyjuice.Client.Endpoint.Proto.http_spec(endpoint) + + assert %{http_spec | body: nil} == %Polyjuice.Client.Endpoint.HttpSpec{ + auth_required: true, + body: nil, + headers: [ + {"Accept", "application/json"}, + {"Content-Type", "application/json"} + ], + method: :post, + path: "_matrix/client/r0/createRoom" + } + + assert Jason.decode!(http_spec.body) == %{ + "visibility" => "public", + "room_alias_name" => "#foo", + "name" => "super fofo", + "topic" => "about foo", + "room_version" => "3", + "creation_content" => %{ + "m.federate" => false + }, + "preset" => "private_chat", + "is_direct" => true, + "power_level_content_override" => %{ + "ban" => 50, + "events" => %{ + "m.room.name" => 100, + "m.room.power_levels" => 100 + } + } + } + + assert Polyjuice.Client.Endpoint.Proto.transform_http_result( + endpoint, + 200, + [{"Content-Type", "application/json"}], + ~s({"room_id":"!room"}) + ) == {:ok, %{"room_id" => "!room"}} + + assert Polyjuice.Client.Endpoint.Proto.transform_http_result( + endpoint, + 500, + [], + "Aaah!" + ) == + {:error, 500, %{"body" => "Aaah!", "errcode" => "CA_UHOREG_POLYJUICE_BAD_RESPONSE"}} + end +end diff --git a/test/polyjuice/client/endpoint/put_room_alias.exs b/test/polyjuice/client/endpoint/put_room_alias.exs new file mode 100644 index 0000000..203a7ab --- /dev/null +++ b/test/polyjuice/client/endpoint/put_room_alias.exs @@ -0,0 +1,52 @@ +# Copyright 2020 Multi Prise <multiestunhappydev@gmail.com> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +defmodule Polyjuice.Client.Endpoint.PutRoomAliasTest do + use ExUnit.Case + + test "PUT room/{room_alias}" do + endpoint = %Polyjuice.Client.Endpoint.PutRoomsSend{ + room: "!room_id", + room_alias: "!room_alias" + } + + http_spec = Polyjuice.Client.Endpoint.Proto.http_spec(endpoint) + + assert TestUtil.http_spec_body_to_binary(http_spec) == %Polyjuice.Client.Endpoint.HttpSpec{ + auth_required: true, + body: ~s({"body":"Hello World!"}), + headers: [ + {"Accept", "application/json"}, + {"Content-Type", "application/json"} + ], + method: :put, + url: "https://example.com/_matrix/client/r0/room/%21room_alias" + } + + assert Polyjuice.Client.Endpoint.Proto.transform_http_result( + endpoint, + 200, + [{"Content-Type", "application/json"}], + "{\"room_id\": \"$foo1\", \"room_alias\": \"$bar\"}" + ) == {:ok, "$bar:exampke.com"} + + assert Polyjuice.Client.Endpoint.Proto.transform_http_result( + endpoint, + 500, + [], + "Aaah!" + ) == + {:error, 500, %{"body" => "Aaah!", "errcode" => "CA_UHOREG_POLYJUICE_BAD_RESPONSE"}} + end +end diff --git a/test/polyjuice/client/room_test.exs b/test/polyjuice/client/room_test.exs index 349ac54..115ab30 100644 --- a/test/polyjuice/client/room_test.exs +++ b/test/polyjuice/client/room_test.exs @@ -378,4 +378,45 @@ defmodule Polyjuice.Client.RoomTest do Polyjuice.Client.API.stop(client) end end + + test "create_room" do + with client = %DummyClient{ + response: { + %Polyjuice.Client.Endpoint.PostCreateRoom{}, + {:ok, "!room"} + } + } do + {:ok, "!room"} = Polyjuice.Client.Room.create_room(client) + end + end + + test "create alias" do + room_id = "id_roomtest:homeserver" + room_alias = "new_room_name:homeserver" + + with client = %DummyClient{ + response: { + %Polyjuice.Client.Endpoint.PutRoomAlias{ + room_id: room_id, + room_alias: "#" <> room_alias + }, + {:ok, "#" <> room_alias} + } + } do + {:ok, "#" <> room_alias} = Polyjuice.Client.Room.create_alias(client, room_id, room_alias) + end + + with client = %DummyClient{ + response: { + %Polyjuice.Client.Endpoint.PutRoomAlias{ + room_id: room_id, + room_alias: "#" <> room_alias + }, + {:ok, "#" <> room_alias} + } + } do + room_alias = "#new_room_name:homeserver" + {:ok, room_alias} = Polyjuice.Client.Room.create_alias(client, room_id, room_alias) + end + end end |