From a85dca5b3da94dbe54a781eedf66d6fddc99c7c8 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 28 Aug 2021 12:17:16 -0400 Subject: [PATCH] Add filtering by item content --- lib/frenzy/pipeline/filter_engine.ex | 29 ++++++++++++++++--- .../live/filter/filter_rule_live.ex | 4 ++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/frenzy/pipeline/filter_engine.ex b/lib/frenzy/pipeline/filter_engine.ex index 0de7c51..e1f7034 100644 --- a/lib/frenzy/pipeline/filter_engine.ex +++ b/lib/frenzy/pipeline/filter_engine.ex @@ -45,18 +45,24 @@ defmodule Frenzy.Pipeline.FilterEngine do def validate_rules(_rules), do: {:error, "rules must be a list"} + @rule_modes ~W[contains_string contains_string_case_sensitive matches_regex] + @rule_properties ~W[url title author content] + def validate_rule(rule) do cond do not is_map(rule) -> {:error, "rule must be a map"} not (Map.has_key?(rule, "mode") and is_binary(rule["mode"]) and - rule["mode"] in ["contains_string", "matches_regex"]) -> - {:error, "mode property must be a string, either 'contains_string' or 'matches_regex'"} + rule["mode"] in @rule_modes) -> + rule_modes_text = Enum.map_join(@rule_modes, ", ", &"'#{&1}'") + {:error, "mode property must be a string, one of #{rule_modes_text}"} not (Map.has_key?(rule, "property") and is_binary(rule["property"]) and - rule["property"] in ["url", "title", "author"]) -> - {:error, "property property must be a string, either 'url', 'title', or 'author'"} + rule["property"] in @rule_properties) -> + rule_props_text = Enum.map_join(@rule_properties, ", ", &"'#{&1}'") + + {:error, "property property must be a string, one of #{rule_props_text}"} not (Map.has_key?(rule, "param") and is_binary(rule["param"])) -> {:error, "param property must be a string"} @@ -105,6 +111,10 @@ defmodule Frenzy.Pipeline.FilterEngine do end defp matches(value, "contains_string", param) do + String.contains?(String.downcase(value), String.downcase(param)) + end + + defp matches(value, "contains_string_case_sensitive", param) do String.contains?(value, param) end @@ -116,5 +126,16 @@ defmodule Frenzy.Pipeline.FilterEngine do defp get_property(item_params, "url"), do: item_params.url defp get_property(item_params, "title"), do: item_params.title defp get_property(item_params, "author"), do: item_params.author + + defp get_property(%{content: content, content_type: type}, "content") + when type in ["text/plain", "text/gemini"], + do: content + + defp get_property(%{content: content, content_type: "text/html"}, "content") do + content + |> Floki.parse() + |> Floki.text() + end + defp get_property(_item_params, _property), do: {:error, "invalid property"} end diff --git a/lib/frenzy_web/live/filter/filter_rule_live.ex b/lib/frenzy_web/live/filter/filter_rule_live.ex index b33b274..90b1a7f 100644 --- a/lib/frenzy_web/live/filter/filter_rule_live.ex +++ b/lib/frenzy_web/live/filter/filter_rule_live.ex @@ -3,13 +3,15 @@ defmodule FrenzyWeb.FilterRuleLive do @modes [ {"Contains Substring", "contains_string"}, + {"Contains Substring (case sensitive)", "contains_string_case_sensitive"}, {"Matches Regex", "matches_regex"} ] @properties [ {"Title", "title"}, {"URL", "url"}, - {"Author", "author"} + {"Author", "author"}, + {"Content", "content"} ] @impl true