[MastodonAPI] Add filters
authorHaelwenn (lanodan) Monnier <contact@hacktivis.me>
Tue, 14 Aug 2018 02:27:28 +0000 (04:27 +0200)
committerHaelwenn (lanodan) Monnier <contact@hacktivis.me>
Mon, 27 Aug 2018 13:09:05 +0000 (15:09 +0200)
lib/pleroma/filter.ex [new file with mode: 0644]
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/mastodon_api/views/filter_view.ex [new file with mode: 0644]
lib/pleroma/web/router.ex
priv/repo/migrations/20180813003722_create_filters.exs [new file with mode: 0644]
test/filter_test.exs [new file with mode: 0644]
test/web/mastodon_api/mastodon_api_controller_test.exs

diff --git a/lib/pleroma/filter.ex b/lib/pleroma/filter.ex
new file mode 100644 (file)
index 0000000..fe904df
--- /dev/null
@@ -0,0 +1,62 @@
+defmodule Pleroma.Filter do
+  use Ecto.Schema
+  import Ecto.{Changeset, Query}
+  alias Pleroma.{User, Repo, Activity}
+
+  schema "filters" do
+    belongs_to(:user, Pleroma.User)
+    field(:filter_id, :integer)
+    field(:hide, :boolean, default: false)
+    field(:whole_word, :boolean, default: true)
+    field(:phrase, :string)
+    field(:context, {:array, :string})
+    field(:expires_at, :utc_datetime)
+
+    timestamps()
+  end
+
+  def get(id, %{id: user_id} = _user) do
+    query =
+      from(
+        f in Pleroma.Filter,
+        where: f.filter_id == ^id,
+        where: f.user_id == ^user_id
+      )
+
+    Repo.one(query)
+  end
+
+  def get_filters(%Pleroma.User{id: user_id} = user) do
+    query =
+      from(
+        f in Pleroma.Filter,
+        where: f.user_id == ^user_id
+      )
+
+    Repo.all(query)
+  end
+
+  def create(%Pleroma.Filter{} = filter) do
+    Repo.insert(filter)
+  end
+
+  def delete(%Pleroma.Filter{id: filter_key} = filter) when is_number(filter_key) do
+    Repo.delete(filter)
+  end
+
+  def delete(%Pleroma.Filter{id: filter_key} = filter) when is_nil(filter_key) do
+    %Pleroma.Filter{id: id} = get(filter.filter_id, %{id: filter.user_id})
+
+    filter
+    |> Map.put(:id, id)
+    |> Repo.delete()
+  end
+
+  def update(%Pleroma.Filter{} = filter) do
+    destination = Map.from_struct(filter)
+
+    Pleroma.Filter.get(filter.filter_id, %{id: filter.user_id})
+    |> cast(destination, [:phrase, :context, :hide, :expires_at, :whole_word])
+    |> Repo.update()
+  end
+end
index f482de6fdc9bbd8781d6967bd103254d19f7fd0a..649ee033e0287216e66f88f2b1bfd76191948d1a 100644 (file)
@@ -2,7 +2,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   use Pleroma.Web, :controller
   alias Pleroma.{Repo, Object, Activity, User, Notification, Stats}
   alias Pleroma.Web
-  alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView}
+  alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView, FilterView}
   alias Pleroma.Web.ActivityPub.ActivityPub
   alias Pleroma.Web.ActivityPub.Utils
   alias Pleroma.Web.CommonAPI
@@ -1089,6 +1089,65 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     end
   end
 
