|
- # Pleroma: A lightweight social networking server
- # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
- # SPDX-License-Identifier: AGPL-3.0-only
-
- defmodule Pleroma.Filter do
- use Ecto.Schema
-
- import Ecto.Changeset
- import Ecto.Query
-
- alias Pleroma.Repo
- alias Pleroma.User
-
- schema "filters" do
- belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
- 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_active(query) do
- from(f in query, where: is_nil(f.expires_at) or f.expires_at > ^NaiveDateTime.utc_now())
- end
-
- def get_irreversible(query) do
- from(f in query, where: f.hide)
- end
-
- def get_filters(query \\ __MODULE__, %User{id: user_id}) do
- query =
- from(
- f in query,
- where: f.user_id == ^user_id,
- order_by: [desc: :id]
- )
-
- Repo.all(query)
- end
-
- def create(%Pleroma.Filter{user_id: user_id, filter_id: nil} = filter) do
- # If filter_id wasn't given, use the max filter_id for this user plus 1.
- # XXX This could result in a race condition if a user tries to add two
- # different filters for their account from two different clients at the
- # same time, but that should be unlikely.
-
- max_id_query =
- from(
- f in Pleroma.Filter,
- where: f.user_id == ^user_id,
- select: max(f.filter_id)
- )
-
- filter_id =
- case Repo.one(max_id_query) do
- # Start allocating from 1
- nil ->
- 1
-
- max_id ->
- max_id + 1
- end
-
- filter
- |> Map.put(:filter_id, filter_id)
- |> Repo.insert()
- 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, params) do
- filter
- |> cast(params, [:phrase, :context, :hide, :expires_at, :whole_word])
- |> validate_required([:phrase, :context])
- |> Repo.update()
- end
-
- def compose_regex(user_or_filters, format \\ :postgres)
-
- def compose_regex(%User{} = user, format) do
- __MODULE__
- |> get_active()
- |> get_irreversible()
- |> get_filters(user)
- |> compose_regex(format)
- end
-
- def compose_regex([_ | _] = filters, format) do
- phrases =
- filters
- |> Enum.map(& &1.phrase)
- |> Enum.join("|")
-
- case format do
- :postgres ->
- "\\y(#{phrases})\\y"
-
- :re ->
- ~r/\b#{phrases}\b/i
-
- _ ->
- nil
- end
- end
-
- def compose_regex(_, _), do: nil
- end
|