diff --git a/lib/frenzy/filter_engine.ex b/lib/frenzy/filter_engine.ex new file mode 100644 index 0000000..ffcc700 --- /dev/null +++ b/lib/frenzy/filter_engine.ex @@ -0,0 +1,33 @@ +defmodule Frenzy.FilterEngine do + def matches?(item, filter) do + score = + filter.rules + |> Enum.map(fn rule -> score(item, rule) end) + |> Enum.sum() + + score >= filter.score + end + + def score(item, rule) do + prop_value = get_property(item, rule.property) + + if matches(prop_value, rule.mode, rule.param) do + rule.weight + else + 0 + end + end + + def matches(value, "contains_string", param) do + String.contains?(value, param) + end + + def matches(value, "matches_regex", param) do + regex = Regex.compile(param) + String.match?(value, regex) + end + + def get_property(item, "url"), do: item.url + def get_property(item, "title"), do: item.title + def get_property(item, "author"), do: item.author +end diff --git a/lib/frenzy/update_feeds.ex b/lib/frenzy/update_feeds.ex index 8c00473..3f8c891 100644 --- a/lib/frenzy/update_feeds.ex +++ b/lib/frenzy/update_feeds.ex @@ -1,6 +1,6 @@ defmodule Frenzy.UpdateFeeds do use GenServer - alias Frenzy.{Repo, Feed, Item} + alias Frenzy.{Repo, Feed, Item, FilterEngine} import Ecto.Query require Logger @@ -89,7 +89,7 @@ defmodule Frenzy.UpdateFeeds do Repo.update(changeset) - feed = Repo.preload(feed, :items) + feed = Repo.preload(feed, items: [], filter: [:rules]) Enum.map(rss.items, fn entry -> # todo: use Repo.exists for this @@ -100,8 +100,7 @@ defmodule Frenzy.UpdateFeeds do end defp create_item(feed, entry) do - Logger.debug("Creating item for:") - IO.inspect(entry) + Logger.debug("Creating item for #{entry.url}") url = get_real_url(entry) @@ -115,15 +114,43 @@ defmodule Frenzy.UpdateFeeds do entry.description end + item_params = %{ + guid: entry.id, + title: entry.title, + url: url, + date: parse_date(entry.published_at), + creator: "", + content: content + } + + result = + if feed.filter_enabled do + case {feed.filter.mode, FilterEngine.matches?(item_params, feed.filter)} do + {"accept", true} -> + :store + + {"reject", false} -> + :store + + _ -> + Logger.debug("Skipping item #{url} due to feed filter") + :tombstone + end + else + :store + end + changeset = - Ecto.build_assoc(feed, :items, %{ - guid: entry.id, - title: entry.title, - url: url, - date: parse_date(entry.published_at), - creator: "", - content: content - }) + case result do + :store -> + Ecto.build_assoc(feed, :items, item_params) + + :tombstone -> + Ecto.build_assoc(feed, :items, %{ + guid: entry.id, + tombstone: true + }) + end Repo.insert(changeset) end