aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authoreugenijm <eugenijm@protonmail.com>2019-03-18 04:32:23 +0300
committereugenijm <eugenijm@protonmail.com>2019-03-18 11:27:27 +0300
commit1588688a11ab82bf794d736fd6d18eebf1269dfe (patch)
tree5db793c8405f29d8f5e0970161af4b4ac02ab6c6 /lib
parent1344e34ed3a337b54e450af474f81e2f326bf768 (diff)
downloadpleroma-1588688a11ab82bf794d736fd6d18eebf1269dfe.tar.gz
Added support for exclude_types, limit, and min_id in Mastodon
notifications. Unify Mastodon-compatible pagination logic.
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/activity.ex8
-rw-r--r--lib/pleroma/notification.ex36
-rw-r--r--lib/pleroma/pagination.ex78
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api.ex48
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex2
5 files changed, 114 insertions, 58 deletions
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex
index 79dc26b01..de0e66681 100644
--- a/lib/pleroma/activity.ex
+++ b/lib/pleroma/activity.ex
@@ -22,6 +22,10 @@ defmodule Pleroma.Activity do
"Like" => "favourite"
}
+ @mastodon_to_ap_notification_types for {k, v} <- @mastodon_notification_types,
+ into: %{},
+ do: {v, k}
+
schema "activities" do
field(:data, :map)
field(:local, :boolean, default: true)
@@ -126,6 +130,10 @@ defmodule Pleroma.Activity do
def mastodon_notification_type(%Activity{}), do: nil
+ def from_mastodon_notification_type(type) do
+ Map.get(@mastodon_to_ap_notification_types, type)
+ end
+
def all_by_actor_and_id(actor, status_ids \\ [])
def all_by_actor_and_id(_actor, []), do: []
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 765191275..a98649b63 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Notification do
alias Pleroma.Activity
alias Pleroma.Notification
+ alias Pleroma.Pagination
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.CommonAPI
@@ -28,36 +29,17 @@ defmodule Pleroma.Notification do
|> cast(attrs, [:seen])
end
- # TODO: Make generic and unify (see activity_pub.ex)
- defp restrict_max(query, %{"max_id" => max_id}) do
- from(activity in query, where: activity.id < ^max_id)
+ def for_user_query(user) do
+ Notification
+ |> where(user_id: ^user.id)
+ |> join(:inner, [n], activity in assoc(n, :activity))
+ |> preload(:activity)
end
- defp restrict_max(query, _), do: query
-
- defp restrict_since(query, %{"since_id" => since_id}) do
- from(activity in query, where: activity.id > ^since_id)
- end
-
- defp restrict_since(query, _), do: query
-
def for_user(user, opts \\ %{}) do
- query =
- from(
- n in Notification,
- where: n.user_id == ^user.id,
- order_by: [desc: n.id],
- join: activity in assoc(n, :activity),
- preload: [activity: activity],
- limit: 20
- )
-
- query =
- query
- |> restrict_since(opts)
- |> restrict_max(opts)
-
- Repo.all(query)
+ user
+ |> for_user_query()
+ |> Pagination.fetch_paginated(opts)
end
def set_read_up_to(%{id: user_id} = _user, id) do
diff --git a/lib/pleroma/pagination.ex b/lib/pleroma/pagination.ex
new file mode 100644
index 000000000..7c864deef
--- /dev/null
+++ b/lib/pleroma/pagination.ex
@@ -0,0 +1,78 @@
+defmodule Pleroma.Pagination do
+ @moduledoc """
+ Implements Mastodon-compatible pagination.
+ """
+
+ import Ecto.Query
+ import Ecto.Changeset
+
+ alias Pleroma.Repo
+
+ @default_limit 20
+
+ def fetch_paginated(query, params) do
+ options = cast_params(params)
+
+ query
+ |> paginate(options)
+ |> Repo.all()
+ |> enforce_order(options)
+ end
+
+ def paginate(query, options) do
+ query
+ |> restrict(:min_id, options)
+ |> restrict(:since_id, options)
+ |> restrict(:max_id, options)
+ |> restrict(:order, options)
+ |> restrict(:limit, options)
+ end
+
+ defp cast_params(params) do
+ param_types = %{
+ min_id: :string,
+ since_id: :string,
+ max_id: :string,
+ limit: :integer
+ }
+
+ changeset = cast({%{}, param_types}, params, Map.keys(param_types))
+ changeset.changes
+ end
+
+ defp restrict(query, :min_id, %{min_id: min_id}) do
+ where(query, [q], q.id > ^min_id)
+ end
+
+ defp restrict(query, :since_id, %{since_id: since_id}) do
+ where(query, [q], q.id > ^since_id)
+ end
+
+ defp restrict(query, :max_id, %{max_id: max_id}) do
+ where(query, [q], q.id < ^max_id)
+ end
+
+ defp restrict(query, :order, %{min_id: _}) do
+ order_by(query, [u], fragment("? asc nulls last", u.id))
+ end
+
+ defp restrict(query, :order, _options) do
+ order_by(query, [u], fragment("? desc nulls last", u.id))
+ end
+
+ defp restrict(query, :limit, options) do
+ limit = Map.get(options, :limit, @default_limit)
+
+ query
+ |> limit(^limit)
+ end
+
+ defp restrict(query, _, _), do: query
+
+ defp enforce_order(result, %{min_id: _}) do
+ result
+ |> Enum.reverse()
+ end
+
+ defp enforce_order(result, _), do: result
+end
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex
index 54cb6c97a..08ea5f967 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex
@@ -2,61 +2,49 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
import Ecto.Query
import Ecto.Changeset
- alias Pleroma.Repo
+ alias Pleroma.Activity
+ alias Pleroma.Notification
+ alias Pleroma.Pagination
alias Pleroma.User
- @default_limit 20
-
def get_followers(user, params \\ %{}) do
user
|> User.get_followers_query()
- |> paginate(params)
- |> Repo.all()
+ |> Pagination.fetch_paginated(params)
end
def get_friends(user, params \\ %{}) do
user
|> User.get_friends_query()
- |> paginate(params)
- |> Repo.all()
+ |> Pagination.fetch_paginated(params)
end
- def paginate(query, params \\ %{}) do
+ def get_notifications(user, params \\ %{}) do
options = cast_params(params)
- query
- |> restrict(:max_id, options)
- |> restrict(:since_id, options)
- |> restrict(:limit, options)
- |> order_by([u], fragment("? desc nulls last", u.id))
+ user
+ |> Notification.for_user_query()
+ |> restrict(:exclude_types, options)
+ |> Pagination.fetch_paginated(params)
end
- def cast_params(params) do
+ defp cast_params(params) do
param_types = %{
- max_id: :string,
- since_id: :string,
- limit: :integer
+ exclude_types: {:array, :string}
}
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
changeset.changes
end
- defp restrict(query, :max_id, %{max_id: max_id}) do
- query
- |> where([q], q.id < ^max_id)
- end
-
- defp restrict(query, :since_id, %{since_id: since_id}) do
- query
- |> where([q], q.id > ^since_id)
- end
-
- defp restrict(query, :limit, options) do
- limit = Map.get(options, :limit, @default_limit)
+ defp restrict(query, :exclude_types, %{exclude_types: mastodon_types = [_ | _]}) do
+ ap_types =
+ mastodon_types
+ |> Enum.map(&Activity.from_mastodon_notification_type/1)
+ |> Enum.filter(& &1)
query
- |> limit(^limit)
+ |> where([q, a], not fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data))
end
defp restrict(query, _, _), do: query
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 952aa2453..2eb1da561 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -502,7 +502,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def notifications(%{assigns: %{user: user}} = conn, params) do
- notifications = Notification.for_user(user, params)
+ notifications = MastodonAPI.get_notifications(user, params)
conn
|> add_link_headers(:notifications, notifications)