Add MRFs for direct message manipulation
This commit is contained in:
parent
4e969758e5
commit
d310f99d6a
|
@ -158,6 +158,8 @@ defmodule Pleroma.User do
|
||||||
field(:last_status_at, :naive_datetime)
|
field(:last_status_at, :naive_datetime)
|
||||||
field(:language, :string)
|
field(:language, :string)
|
||||||
field(:status_ttl_days, :integer, default: nil)
|
field(:status_ttl_days, :integer, default: nil)
|
||||||
|
field(:accepts_direct_messages_from_followed, :boolean)
|
||||||
|
field(:accepts_direct_messages_from_not_followed, :boolean)
|
||||||
|
|
||||||
embeds_one(
|
embeds_one(
|
||||||
:notification_settings,
|
:notification_settings,
|
||||||
|
@ -2722,4 +2724,17 @@ def unfollow_hashtag(%User{} = user, %Hashtag{} = hashtag) do
|
||||||
def following_hashtag?(%User{} = user, %Hashtag{} = hashtag) do
|
def following_hashtag?(%User{} = user, %Hashtag{} = hashtag) do
|
||||||
not is_nil(HashtagFollow.get(user, hashtag))
|
not is_nil(HashtagFollow.get(user, hashtag))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def accepts_direct_messages?(%User{} = receiver, %User{} = sender) do
|
||||||
|
cond do
|
||||||
|
User.following?(receiver, sender) && receiver.accepts_direct_messages_from_followed == true ->
|
||||||
|
true
|
||||||
|
|
||||||
|
receiver.accepts_direct_messages_from_not_followed == true ->
|
||||||
|
true
|
||||||
|
|
||||||
|
true ->
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -147,7 +147,8 @@ def get_policies do
|
||||||
|> Enum.concat([
|
|> Enum.concat([
|
||||||
Pleroma.Web.ActivityPub.MRF.HashtagPolicy,
|
Pleroma.Web.ActivityPub.MRF.HashtagPolicy,
|
||||||
Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy,
|
Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy,
|
||||||
Pleroma.Web.ActivityPub.MRF.NormalizeMarkup
|
Pleroma.Web.ActivityPub.MRF.NormalizeMarkup,
|
||||||
|
Pleroma.Web.ActivityPub.MRF.DirectMessageDisabledPolicy
|
||||||
])
|
])
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.DirectMessageDisabledPolicy do
|
||||||
|
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||||
|
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
|
||||||
|
@moduledoc """
|
||||||
|
Removes entries from the "To" field from direct messages if the user has requested to not
|
||||||
|
allow direct messages
|
||||||
|
"""
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(
|
||||||
|
%{
|
||||||
|
"type" => "Note",
|
||||||
|
"actor" => actor
|
||||||
|
} = activity
|
||||||
|
) do
|
||||||
|
with true <- Visibility.is_direct?(%{data: activity}),
|
||||||
|
recipients <- Map.get(activity, "to"),
|
||||||
|
sender <- User.get_cached_by_ap_id(actor) do
|
||||||
|
new_to =
|
||||||
|
Enum.filter(recipients, fn recv ->
|
||||||
|
should_filter?(sender, recv)
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:ok, Map.put(activity, :to, new_to)}
|
||||||
|
else
|
||||||
|
_ -> {:ok, activity}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(object), do: {:ok, object}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def describe, do: {:ok, %{}}
|
||||||
|
|
||||||
|
defp should_filter?(sender, receiver_ap_id) do
|
||||||
|
with %User{local: true} = receiver <- User.get_cached_by_ap_id(receiver_ap_id) do
|
||||||
|
User.accepts_direct_messages?(receiver, sender)
|
||||||
|
else
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,49 @@
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.RejectNewlyCreatedAccountNotesPolicy do
|
||||||
|
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||||
|
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
|
@moduledoc """
|
||||||
|
Rejects notes from accounts that were created below a certain threshold of time ago
|
||||||
|
"""
|
||||||
|
@impl true
|
||||||
|
def filter(
|
||||||
|
%{
|
||||||
|
"type" => type,
|
||||||
|
"actor" => actor
|
||||||
|
} = activity
|
||||||
|
) when type in ["Note", "Create"] do
|
||||||
|
min_age = Pleroma.Config.get([:mrf_reject_newly_created_account_notes, :age])
|
||||||
|
|
||||||
|
with %User{} = user <- Pleroma.User.get_cached_by_ap_id(actor),
|
||||||
|
true <- Timex.diff(Timex.now(), user.inserted_at, :seconds) < min_age do
|
||||||
|
{:reject, "Account created too recently"}
|
||||||
|
else
|
||||||
|
_ -> {:ok, activity}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(object), do: {:ok, object}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def describe, do: {:ok, %{}}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_reject_newly_created_account_notes,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.RejectNewlyCreatedAccountNotesPolicy",
|
||||||
|
label: "MRF Reject New Accounts",
|
||||||
|
description: "Reject notes from accounts created too recently",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :age,
|
||||||
|
type: :integer,
|
||||||
|
description: "Time below which to reject (in seconds)",
|
||||||
|
suggestions: [86_400]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -708,6 +708,17 @@ defp update_credentials_request do
|
||||||
nullable: true,
|
nullable: true,
|
||||||
description:
|
description:
|
||||||
"Number of days after which statuses will be deleted. Set to -1 to disable."
|
"Number of days after which statuses will be deleted. Set to -1 to disable."
|
||||||
|
},
|
||||||
|
accepts_direct_messages_from_followed: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
nullable: true,
|
||||||
|
description:
|
||||||
|
"Whether to accept DMs from people you follow (will be overridden by accepts_direct_messages_from_not_followed if true)"
|
||||||
|
},
|
||||||
|
accepts_direct_messages_from_not_followed: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
nullable: true,
|
||||||
|
description: "Whether to accept DMs from everyone"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
example: %{
|
example: %{
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddUnfollowedDmRestrictions do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:users) do
|
||||||
|
add(:accepts_direct_messages_from_followed, :boolean, default: true)
|
||||||
|
add(:accepts_direct_messages_from_not_followed, :boolean, default: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -146,8 +146,7 @@ test "should work when no detected language is received" do
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
assert {:ok, "", "I will crush you"} =
|
assert {:ok, "", "I will crush you"} = LibreTranslate.translate("ギュギュ握りつぶしちゃうぞ", nil, "en")
|
||||||
LibreTranslate.translate("ギュギュ握りつぶしちゃうぞ", nil, "en")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2756,4 +2756,36 @@ test "should not error when trying to unfollow a hashtag twice" do
|
||||||
assert user.followed_hashtags |> Enum.count() == 0
|
assert user.followed_hashtags |> Enum.count() == 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "accepts_direct_messages?/2" do
|
||||||
|
test "should return true if the recipient follows the sender and has turned on 'accept from follows'" do
|
||||||
|
recipient =
|
||||||
|
insert(:user, %{
|
||||||
|
accepts_direct_messages_from_followed: true,
|
||||||
|
accepts_direct_messages_from_not_followed: false
|
||||||
|
})
|
||||||
|
|
||||||
|
sender = insert(:user)
|
||||||
|
|
||||||
|
refute User.accepts_direct_messages?(recipient, sender)
|
||||||
|
|
||||||
|
CommonAPI.follow(recipient, sender)
|
||||||
|
|
||||||
|
assert User.accepts_direct_messages?(recipient, sender)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should return true if the recipient has 'accept from everyone' on" do
|
||||||
|
recipient = insert(:user, %{accepts_direct_messages_from_not_followed: true})
|
||||||
|
sender = insert(:user)
|
||||||
|
|
||||||
|
assert User.accepts_direct_messages?(recipient, sender)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "should return false if the receipient has 'accept from everyone' off" do
|
||||||
|
recipient = insert(:user, %{accepts_direct_messages_from_not_followed: false})
|
||||||
|
sender = insert(:user)
|
||||||
|
|
||||||
|
refute User.accepts_direct_messages?(recipient, sender)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.DirectMessageDisabledPolicyTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF.DirectMessageDisabledPolicy
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
|
describe "strips recipients" do
|
||||||
|
test "when the user denies the direct message" do
|
||||||
|
sender = insert(:user)
|
||||||
|
recipient = insert(:user, %{accepts_direct_messages_from_not_followed: false})
|
||||||
|
|
||||||
|
refute User.accepts_direct_messages?(recipient, sender)
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => sender.ap_id,
|
||||||
|
"to" => [recipient.ap_id],
|
||||||
|
"cc" => [],
|
||||||
|
"type" => "Note"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, %{to: []}} = DirectMessageDisabledPolicy.filter(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "when the user does not deny the direct message" do
|
||||||
|
sender = insert(:user)
|
||||||
|
recipient = insert(:user, %{accepts_direct_messages_from_not_followed: true})
|
||||||
|
|
||||||
|
assert User.accepts_direct_messages?(recipient, sender)
|
||||||
|
|
||||||
|
message = %{
|
||||||
|
"actor" => sender.ap_id,
|
||||||
|
"to" => [recipient.ap_id],
|
||||||
|
"cc" => [],
|
||||||
|
"type" => "Note"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, message} = DirectMessageDisabledPolicy.filter(message)
|
||||||
|
assert message.to == [recipient.ap_id]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue