summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHubert Chathi <hubert@uhoreg.ca>2019-10-09 19:56:28 -0400
committerHubert Chathi <hubert@uhoreg.ca>2019-10-09 20:00:07 -0400
commit6c3f5e01daa5ce7212f1e48f5d678835f8e6cfd2 (patch)
tree8ca55cbfa7424e9f85b2d0eae76b34dc4c929cf2
parentremove some logging lines (diff)
add some documentation and move room functions to a separate submodule
-rw-r--r--lib/polyjuice/client.ex182
-rw-r--r--lib/polyjuice/client/room.ex151
-rw-r--r--lib/polyjuice/client/storage.ex2
-rw-r--r--lib/polyjuice/client/sync.ex2
-rw-r--r--test/polyjuice/client/room_test.exs (renamed from test/polyjuice/client_test.exs)34
5 files changed, 222 insertions, 149 deletions
diff --git a/lib/polyjuice/client.ex b/lib/polyjuice/client.ex
index 0c60241..93b672b 100644
--- a/lib/polyjuice/client.ex
+++ b/lib/polyjuice/client.ex
@@ -15,12 +15,38 @@
defmodule Polyjuice.Client do
@moduledoc """
Matrix client functions.
+
+ The struct in this module, or any struct that implements the
+ `Polyjuice.Client.API` protocol, can be used to connect to a Matrix server
+ using the functions from submodules.
+
+ - `Polyjuice.Client.Filter`: build filters for use with sync
+ - `Polyjuice.Client.Room`: interact with rooms, such as sending messages
+ - `Polyjuice.Client.MsgBuilder`: build message contents
+
+ To sync with the homeserver, start a process using the child spec returned by
+ `Polyjuice.Client.API.sync_child_spec/3`.
+
"""
require Logger
+ @typedoc """
+ Matrix client data.
+
+ - `base_url` (string): Required. The base URL for the homeserver.
+ - `access_token` (string): Required to call endpoints that require an
+ authenticated user. The user's access token.
+ - `user_id` (string): Required for some endpoints and for sync. The user's
+ Matrix ID.
+ - `storage` (`Polyjuice.Client.Storage`): Required for some endpoints and for
+ sync. Storage for the client.
+
+ """
@type t :: %__MODULE__{
base_url: String.t(),
- access_token: String.t()
+ access_token: String.t(),
+ user_id: String.t(),
+ storage: Polyjuice.Client.Storage.t()
}
@enforce_keys [:base_url]
@@ -42,8 +68,10 @@ defmodule Polyjuice.Client do
"""
@doc """
- Call a Matrix client API. This is a lower-level function; generally, clients
- will want to call one of the higher-level functions from `Polyjuice.Client`.
+ Call a Matrix client API.
+
+ This is a lower-level function; generally, clients will want to call one of
+ the higher-level functions from `Polyjuice.Client`.
"""
@spec call(
client_api :: Polyjuice.Client.API.t(),
@@ -59,10 +87,26 @@ defmodule Polyjuice.Client do
@doc """
Get the child spec for the sync process.
+
+ `listener` will receive messages with the sync results. Messages include:
+
+ - `{:connected}`: the process has connected to the homeserver
+ - `{:disconnected}`: the process has been disconnected from the homeserver
+ - `{:initial_sync_completed}`: the first sync has completed
+ - `{:limited, room_id, prev_batch}`: a room's timeline has been limited.
+ Previous messages can be fetched using the `prev_batch`
+ - `{:message, room_id, event}`: a message event has been received
+ - `{:state, room_id, event}`: a state event has been received
+ - `{:invite, room_id, inviter, invite_state}`: the user was invited to a room
+ - `{:left, room_id}`: the user left a room
+
+ `opts` is a keyword list of options:
+
+ - `filter:` (string or map) the filter to use with the sync
"""
@spec sync_child_spec(
client_api :: Polyjuice.Client.API.t(),
- listener :: pid() | fun(),
+ listener :: pid(),
opts :: list()
) :: map()
def sync_child_spec(client_api, listener, opts \\ [])
@@ -110,134 +154,4 @@ defmodule Polyjuice.Client do
Polyjuice.Client.Sync.child_spec([client, listener | opts])
end
end
-
- @doc """
- Send a message to a room.
-
- `msg` can either be anything that implements the
- `Polyjuice.Client.MsgBuilder.MsgData` protocol (which will be sent as an
- `m.message`), or a map (which specifies the full message content).
-
- Examples:
-
- Polyjuice.Client.send_message(client, "text message", "!room_id")
-
- Polyjuice.Client.send_message(
- client,
- {"message with formatting", "<i>message</i> with <b>formatting</b>"},
- "!room_id"
- )
-
- Polyjuice.Client.send_message(
- client,
- ["Hello, ", Polyjuice.Client.MsgBuilder.mention("@world:example.com")],
- "!room_id"
- )
-
- Polyjuice.Client.send_message(
- client,
- %{"msgtype" => "m.notice", "body" => "using full message content"},
- "!room_id"
- )
-
- """
- @spec send_message(
- client_api :: Polyjuice.Client.API.t(),
- msg :: map | Polyjuice.Client.MsgBuilder.MsgData.t(),
- room :: String.t()
- ) :: String.t()
- def send_message(client_api, msg, room) when is_binary(room) do
- cond do
- Polyjuice.Client.MsgBuilder.MsgData.impl_for(msg) != nil ->
- Polyjuice.Client.API.call(
- client_api,
- %Polyjuice.Client.Endpoint.PutRoomsSend{
- txn_id: Polyjuice.Client.API.transaction_id(client_api),
- room: room,
- event_type: "m.room.message",
- message: Polyjuice.Client.MsgBuilder.to_message(msg)
- }
- )
-
- is_map(msg) and not Map.has_key?(msg, :__struct__) ->
- Polyjuice.Client.API.call(
- client_api,
- %Polyjuice.Client.Endpoint.PutRoomsSend{
- txn_id: Polyjuice.Client.API.transaction_id(client_api),
- room: room,
- event_type: "m.room.message",
- message: msg
- }
- )
-
- true ->
- raise ArgumentError, message: "invalid argument msg"
- end
- end
-
- @doc """
- Send an event to a room.
- """
- @spec send_event(
- client_api :: Polyjuice.Client.API.t(),
- event_type :: String.t(),
- event :: map,
- room :: String.t()
- ) :: String.t()
- def send_event(client_api, event_type, event, room)
- when is_binary(event_type) and is_map(event) and is_binary(room) do
- Polyjuice.Client.API.call(
- client_api,
- %Polyjuice.Client.Endpoint.PutRoomsSend{
- txn_id: Polyjuice.Client.API.transaction_id(client_api),
- room: room,
- event_type: event_type,
- message: event
- }
- )
- end
-
- @doc """
- Update the client's read receipt (of the given type) to the given message in the
- given room.
- """
- @spec update_read_receipt(
- client_api :: Polyjuice.Client.API.t(),
- room :: String.t(),
- event_id :: String.t(),
- receipt_type :: String.t()
- ) :: Any
- def update_read_receipt(client_api, room, event_id, receipt_type \\ "m.read")
- when is_binary(room) and is_binary(event_id) and is_binary(receipt_type) do
- Polyjuice.Client.API.call(
- client_api,
- %Polyjuice.Client.Endpoint.PostRoomsReceipt{
- room: room,
- event_id: event_id,
- receipt_type: receipt_type
- }
- )
- end
-
- @doc """
- Join a room.
- """
- @spec join_room(
- client_api :: Polyjuice.Client.API.t(),
- room :: String.t(),
- servers :: list(String.t()),
- third_party_join :: map | nil
- ) :: Any
- def join_room(client_api, room, servers \\ [], third_party_signed \\ nil)
- when is_binary(room) and is_list(servers) and
- (is_map(third_party_signed) or third_party_signed == nil) do
- Polyjuice.Client.API.call(
- client_api,
- %Polyjuice.Client.Endpoint.PostJoin{
- room: room,
- servers: servers,
- third_party_signed: third_party_signed
- }
- )
- end
end
diff --git a/lib/polyjuice/client/room.ex b/lib/polyjuice/client/room.ex
new file mode 100644
index 0000000..f93bfd6
--- /dev/null
+++ b/lib/polyjuice/client/room.ex
@@ -0,0 +1,151 @@
+# Copyright 2019 Hubert Chathi <hubert@uhoreg.ca>
+#
+# 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.Room do
+ @moduledoc """
+ Room-related functions.
+
+ """
+ require Logger
+
+ @doc """
+ Send a message to a room.
+
+ `msg` can either be anything that implements the
+ `Polyjuice.Client.MsgBuilder.MsgData` protocol (which will be sent as an
+ `m.message`), or a map (which specifies the full message content).
+
+ Examples:
+
+ Polyjuice.Client.Room.send_message(client, "text message", "!room_id")
+
+ Polyjuice.Client.Room.send_message(
+ client,
+ {"message with formatting", "<i>message</i> with <b>formatting</b>"},
+ "!room_id"
+ )
+
+ Polyjuice.Client.Room.send_message(
+ client,
+ ["Hello, ", Polyjuice.Client.MsgBuilder.mention("@world:example.com")],
+ "!room_id"
+ )
+
+ Polyjuice.Client.Room.send_message(
+ client,
+ %{"msgtype" => "m.notice", "body" => "using full message content"},
+ "!room_id"
+ )
+
+ """
+ @spec send_message(
+ client_api :: Polyjuice.Client.API.t(),
+ room :: String.t(),
+ msg :: map | Polyjuice.Client.MsgBuilder.MsgData.t()
+ ) :: String.t()
+ def send_message(client_api, room, msg) when is_binary(room) do
+ cond do
+ Polyjuice.Client.MsgBuilder.MsgData.impl_for(msg) != nil ->
+ Polyjuice.Client.API.call(
+ client_api,
+ %Polyjuice.Client.Endpoint.PutRoomsSend{
+ txn_id: Polyjuice.Client.API.transaction_id(client_api),
+ room: room,
+ event_type: "m.room.message",
+ message: Polyjuice.Client.MsgBuilder.to_message(msg)
+ }
+ )
+
+ is_map(msg) and not Map.has_key?(msg, :__struct__) ->
+ Polyjuice.Client.API.call(
+ client_api,
+ %Polyjuice.Client.Endpoint.PutRoomsSend{
+ txn_id: Polyjuice.Client.API.transaction_id(client_api),
+ room: room,
+ event_type: "m.room.message",
+ message: msg
+ }
+ )
+
+ true ->
+ raise ArgumentError, message: "invalid argument msg"
+ end
+ end
+
+ @doc """
+ Send an event to a room.
+ """
+ @spec send_event(
+ client_api :: Polyjuice.Client.API.t(),
+ room :: String.t(),
+ event_type :: String.t(),
+ event :: map
+ ) :: String.t()
+ def send_event(client_api, room, event_type, event)
+ when is_binary(event_type) and is_map(event) and is_binary(room) do
+ Polyjuice.Client.API.call(
+ client_api,
+ %Polyjuice.Client.Endpoint.PutRoomsSend{
+ txn_id: Polyjuice.Client.API.transaction_id(client_api),
+ room: room,
+ event_type: event_type,
+ message: event
+ }
+ )
+ end
+
+ @doc """
+ Update the client's read receipt (of the given type) to the given message in the
+ given room.
+ """
+ @spec update_read_receipt(
+ client_api :: Polyjuice.Client.API.t(),
+ room :: String.t(),
+ event_id :: String.t(),
+ receipt_type :: String.t()
+ ) :: Any
+ def update_read_receipt(client_api, room, event_id, receipt_type \\ "m.read")
+ when is_binary(room) and is_binary(event_id) and is_binary(receipt_type) do
+ Polyjuice.Client.API.call(
+ client_api,
+ %Polyjuice.Client.Endpoint.PostRoomsReceipt{
+ room: room,
+ event_id: event_id,
+ receipt_type: receipt_type
+ }
+ )
+ end
+
+ @doc """
+ Join a room.
+ """
+ @spec join(
+ client_api :: Polyjuice.Client.API.t(),
+ room :: String.t(),
+ servers :: list(String.t()),
+ third_party_join :: map | nil
+ ) :: Any
+ def join(client_api, room, servers \\ [], third_party_signed \\ nil)
+ when is_binary(room) and is_list(servers) and
+ (is_map(third_party_signed) or third_party_signed == nil) do
+ Polyjuice.Client.API.call(
+ client_api,
+ %Polyjuice.Client.Endpoint.PostJoin{
+ room: room,
+ servers: servers,
+ third_party_signed: third_party_signed
+ }
+ )
+ end
+end
diff --git a/lib/polyjuice/client/storage.ex b/lib/polyjuice/client/storage.ex
index 3f5e26d..9172e5b 100644
--- a/lib/polyjuice/client/storage.ex
+++ b/lib/polyjuice/client/storage.ex
@@ -55,7 +55,7 @@ defprotocol Polyjuice.Client.Storage do
def set_filter_id(storage, filter, filter_id)
@doc """
- Get the ID stored for a filter, or `nil' if no ID has been stored.
+ Get the ID stored for a filter, or `nil` if no ID has been stored.
"""
@spec get_filter_id(storage :: __MODULE__.t(), filter :: map) :: String.t() | nil
def get_filter_id(storage, filter)
diff --git a/lib/polyjuice/client/sync.ex b/lib/polyjuice/client/sync.ex
index 4bd1a72..70f357c 100644
--- a/lib/polyjuice/client/sync.ex
+++ b/lib/polyjuice/client/sync.ex
@@ -302,7 +302,7 @@ defmodule Polyjuice.Client.Sync do
if Map.get(timeline, "limited", false) do
with {:ok, prev_batch} <- Map.get(timeline, "prev_batch") do
- send(state.listener, {:limited, room, prev_batch})
+ send(state.listener, {:limited, roomname, prev_batch})
end
end
diff --git a/test/polyjuice/client_test.exs b/test/polyjuice/client/room_test.exs
index 7c25bc4..36d80cb 100644
--- a/test/polyjuice/client_test.exs
+++ b/test/polyjuice/client/room_test.exs
@@ -12,9 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-defmodule Polyjuice.ClientTest do
+defmodule Polyjuice.Client.RoomTest do
use ExUnit.Case
- doctest Polyjuice.Client
+ doctest Polyjuice.Client.Room
test "send message" do
with client = %DummyClient{
@@ -31,7 +31,7 @@ defmodule Polyjuice.ClientTest do
{:ok, "$foo1"}
}
} do
- {:ok, event_id} = Polyjuice.Client.send_message(client, "foo", "!bar")
+ {:ok, event_id} = Polyjuice.Client.Room.send_message(client, "!bar", "foo")
assert event_id == "$foo1"
end
@@ -51,7 +51,7 @@ defmodule Polyjuice.ClientTest do
{:ok, "$foo2"}
}
} do
- {:ok, event_id} = Polyjuice.Client.send_message(client, {"foo", "<i>foo</i>"}, "!bar")
+ {:ok, event_id} = Polyjuice.Client.Room.send_message(client, "!bar", {"foo", "<i>foo</i>"})
assert event_id == "$foo2"
end
@@ -70,16 +70,24 @@ defmodule Polyjuice.ClientTest do
}
} do
{:ok, event_id} =
- Polyjuice.Client.send_message(client, %{"msgtype" => "m.notice", "body" => "foo"}, "!bar")
+ Polyjuice.Client.Room.send_message(client, "!bar", %{
+ "msgtype" => "m.notice",
+ "body" => "foo"
+ })
assert event_id == "$foo3"
# trying to send a non-msgdata should error
- assert_raise ArgumentError, fn -> Polyjuice.Client.send_message(client, 1, "!bar") end
- assert_raise ArgumentError, fn -> Polyjuice.Client.send_message(client, client, "!bar") end
+ assert_raise ArgumentError, fn ->
+ Polyjuice.Client.Room.send_message(client, "!bar", 1)
+ end
+
+ assert_raise ArgumentError, fn ->
+ Polyjuice.Client.Room.send_message(client, "!bar", client)
+ end
assert_raise FunctionClauseError, fn ->
- Polyjuice.Client.send_message(client, {"a"}, "!bar")
+ Polyjuice.Client.Room.send_message(client, "!bar", {"a"})
end
end
end
@@ -100,11 +108,11 @@ defmodule Polyjuice.ClientTest do
}
} do
{:ok, event_id} =
- Polyjuice.Client.send_event(
+ Polyjuice.Client.Room.send_event(
client,
+ "!bar",
"m.room.message",
- %{"msgtype" => "m.text", "body" => "foo"},
- "!bar"
+ %{"msgtype" => "m.text", "body" => "foo"}
)
assert event_id == "$foo1"
@@ -122,8 +130,8 @@ defmodule Polyjuice.ClientTest do
{:ok}
}
} do
- {:ok} = Polyjuice.Client.update_read_receipt(client, "!room", "$event", "m.read")
- {:ok} = Polyjuice.Client.update_read_receipt(client, "!room", "$event")
+ {:ok} = Polyjuice.Client.Room.update_read_receipt(client, "!room", "$event", "m.read")
+ {:ok} = Polyjuice.Client.Room.update_read_receipt(client, "!room", "$event")
end
end
end