Merge remote-tracking branch 'remotes/upstream/develop' into 1304-user-info-deprecation
# Conflicts: # lib/pleroma/notification.ex
This commit is contained in:
commit
8cc809e44e
18 changed files with 552 additions and 37 deletions
74
lib/pleroma/marker.ex
Normal file
74
lib/pleroma/marker.ex
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Marker do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset
|
||||
import Ecto.Query
|
||||
|
||||
alias Ecto.Multi
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
@timelines ["notifications"]
|
||||
|
||||
schema "markers" do
|
||||
field(:last_read_id, :string, default: "")
|
||||
field(:timeline, :string, default: "")
|
||||
field(:lock_version, :integer, default: 0)
|
||||
|
||||
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
|
||||
timestamps()
|
||||
end
|
||||
|
||||
def get_markers(user, timelines \\ []) do
|
||||
Repo.all(get_query(user, timelines))
|
||||
end
|
||||
|
||||
def upsert(%User{} = user, attrs) do
|
||||
attrs
|
||||
|> Map.take(@timelines)
|
||||
|> Enum.reduce(Multi.new(), fn {timeline, timeline_attrs}, multi ->
|
||||
marker =
|
||||
user
|
||||
|> get_marker(timeline)
|
||||
|> changeset(timeline_attrs)
|
||||
|
||||
Multi.insert(multi, timeline, marker,
|
||||
returning: true,
|
||||
on_conflict: {:replace, [:last_read_id]},
|
||||
conflict_target: [:user_id, :timeline]
|
||||
)
|
||||
end)
|
||||
|> Repo.transaction()
|
||||
end
|
||||
|
||||
defp get_marker(user, timeline) do
|
||||
case Repo.find_resource(get_query(user, timeline)) do
|
||||
{:ok, marker} -> %__MODULE__{marker | user: user}
|
||||
_ -> %__MODULE__{timeline: timeline, user_id: user.id}
|
||||
end
|
||||
end
|
||||
|
||||
@doc false
|
||||
defp changeset(marker, attrs) do
|
||||
marker
|
||||
|> cast(attrs, [:last_read_id])
|
||||
|> validate_required([:user_id, :timeline, :last_read_id])
|
||||
|> validate_inclusion(:timeline, @timelines)
|
||||
end
|
||||
|
||||
defp by_timeline(query, timeline) do
|
||||
from(m in query, where: m.timeline in ^List.wrap(timeline))
|
||||
end
|
||||
|
||||
defp by_user_id(query, id), do: from(m in query, where: m.user_id == ^id)
|
||||
|
||||
defp get_query(user, timelines) do
|
||||
__MODULE__
|
||||
|> by_user_id(user.id)
|
||||
|> by_timeline(timelines)
|
||||
end
|
||||
end
|
||||
|
|
@ -55,9 +55,19 @@ defmodule Pleroma.Notification do
|
|||
)
|
||||
|> preload([n, a, o], activity: {a, object: o})
|
||||
|> exclude_muted(user, opts)
|
||||
|> exclude_blocked(user)
|
||||
|> exclude_visibility(opts)
|
||||
end
|
||||
|
||||
defp exclude_blocked(query, user) do
|
||||
query
|
||||
|> where([n, a], a.actor not in ^user.info.blocks)
|
||||
|> where(
|
||||
[n, a],
|
||||
fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks
|
||||
)
|
||||
end
|
||||
|
||||
defp exclude_muted(query, _, %{with_muted: true}) do
|
||||
query
|
||||
end
|
||||
|
|
@ -65,11 +75,6 @@ defmodule Pleroma.Notification do
|
|||
defp exclude_muted(query, user, _opts) do
|
||||
query
|
||||
|> where([n, a], a.actor not in ^user.muted_notifications)
|
||||
|> where([n, a], a.actor not in ^user.blocks)
|
||||
|> where(
|
||||
[n, a],
|
||||
fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.domain_blocks
|
||||
)
|
||||
|> join(:left, [n, a], tm in Pleroma.ThreadMute,
|
||||
on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -49,26 +49,28 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
|
||||
def determine_explicit_mentions(_), do: []
|
||||
|
||||
@spec recipient_in_collection(any(), any()) :: boolean()
|
||||
defp recipient_in_collection(ap_id, coll) when is_binary(coll), do: ap_id == coll
|
||||
defp recipient_in_collection(ap_id, coll) when is_list(coll), do: ap_id in coll
|
||||
defp recipient_in_collection(_, _), do: false
|
||||
@spec label_in_collection?(any(), any()) :: boolean()
|
||||
defp label_in_collection?(ap_id, coll) when is_binary(coll), do: ap_id == coll
|
||||
defp label_in_collection?(ap_id, coll) when is_list(coll), do: ap_id in coll
|
||||
defp label_in_collection?(_, _), do: false
|
||||
|
||||
@spec label_in_message?(String.t(), map()) :: boolean()
|
||||
def label_in_message?(label, params),
|
||||
do:
|
||||
[params["to"], params["cc"], params["bto"], params["bcc"]]
|
||||
|> Enum.any?(&label_in_collection?(label, &1))
|
||||
|
||||
@spec unaddressed_message?(map()) :: boolean()
|
||||
def unaddressed_message?(params),
|
||||
do:
|
||||
[params["to"], params["cc"], params["bto"], params["bcc"]]
|
||||
|> Enum.all?(&is_nil(&1))
|
||||
|
||||
@spec recipient_in_message(User.t(), User.t(), map()) :: boolean()
|
||||
def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params) do
|
||||
addresses = [params["to"], params["cc"], params["bto"], params["bcc"]]
|
||||
|
||||
cond do
|
||||
Enum.any?(addresses, &recipient_in_collection(ap_id, &1)) -> true
|
||||
# if the message is unaddressed at all, then assume it is directly addressed
|
||||
# to the recipient
|
||||
Enum.all?(addresses, &is_nil(&1)) -> true
|
||||
# if the message is sent from somebody the user is following, then assume it
|
||||
# is addressed to the recipient
|
||||
User.following?(recipient, actor) -> true
|
||||
true -> false
|
||||
end
|
||||
end
|
||||
def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params),
|
||||
do:
|
||||
label_in_message?(ap_id, params) || unaddressed_message?(params) ||
|
||||
User.following?(recipient, actor)
|
||||
|
||||
defp extract_list(target) when is_binary(target), do: [target]
|
||||
defp extract_list(lst) when is_list(lst), do: lst
|
||||
|
|
@ -76,8 +78,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
|
||||
def maybe_splice_recipient(ap_id, params) do
|
||||
need_splice? =
|
||||
!recipient_in_collection(ap_id, params["to"]) &&
|
||||
!recipient_in_collection(ap_id, params["cc"])
|
||||
!label_in_collection?(ap_id, params["to"]) &&
|
||||
!label_in_collection?(ap_id, params["cc"])
|
||||
|
||||
if need_splice? do
|
||||
cc_list = extract_list(params["cc"])
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
|
|
@ -15,7 +16,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
|
|||
def is_public?(%Object{data: data}), do: is_public?(data)
|
||||
def is_public?(%Activity{data: data}), do: is_public?(data)
|
||||
def is_public?(%{"directMessage" => true}), do: false
|
||||
def is_public?(data), do: Pleroma.Constants.as_public() in (data["to"] ++ (data["cc"] || []))
|
||||
def is_public?(data), do: Utils.label_in_message?(Pleroma.Constants.as_public(), data)
|
||||
|
||||
def is_private?(activity) do
|
||||
with false <- is_public?(activity),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MarkerController do
|
||||
use Pleroma.Web, :controller
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["read:statuses"]}
|
||||
when action == :index
|
||||
)
|
||||
|
||||
plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :upsert)
|
||||
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||
|
||||
# GET /api/v1/markers
|
||||
def index(%{assigns: %{user: user}} = conn, params) do
|
||||
markers = Pleroma.Marker.get_markers(user, params["timeline"])
|
||||
render(conn, "markers.json", %{markers: markers})
|
||||
end
|
||||
|
||||
# POST /api/v1/markers
|
||||
def upsert(%{assigns: %{user: user}} = conn, params) do
|
||||
with {:ok, result} <- Pleroma.Marker.upsert(user, params),
|
||||
markers <- Map.values(result) do
|
||||
render(conn, "markers.json", %{markers: markers})
|
||||
end
|
||||
end
|
||||
end
|
||||
17
lib/pleroma/web/mastodon_api/views/marker_view.ex
Normal file
17
lib/pleroma/web/mastodon_api/views/marker_view.ex
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.MarkerView do
|
||||
use Pleroma.Web, :view
|
||||
|
||||
def render("markers.json", %{markers: markers}) do
|
||||
Enum.reduce(markers, %{}, fn m, acc ->
|
||||
Map.put_new(acc, m.timeline, %{
|
||||
last_read_id: m.last_read_id,
|
||||
version: m.lock_version,
|
||||
updated_at: NaiveDateTime.to_iso8601(m.updated_at)
|
||||
})
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
@ -125,6 +125,10 @@ defmodule Pleroma.Web.Push.Impl do
|
|||
end
|
||||
end
|
||||
|
||||
def format_title(%{activity: %{data: %{"directMessage" => true}}}) do
|
||||
"New Direct Message"
|
||||
end
|
||||
|
||||
def format_title(%{activity: %{data: %{"type" => type}}}) do
|
||||
case type do
|
||||
"Create" -> "New Mention"
|
||||
|
|
|
|||
|
|
@ -405,6 +405,9 @@ defmodule Pleroma.Web.Router do
|
|||
get("/push/subscription", SubscriptionController, :get)
|
||||
put("/push/subscription", SubscriptionController, :update)
|
||||
delete("/push/subscription", SubscriptionController, :delete)
|
||||
|
||||
get("/markers", MarkerController, :index)
|
||||
post("/markers", MarkerController, :upsert)
|
||||
end
|
||||
|
||||
scope "/api/web", Pleroma.Web do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue