diff options
author | eugenijm <eugenijm@protonmail.com> | 2019-03-18 04:32:23 +0300 |
---|---|---|
committer | eugenijm <eugenijm@protonmail.com> | 2019-03-18 11:27:27 +0300 |
commit | 1588688a11ab82bf794d736fd6d18eebf1269dfe (patch) | |
tree | 5db793c8405f29d8f5e0970161af4b4ac02ab6c6 /lib | |
parent | 1344e34ed3a337b54e450af474f81e2f326bf768 (diff) | |
download | pleroma-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.ex | 8 | ||||
-rw-r--r-- | lib/pleroma/notification.ex | 36 | ||||
-rw-r--r-- | lib/pleroma/pagination.ex | 78 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api.ex | 48 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 |
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) |