+  def get_filters(%{assigns: %{user: user}} = conn, params) do
+    filters = Pleroma.Filter.get_filters(user)
+    res = FilterView.render("filters.json", filters: filters)
+    json(conn, res)
+  end
+
+  def create_filter(
+        %{assigns: %{user: user}} = conn,
+        %{"phrase" => phrase, "context" => context} = params
+      ) do
+    query = %Pleroma.Filter{
+      user_id: user.id,
+      phrase: phrase,
+      context: context,
+      hide: Map.get(params, "irreversible", nil),
+      whole_word: Map.get(params, "boolean", true)
+      # expires_at
+    }
+
+    {:ok, response} = Pleroma.Filter.create(query)
+    res = FilterView.render("filter.json", filter: response)
+    json(conn, res)
+  end
+
+  def get_filter(%{assigns: %{user: user}} = conn, %{"id" => filter_id} = params) do
+    filter = Pleroma.Filter.get(filter_id, user)
+    res = FilterView.render("filter.json", filter: filter)
+    json(conn, res)
+  end
+
+  def update_filter(
+        %{assigns: %{user: user}} = conn,
+        %{"phrase" => phrase, "context" => context, "id" => filter_id} = params
+      ) do
+    query = %Pleroma.Filter{
+      user_id: user.id,
+      filter_id: filter_id,
+      phrase: phrase,
+      context: context,
+      hide: Map.get(params, "irreversible", nil),
+      whole_word: Map.get(params, "boolean", true)
+      # expires_at
+    }
+
+    {:ok, response} = Pleroma.Filter.update(query)
+    res = FilterView.render("filter.json", filter: response)
+    json(conn, res)
+  end
+
+  def delete_filter(%{assigns: %{user: user}} = conn, %{"id" => filter_id} = params) do
+    query = %Pleroma.Filter{
+      user_id: user.id,
+      filter_id: filter_id
+    }
+
+    {:ok, response} = Pleroma.Filter.delete(query)
+    json(conn, %{})
+  end
+
   def errors(conn, _) do
     conn
     |> put_status(500)
diff --git a/lib/pleroma/web/mastodon_api/views/filter_view.ex b/lib/pleroma/web/mastodon_api/views/filter_view.ex
new file mode 100644 (file)
index 0000000..3f8c62f
--- /dev/null
@@ -0,0 +1,20 @@
+defmodule Pleroma.Web.MastodonAPI.FilterView do
+  use Pleroma.Web, :view
+  alias Pleroma.Web.MastodonAPI.FilterView
+  alias Pleroma.Web.CommonAPI.Utils
+
+  def render("filters.json", %{filters: filters} = opts) do
+    render_many(filters, FilterView, "filter.json", opts)
+  end
+
+  def render("filter.json", %{filter: filter}) do
+    %{
+      id: to_string(filter.filter_id),
+      phrase: filter.phrase,
+      context: filter.context,
+      expires_at: Utils.to_masto_date(filter.expires_at),
+      irreversible: filter.hide,
+      whole_word: false
+    }
+  end
+end
index 92732379465af1d6353d7d4c39a8123ac7cbbae6..b212a29095345c119846e2611a501f53e75f660e 100644 (file)
@@ -154,6 +154,12 @@ defmodule Pleroma.Web.Router do
     post("/domain_blocks", MastodonAPIController, :block_domain)
     delete("/domain_blocks", MastodonAPIController, :unblock_domain)
 
+    get("/filters", MastodonAPIController, :get_filters)
+    post("/filters", MastodonAPIController, :create_filter)
+    get("/filters/:id", MastodonAPIController, :get_filter)
+    put("/filters/:id", MastodonAPIController, :update_filter)
+    delete("/filters/:id", MastodonAPIController, :delete_filter)
+
     get("/suggestions", MastodonAPIController, :suggestions)
   end
 
