diff options
author | Hubert Chathi <hubert@uhoreg.ca> | 2020-05-12 18:39:58 -0400 |
---|---|---|
committer | Hubert Chathi <hubert@uhoreg.ca> | 2020-05-12 18:39:58 -0400 |
commit | 3bd34cf08e19d4eda8e4d722bccf7d7476ab684e (patch) | |
tree | 8522236eac895ab105c424739d5263fcfe99047c | |
parent | fix typespec (diff) |
add some more filtering methods and reduce duplicate code
-rw-r--r-- | lib/polyjuice/client/filter.ex | 281 | ||||
-rw-r--r-- | test/polyjuice/client/filter_test.exs | 63 |
2 files changed, 197 insertions, 147 deletions
diff --git a/lib/polyjuice/client/filter.ex b/lib/polyjuice/client/filter.ex index 91e0db2..fb8c6f1 100644 --- a/lib/polyjuice/client/filter.ex +++ b/lib/polyjuice/client/filter.ex @@ -128,49 +128,124 @@ defmodule Polyjuice.Client.Filter do Map.put(filter, key, put(Map.get(filter, key, %{}), rest, val)) end + defmodule Event do + @moduledoc """ + Create `EventFilter`s, `RoomEventFilter`s, `StateFilter`s, or `RoomFilter`s. + + https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-user-userid-filter + + These are filters that form part of a `Polyjuice.Client.Filter`. Not all of + the functions in here may apply to all the different types of filters. + """ + + @doc """ + Add items to a list parameter in the filter. + """ + @spec add_to_list(filter :: map, name :: String.t(), data :: list) :: map + def add_to_list(filter \\ %{}, name, data) + when is_map(filter) and is_binary(name) and is_list(data) do + Polyjuice.Client.Filter.update( + filter, + [name], + data, + &Enum.concat(&1, data) + ) + end + + @doc """ + Include certain types of events. + """ + @spec include_types(filter :: map, types :: list) :: map + def include_types(filter \\ %{}, types) when is_map(filter) and is_list(types), + do: add_to_list(filter, "types", types) + + @doc """ + Exclude certain types of events. + """ + @spec exclude_types(filter :: map, types :: list) :: map + def exclude_types(filter \\ %{}, types) when is_map(filter) and is_list(types), + do: add_to_list(filter, "not_types", types) + + @doc """ + Include certain senders. + """ + @spec include_senders(filter :: map, types :: list) :: map + def include_senders(filter \\ %{}, senders) when is_map(filter) and is_list(senders), + do: add_to_list(filter, "senders", senders) + + @doc """ + Exclude certain senders. + """ + @spec exclude_senders(filter :: map, senders :: list) :: map + def exclude_senders(filter \\ %{}, senders) when is_map(filter) and is_list(senders), + do: add_to_list(filter, "not_senders", senders) + + @doc """ + Include certain rooms. + """ + @spec include_rooms(filter :: map, rooms :: list) :: map + def include_rooms(filter \\ %{}, rooms) when is_map(filter) and is_list(rooms), + do: add_to_list(filter, "rooms", rooms) + + @doc """ + Exclude certain rooms. + """ + @spec exclude_rooms(filter :: map, rooms :: list) :: map + def exclude_rooms(filter \\ %{}, rooms) when is_map(filter) and is_list(rooms), + do: add_to_list(filter, "not_rooms", rooms) + + @doc """ + Set the maximum number of events to return. + """ + @spec limit(filter :: map, limit :: integer) :: map + def limit(filter \\ %{}, limit) when is_map(filter) and is_integer(limit), + do: Map.put(filter, "limit", limit) + + @doc """ + Set whether to include or exclude events that have a URL. + + If `flag` is `true`, only events that have a `url` field will be included. + If `flag` is `false`, events that have a `url` field will be excluded. + """ + @spec contains_url(filter :: map, flag :: boolean) :: map + def contains_url(%{} = filter \\ %{}, flag) when is_map(filter) and is_boolean(flag), + do: Map.put(filter, "contains_url", flag) + end + @doc """ - Allow certain types of presence events to be included. + Update the presence filter using a function. """ - @spec include_presence_types(filter :: map, types :: list) :: map - def include_presence_types(filter \\ %{}, types) - - def include_presence_types(filter, types) when filter == %{} and is_list(types) do - %{ - "presence" => %{ - "types" => types - } - } + @spec presence(filter :: map, f :: function) :: map + def presence(filter, f) when is_function(f) do + Map.put(filter, "presence", f.(Map.get(filter, "presence", %{}))) end - def include_presence_types(filter, types) when is_map(filter) and is_list(types) do - update( - filter, - ["presence", "types"], - types, - &Enum.concat(&1, types) - ) + @doc """ + Allow certain types of presence events to be included. + """ + @spec include_presence_types(filter :: map, types :: list) :: map + def include_presence_types(filter \\ %{}, types) when is_map(filter) and is_list(types) do + presence(filter, &Polyjuice.Client.Filter.Event.include_types(&1, types)) end @doc """ Don't allow certain types of presence events. """ @spec exclude_presence_types(filter :: map, types :: list) :: map - def exclude_presence_types(filter \\ %{}, types) - - def exclude_presence_types(filter, types) when filter == %{} and is_list(types) do - %{ - "presence" => %{ - "not_types" => types - } - } + def exclude_presence_types(filter \\ %{}, types) do + presence(filter, &Polyjuice.Client.Filter.Event.exclude_types(&1, types)) end - def exclude_presence_types(filter, types) when is_map(filter) and is_list(types) do + @doc """ + Update the ephemeral filter using a function. + """ + @spec ephemeral(filter :: map, f :: function) :: map + def ephemeral(filter, f) when is_function(f) do update( filter, - ["presence", "not_types"], - types, - &Enum.concat(&1, types) + ["room", "ephemeral"], + f.(%{}), + f ) end @@ -178,49 +253,28 @@ defmodule Polyjuice.Client.Filter do Allow certain types of ephemeral room events to be included. """ @spec include_ephemeral_types(filter :: map, types :: list) :: map - def include_ephemeral_types(filter \\ %{}, types) - - def include_ephemeral_types(filter, types) when filter == %{} and is_list(types) do - %{ - "room" => %{ - "ephemeral" => %{ - "types" => types - } - } - } - end - - def include_ephemeral_types(filter, types) when is_map(filter) and is_list(types) do - update( - filter, - ["room", "ephemeral", "types"], - types, - &Enum.concat(&1, types) - ) + def include_ephemeral_types(filter \\ %{}, types) do + ephemeral(filter, &Polyjuice.Client.Filter.Event.include_types(&1, types)) end @doc """ Don't allow certain types of ephemeral room events. """ @spec exclude_ephemeral_types(filter :: map, types :: list) :: map - def exclude_ephemeral_types(filter \\ %{}, types) - - def exclude_ephemeral_types(filter, types) when filter == %{} and is_list(types) do - %{ - "room" => %{ - "ephemeral" => %{ - "not_types" => types - } - } - } + def exclude_ephemeral_types(filter \\ %{}, types) do + ephemeral(filter, &Polyjuice.Client.Filter.Event.exclude_types(&1, types)) end - def exclude_ephemeral_types(filter, types) when is_map(filter) and is_list(types) do + @doc """ + Update the state filter using a function. + """ + @spec state(filter :: map, f :: function) :: map + def state(filter, f) when is_function(f) do update( filter, - ["room", "ephemeral", "not_types"], - types, - &Enum.concat(&1, types) + ["room", "state"], + f.(%{}), + f ) end @@ -228,49 +282,28 @@ defmodule Polyjuice.Client.Filter do Allow certain types of state events to be included. """ @spec include_state_types(filter :: map, types :: list) :: map - def include_state_types(filter \\ %{}, types) - - def include_state_types(filter, types) when filter == %{} and is_list(types) do - %{ - "room" => %{ - "state" => %{ - "types" => types - } - } - } - end - - def include_state_types(filter, types) when is_map(filter) and is_list(types) do - update( - filter, - ["room", "state", "types"], - types, - &Enum.concat(&1, types) - ) + def include_state_types(filter \\ %{}, types) do + state(filter, &Polyjuice.Client.Filter.Event.include_types(&1, types)) end @doc """ Don't allow certain types of state events. """ @spec exclude_state_types(filter :: map, types :: list) :: map - def exclude_state_types(filter \\ %{}, types) - - def exclude_state_types(filter, types) when filter == %{} and is_list(types) do - %{ - "room" => %{ - "state" => %{ - "not_types" => types - } - } - } + def exclude_state_types(filter \\ %{}, types) do + state(filter, &Polyjuice.Client.Filter.Event.exclude_types(&1, types)) end - def exclude_state_types(filter, types) when is_map(filter) and is_list(types) do + @doc """ + Update the timeline filter using a function. + """ + @spec timeline(filter :: map, f :: function) :: map + def timeline(filter, f) when is_function(f) do update( filter, - ["room", "state", "not_types"], - types, - &Enum.concat(&1, types) + ["room", "timeline"], + f.(%{}), + f ) end @@ -278,70 +311,24 @@ defmodule Polyjuice.Client.Filter do Allow certain types of timeline events to be included. """ @spec include_timeline_types(filter :: map, types :: list) :: map - def include_timeline_types(filter \\ %{}, types) - - def include_timeline_types(filter, types) when filter == %{} and is_list(types) do - %{ - "room" => %{ - "timeline" => %{ - "types" => types - } - } - } - end - - def include_timeline_types(filter, types) when is_map(filter) and is_list(types) do - update( - filter, - ["room", "timeline", "types"], - types, - &Enum.concat(&1, types) - ) + def include_timeline_types(filter \\ %{}, types) do + timeline(filter, &Polyjuice.Client.Filter.Event.include_types(&1, types)) end @doc """ Don't allow certain types of timeline events. """ @spec exclude_timeline_types(filter :: map, types :: list) :: map - def exclude_timeline_types(filter \\ %{}, types) - - def exclude_timeline_types(filter, types) when filter == %{} and is_list(types) do - %{ - "room" => %{ - "timeline" => %{ - "not_types" => types - } - } - } - end - - def exclude_timeline_types(filter, types) when is_map(filter) and is_list(types) do - update( - filter, - ["room", "timeline", "not_types"], - types, - &Enum.concat(&1, types) - ) + def exclude_timeline_types(filter \\ %{}, types) do + timeline(filter, &Polyjuice.Client.Filter.Event.exclude_types(&1, types)) end @doc """ Set the maximum number of timeline events. """ @spec limit_timeline_events(filter :: map, limit :: integer) :: map - def limit_timeline_events(filter \\ %{}, limit) - - def limit_timeline_events(filter, limit) when filter == %{} and is_integer(limit) do - %{ - "room" => %{ - "timeline" => %{ - "limit" => limit - } - } - } - end - - def limit_timeline_events(filter, limit) when is_map(filter) and is_integer(limit) do - put(filter, ["room", "timeline", "limit"], limit) + def limit_timeline_events(filter \\ %{}, limit) do + timeline(filter, &Polyjuice.Client.Filter.Event.limit(&1, limit)) end @spec lazy_loading(filter :: map) :: map diff --git a/test/polyjuice/client/filter_test.exs b/test/polyjuice/client/filter_test.exs index 8057360..5101fdc 100644 --- a/test/polyjuice/client/filter_test.exs +++ b/test/polyjuice/client/filter_test.exs @@ -112,6 +112,20 @@ defmodule Polyjuice.Client.FilterTest do } } + assert Filter.include_timeline_types(["foo.*"]) + |> Filter.exclude_timeline_types(["foo.bar"]) == %{ + "room" => %{ + "timeline" => %{"not_types" => ["foo.bar"], "types" => ["foo.*"]} + } + } + + assert Filter.exclude_timeline_types(["foo.bar"]) + |> Filter.include_timeline_types(["foo.*"]) == %{ + "room" => %{ + "timeline" => %{"not_types" => ["foo.bar"], "types" => ["foo.*"]} + } + } + assert Filter.limit_timeline_events(10) == %{"room" => %{"timeline" => %{"limit" => 10}}} assert Filter.lazy_loading() == %{ @@ -135,4 +149,53 @@ defmodule Polyjuice.Client.FilterTest do } } end + + test "event filter" do + assert Filter.Event.add_to_list("foo", ["bar"]) == %{"foo" => ["bar"]} + + assert Filter.Event.include_types(["m.*"]) + |> Filter.Event.exclude_types(["m.reaction"]) == %{ + "types" => ["m.*"], + "not_types" => ["m.reaction"] + } + + assert Filter.Event.exclude_types(["m.reaction"]) + |> Filter.Event.include_types(["m.*"]) == %{ + "types" => ["m.*"], + "not_types" => ["m.reaction"] + } + + assert Filter.Event.include_senders(["@alice:example.org"]) + |> Filter.Event.exclude_senders(["@bob:example.org"]) == %{ + "senders" => ["@alice:example.org"], + "not_senders" => ["@bob:example.org"] + } + + assert Filter.Event.include_senders(["@alice:example.org"]) + |> Filter.Event.include_senders(["@bob:example.org"]) == %{ + "senders" => ["@alice:example.org", "@bob:example.org"] + } + + assert Filter.Event.exclude_senders(["@bob:example.org"]) + |> Filter.Event.include_senders(["@alice:example.org"]) == %{ + "senders" => ["@alice:example.org"], + "not_senders" => ["@bob:example.org"] + } + + assert Filter.Event.include_rooms(["!room1"]) + |> Filter.Event.exclude_rooms(["!room2"]) == %{ + "rooms" => ["!room1"], + "not_rooms" => ["!room2"] + } + + assert Filter.Event.exclude_rooms(["!room2"]) + |> Filter.Event.include_rooms(["!room1"]) == %{ + "rooms" => ["!room1"], + "not_rooms" => ["!room2"] + } + + assert Filter.Event.limit(10) == %{"limit" => 10} + + assert Filter.Event.contains_url(true) == %{"contains_url" => true} + end end |