diff --git a/priv/repo/migrations/20180813003722_create_filters.exs b/priv/repo/migrations/20180813003722_create_filters.exs
new file mode 100644 (file)
index 0000000..a273004
--- /dev/null
@@ -0,0 +1,20 @@
+defmodule Pleroma.Repo.Migrations.CreateFilters do
+  use Ecto.Migration
+
+  def change do
+    create table(:filters) do
+      add :user_id, references(:users, on_delete: :delete_all)
+      add :filter_id, :integer
+      add :hide, :boolean
+      add :phrase, :string
+      add :context, {:array, :string}
+      add :expires_at, :datetime
+      add :whole_word, :boolean
+
+      timestamps()
+    end
+
+    create index(:filters, [:user_id])
+    create index(:filters, [:phrase], where: "hide = true", name: :hided_phrases_index)
+  end
+end
diff --git a/test/filter_test.exs b/test/filter_test.exs
new file mode 100644 (file)
index 0000000..d81c92f
--- /dev/null
@@ -0,0 +1,85 @@
+defmodule Pleroma.FilterTest do
+  alias Pleroma.{User, Repo}
+  use Pleroma.DataCase
+
+  import Pleroma.Factory
+  import Ecto.Query
+
+  test "creating a filter" do
+    user = insert(:user)
+
+    query = %Pleroma.Filter{
+      user_id: user.id,
+      filter_id: 42,
+      phrase: "knights",
+      context: ["home"]
+    }
+
+    {:ok, %Pleroma.Filter{} = filter} = Pleroma.Filter.create(query)
+    result = Pleroma.Filter.get(filter.filter_id, user)
+    assert query.phrase == result.phrase
+  end
+
+  test "deleting a filter" do
+    user = insert(:user)
+
+    query = %Pleroma.Filter{
+      user_id: user.id,
+      filter_id: 0,
+      phrase: "knights",
+      context: ["home"]
+    }
+
+    {:ok, filter} = Pleroma.Filter.create(query)
+    {:ok, filter} = Pleroma.Filter.delete(query)
+    assert is_nil(Repo.get(Pleroma.Filter, filter.filter_id))
+  end
+
+  test "getting all filters by an user" do
+    user = insert(:user)
+
+    query_one = %Pleroma.Filter{
+      user_id: user.id,
+      filter_id: 1,
+      phrase: "knights",
+      context: ["home"]
+    }
+
+    query_two = %Pleroma.Filter{
+      user_id: user.id,
+      filter_id: 2,
+      phrase: "who",
+      context: ["home"]
+    }
+
+    {:ok, filter_one} = Pleroma.Filter.create(query_one)
+    {:ok, filter_two} = Pleroma.Filter.create(query_two)
+    filters = Pleroma.Filter.get_filters(user)
+    assert filter_one in filters
+    assert filter_two in filters
+  end
+
+  test "updating a filter" do
+    user = insert(:user)
+
+    query_one = %Pleroma.Filter{
+      user_id: user.id,
+      filter_id: 1,
+      phrase: "knights",
+      context: ["home"]
+    }
+
+    query_two = %Pleroma.Filter{
+      user_id: user.id,
+      filter_id: 1,
+      phrase: "who",
+      context: ["home", "timeline"]
+    }
+
+    {:ok, filter_one} = Pleroma.Filter.create(query_one)
+    {:ok, filter_two} = Pleroma.Filter.update(query_two)
+    assert filter_one != filter_two
+    assert filter_two.phrase == query_two.phrase
+    assert filter_two.context == query_two.context
+  end
+end
index 9e33c1d0459a10652c7fd01ad64f4745c88d13ec..770776a3bf8037e49ba635028b31c22d26e37324 100644 (file)
@@ -251,6 +251,125 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     end
   end
 
+  describe "filters" do
+    test "creating a filter", %{conn: conn} do
+      user = insert(:user)
+
+      filter = %Pleroma.Filter{
+        phrase: "knights",
+        context: ["home"]
+      }
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
+
+      assert response = json_response(conn, 200)
+      assert response["phrase"] == filter.phrase
+      assert response["context"] == filter.context
+    end
+
+    test "fetching a list of filters", %{conn: conn} do
+      user = insert(:user)
+
+      query_one = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 1,
+        phrase: "knights",
+        context: ["home"]
+      }
+
+      query_two = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 2,
+        phrase: "who",
+        context: ["home"]
+      }
+
+      {:ok, filter_one} = Pleroma.Filter.create(query_one)
+      {:ok, filter_two} = Pleroma.Filter.create(query_two)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/filters")
+
+      assert response = json_response(conn, 200)
+    end
+
+    test "get a filter", %{conn: conn} do
+      user = insert(:user)
+
+      query = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 2,
+        phrase: "knight",
+        context: ["home"]
+      }
+
+      {:ok, filter} = Pleroma.Filter.create(query)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/filters/#{filter.filter_id}")
+
+      assert response = json_response(conn, 200)
+    end
+
+    test "update a filter", %{conn: conn} do
+      user = insert(:user)
+
+      query = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 2,
+        phrase: "knight",
+        context: ["home"]
+      }
+
+      {:ok, filter} = Pleroma.Filter.create(query)
+
+      new = %Pleroma.Filter{
+        phrase: "nii",
+        context: ["home"]
+      }
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> put("/api/v1/filters/#{query.filter_id}", %{
+          phrase: new.phrase,
+          context: new.context
+        })
+
+      assert response = json_response(conn, 200)
+      assert response["phrase"] == new.phrase
+      assert response["context"] == new.context
+    end
+
+    test "delete a filter", %{conn: conn} do
+      user = insert(:user)
+
+      query = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 2,
+        phrase: "knight",
+        context: ["home"]
+      }
+
+      {:ok, filter} = Pleroma.Filter.create(query)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> delete("/api/v1/filters/#{filter.filter_id}")
+
+      assert response = json_response(conn, 200)
+      assert response == %{}
+    end
+  end
+
   describe "lists" do
     test "creating a list", %{conn: conn} do
       user = insert(:user)