Merge remote-tracking branch 'origin/develop' into shigusegubu
This commit is contained in:
commit
c775b4876d
143 changed files with 2064 additions and 1110 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -63,3 +63,6 @@ pleroma.iml
|
|||
|
||||
archive-*
|
||||
.gitlab-ci-local
|
||||
|
||||
# Test files should be named *.exs
|
||||
test/pleroma/**/*.ex
|
||||
|
|
|
@ -9,6 +9,7 @@ variables: &global_variables
|
|||
DB_HOST: postgres
|
||||
DB_PORT: "5432"
|
||||
MIX_ENV: test
|
||||
GIT_STRATEGY: fetch
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
|
@ -133,7 +134,7 @@ unit-testing-1.13.4-otp-25:
|
|||
script: &testing_script
|
||||
- mix ecto.create
|
||||
- mix ecto.migrate
|
||||
- mix pleroma.test_runner --cover --preload-modules
|
||||
- mix test --cover --preload-modules
|
||||
coverage: '/^Line total: ([^ ]*%)$/'
|
||||
artifacts:
|
||||
reports:
|
||||
|
|
1
changelog.d/bugfix-truncate-remote-user-fields.fix
Normal file
1
changelog.d/bugfix-truncate-remote-user-fields.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Truncate remote user fields, avoids them getting rejected
|
0
changelog.d/ci-git-fetch.skip
Normal file
0
changelog.d/ci-git-fetch.skip
Normal file
0
changelog.d/commonapi.skip
Normal file
0
changelog.d/commonapi.skip
Normal file
1
changelog.d/deprecate-subscribe.change
Normal file
1
changelog.d/deprecate-subscribe.change
Normal file
|
@ -0,0 +1 @@
|
|||
Deprecate `/api/v1/pleroma/accounts/:id/subscribe`/`unsubscribe`
|
0
changelog.d/fix-test-failures.skip
Normal file
0
changelog.d/fix-test-failures.skip
Normal file
1
changelog.d/follow-request.fix
Normal file
1
changelog.d/follow-request.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Fixed malformed follow requests that cause them to appear stuck pending due to the recipient being unable to process them.
|
1
changelog.d/follow-validator.fix
Normal file
1
changelog.d/follow-validator.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Improve the FollowValidator to successfully incoming activities with an errant cc field.
|
1
changelog.d/identity-proofs.remove
Normal file
1
changelog.d/identity-proofs.remove
Normal file
|
@ -0,0 +1 @@
|
|||
Remove stub for /api/v1/accounts/:id/identity_proofs (deprecated by Mastodon 3.5.0)
|
1
changelog.d/mailgun.fix
Normal file
1
changelog.d/mailgun.fix
Normal file
|
@ -0,0 +1 @@
|
|||
The Swoosh email adapter for Mailgun was missing a new dependency on :multipart
|
0
changelog.d/mogrify.skip
Normal file
0
changelog.d/mogrify.skip
Normal file
0
changelog.d/mrf-cleanup.skip
Normal file
0
changelog.d/mrf-cleanup.skip
Normal file
1
changelog.d/mrf-fodirectreply.add
Normal file
1
changelog.d/mrf-fodirectreply.add
Normal file
|
@ -0,0 +1 @@
|
|||
Added MRF.FODirectReply which changes replies to followers-only posts to be direct.
|
1
changelog.d/mrf-quietreply.add
Normal file
1
changelog.d/mrf-quietreply.add
Normal file
|
@ -0,0 +1 @@
|
|||
Added MRF.QuietReply which prevents replies to public posts from being published to the timelines
|
1
changelog.d/notifications-marker.change
Normal file
1
changelog.d/notifications-marker.change
Normal file
|
@ -0,0 +1 @@
|
|||
Fix 'Setting a marker should mark notifications as read'
|
1
changelog.d/publisher-reachability.fix
Normal file
1
changelog.d/publisher-reachability.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Address case where instance reachability status couldn't be updated
|
1
changelog.d/remote-object-fetcher.fix
Normal file
1
changelog.d/remote-object-fetcher.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Remote Fetcher Worker recognizes more permanent failure errors
|
1
changelog.d/stream-follow-relationships-count.fix
Normal file
1
changelog.d/stream-follow-relationships-count.fix
Normal file
|
@ -0,0 +1 @@
|
|||
StreamerView: Do not leak follows count if hidden
|
0
changelog.d/text-extensions.skip
Normal file
0
changelog.d/text-extensions.skip
Normal file
1
changelog.d/update-oban.change
Normal file
1
changelog.d/update-oban.change
Normal file
|
@ -0,0 +1 @@
|
|||
Update Oban to 2.18
|
0
changelog.d/user-factory.skip
Normal file
0
changelog.d/user-factory.skip
Normal file
1
changelog.d/user-imports.fix
Normal file
1
changelog.d/user-imports.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Imports of blocks, mutes, and follows would retry repeatedly due to incorrect error handling and all work executed in a single job
|
1
changelog.d/workerhelper.change
Normal file
1
changelog.d/workerhelper.change
Normal file
|
@ -0,0 +1 @@
|
|||
Worker configuration is no longer available. This only affects custom max_retries values for a couple Oban queues.
|
|
@ -613,13 +613,6 @@ config :pleroma, Oban,
|
|||
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}
|
||||
]
|
||||
|
||||
config :pleroma, :workers,
|
||||
retries: [
|
||||
federator_incoming: 5,
|
||||
federator_outgoing: 5,
|
||||
search_indexing: 2
|
||||
]
|
||||
|
||||
config :pleroma, Pleroma.Formatter,
|
||||
class: false,
|
||||
rel: "ugc",
|
||||
|
|
|
@ -2013,23 +2013,6 @@ config :pleroma, :config_description, [
|
|||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
group: :pleroma,
|
||||
key: :workers,
|
||||
type: :group,
|
||||
description: "Includes custom worker options not interpretable directly by `Oban`",
|
||||
children: [
|
||||
%{
|
||||
key: :retries,
|
||||
type: {:keyword, :integer},
|
||||
description: "Max retry attempts for failed jobs, per `Oban` queue",
|
||||
suggestions: [
|
||||
federator_incoming: 5,
|
||||
federator_outgoing: 5
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
group: :pleroma,
|
||||
key: Pleroma.Web.Metadata,
|
||||
|
|
|
@ -510,12 +510,6 @@ Pleroma is generally compatible with the Mastodon 2.7.2 API, but some newer feat
|
|||
|
||||
- `GET /api/v1/trends`: Returns an empty array, `[]`
|
||||
|
||||
### Identity proofs
|
||||
|
||||
*Added in Mastodon 2.8.0*
|
||||
|
||||
- `GET /api/v1/identity_proofs`: Returns an empty array, `[]`
|
||||
|
||||
### Featured tags
|
||||
|
||||
*Added in Mastodon 3.0.0*
|
||||
|
|
|
@ -145,6 +145,9 @@ See [Admin-API](admin_api.md)
|
|||
|
||||
## `/api/v1/pleroma/accounts/:id/subscribe`
|
||||
### Subscribe to receive notifications for all statuses posted by a user
|
||||
|
||||
Deprecated. `notify` parameter in `POST /api/v1/accounts/:id/follow` should be used instead.
|
||||
|
||||
* Method `POST`
|
||||
* Authentication: required
|
||||
* Params:
|
||||
|
@ -171,6 +174,9 @@ See [Admin-API](admin_api.md)
|
|||
|
||||
## `/api/v1/pleroma/accounts/:id/unsubscribe`
|
||||
### Unsubscribe to stop receiving notifications from user statuses
|
||||
|
||||
Deprecated. `notify` parameter in `POST /api/v1/accounts/:id/follow` should be used instead.
|
||||
|
||||
* Method `POST`
|
||||
* Authentication: required
|
||||
* Params:
|
||||
|
|
|
@ -295,10 +295,12 @@ defmodule Mix.Tasks.Pleroma.Database do
|
|||
|> DateTime.from_naive!("Etc/UTC")
|
||||
|> Timex.shift(days: days)
|
||||
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
|
||||
activity_id: activity.id,
|
||||
expires_at: expires_at
|
||||
})
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(
|
||||
%{
|
||||
activity_id: activity.id
|
||||
},
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|> Stream.run()
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
defmodule Mix.Tasks.Pleroma.TestRunner do
|
||||
@shortdoc "Retries tests once if they fail"
|
||||
|
||||
use Mix.Task
|
||||
|
||||
def run(args \\ []) do
|
||||
case System.cmd("mix", ["test"] ++ args, into: IO.stream(:stdio, :line)) do
|
||||
{_, 0} ->
|
||||
:ok
|
||||
|
||||
_ ->
|
||||
retry(args)
|
||||
end
|
||||
end
|
||||
|
||||
def retry(args) do
|
||||
case System.cmd("mix", ["test", "--failed"] ++ args, into: IO.stream(:stdio, :line)) do
|
||||
{_, 0} ->
|
||||
:ok
|
||||
|
||||
_ ->
|
||||
exit(1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -25,7 +25,8 @@ defmodule Pleroma.Emails.Mailer do
|
|||
|> :erlang.term_to_binary()
|
||||
|> Base.encode64()
|
||||
|
||||
MailerWorker.enqueue("email", %{"encoded_email" => encoded_email, "config" => config})
|
||||
MailerWorker.new(%{"op" => "email", "encoded_email" => encoded_email, "config" => config})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
@doc "callback to perform send email from queue"
|
||||
|
|
|
@ -133,10 +133,13 @@ defmodule Pleroma.Filter do
|
|||
defp maybe_add_expires_at(changeset, _), do: changeset
|
||||
|
||||
defp maybe_add_expiration_job(%{expires_at: %NaiveDateTime{} = expires_at} = filter) do
|
||||
Pleroma.Workers.PurgeExpiredFilter.enqueue(%{
|
||||
filter_id: filter.id,
|
||||
expires_at: DateTime.from_naive!(expires_at, "Etc/UTC")
|
||||
})
|
||||
Pleroma.Workers.PurgeExpiredFilter.new(
|
||||
%{
|
||||
filter_id: filter.id
|
||||
},
|
||||
scheduled_at: DateTime.from_naive!(expires_at, "Etc/UTC")
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
defp maybe_add_expiration_job(_), do: {:ok, nil}
|
||||
|
|
|
@ -297,7 +297,8 @@ defmodule Pleroma.Instances.Instance do
|
|||
all of those users' activities and notifications.
|
||||
"""
|
||||
def delete_users_and_activities(host) when is_binary(host) do
|
||||
DeleteWorker.enqueue("delete_instance", %{"host" => host})
|
||||
DeleteWorker.new(%{"op" => "delete_instance", "host" => host})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
def perform(:delete_instance, host) when is_binary(host) do
|
||||
|
|
|
@ -52,11 +52,14 @@ defmodule Pleroma.MFA.Token do
|
|||
@spec create(User.t(), Authorization.t() | nil) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
|
||||
def create(user, authorization \\ nil) do
|
||||
with {:ok, token} <- do_create(user, authorization) do
|
||||
Pleroma.Workers.PurgeExpiredToken.enqueue(%{
|
||||
token_id: token.id,
|
||||
valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"),
|
||||
mod: __MODULE__
|
||||
})
|
||||
Pleroma.Workers.PurgeExpiredToken.new(
|
||||
%{
|
||||
token_id: token.id,
|
||||
mod: __MODULE__
|
||||
},
|
||||
scheduled_at: DateTime.from_naive!(token.valid_until, "Etc/UTC")
|
||||
)
|
||||
|> Oban.insert()
|
||||
|
||||
{:ok, token}
|
||||
end
|
||||
|
|
|
@ -255,7 +255,8 @@ defmodule Pleroma.Object do
|
|||
@spec cleanup_attachments(boolean(), Object.t()) ::
|
||||
{:ok, Oban.Job.t() | nil}
|
||||
def cleanup_attachments(true, %Object{} = object) do
|
||||
AttachmentsCleanupWorker.enqueue("cleanup_attachments", %{"object" => object})
|
||||
AttachmentsCleanupWorker.new(%{"op" => "cleanup_attachments", "object" => object})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
def cleanup_attachments(_, _), do: {:ok, nil}
|
||||
|
|
|
@ -73,50 +73,22 @@ defmodule Pleroma.Object.Fetcher do
|
|||
{:object, data, Object.normalize(activity, fetch: false)} do
|
||||
{:ok, object}
|
||||
else
|
||||
{:allowed_depth, false} = e ->
|
||||
log_fetch_error(id, e)
|
||||
{:error, :allowed_depth}
|
||||
|
||||
{:containment, reason} = e ->
|
||||
log_fetch_error(id, e)
|
||||
{:error, reason}
|
||||
|
||||
{:transmogrifier, {:error, {:reject, reason}}} = e ->
|
||||
log_fetch_error(id, e)
|
||||
{:reject, reason}
|
||||
|
||||
{:transmogrifier, {:reject, reason}} = e ->
|
||||
log_fetch_error(id, e)
|
||||
{:reject, reason}
|
||||
|
||||
{:transmogrifier, reason} = e ->
|
||||
log_fetch_error(id, e)
|
||||
{:error, reason}
|
||||
|
||||
{:object, data, nil} ->
|
||||
reinject_object(%Object{}, data)
|
||||
|
||||
{:normalize, object = %Object{}} ->
|
||||
{:ok, object}
|
||||
|
||||
{:fetch_object, %Object{} = object} ->
|
||||
{:ok, object}
|
||||
|
||||
{:fetch, {:error, reason}} = e ->
|
||||
log_fetch_error(id, e)
|
||||
{:error, reason}
|
||||
{:object, data, nil} ->
|
||||
reinject_object(%Object{}, data)
|
||||
|
||||
e ->
|
||||
log_fetch_error(id, e)
|
||||
{:error, e}
|
||||
Logger.metadata(object: id)
|
||||
Logger.error("Object rejected while fetching #{id} #{inspect(e)}")
|
||||
e
|
||||
end
|
||||
end
|
||||
|
||||
defp log_fetch_error(id, error) do
|
||||
Logger.metadata(object: id)
|
||||
Logger.error("Object rejected while fetching #{id} #{inspect(error)}")
|
||||
end
|
||||
|
||||
defp prepare_activity_params(data) do
|
||||
%{
|
||||
"type" => "Create",
|
||||
|
|
|
@ -2,11 +2,13 @@ defmodule Pleroma.Search do
|
|||
alias Pleroma.Workers.SearchIndexingWorker
|
||||
|
||||
def add_to_index(%Pleroma.Activity{id: activity_id}) do
|
||||
SearchIndexingWorker.enqueue("add_to_index", %{"activity" => activity_id})
|
||||
SearchIndexingWorker.new(%{"op" => "add_to_index", "activity" => activity_id})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
def remove_from_index(%Pleroma.Object{id: object_id}) do
|
||||
SearchIndexingWorker.enqueue("remove_from_index", %{"object" => object_id})
|
||||
SearchIndexingWorker.new(%{"op" => "remove_from_index", "object" => object_id})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
def search(query, options) do
|
||||
|
|
|
@ -463,6 +463,7 @@ defmodule Pleroma.User do
|
|||
def remote_user_changeset(struct \\ %User{local: false}, params) do
|
||||
bio_limit = Config.get([:instance, :user_bio_length], 5000)
|
||||
name_limit = Config.get([:instance, :user_name_length], 100)
|
||||
fields_limit = Config.get([:instance, :max_remote_account_fields], 0)
|
||||
|
||||
name =
|
||||
case params[:name] do
|
||||
|
@ -476,6 +477,7 @@ defmodule Pleroma.User do
|
|||
|> Map.put_new(:last_refreshed_at, NaiveDateTime.utc_now())
|
||||
|> truncate_if_exists(:name, name_limit)
|
||||
|> truncate_if_exists(:bio, bio_limit)
|
||||
|> Map.update(:fields, [], &Enum.take(&1, fields_limit))
|
||||
|> truncate_fields_param()
|
||||
|> fix_follower_address()
|
||||
|
||||
|
@ -736,7 +738,8 @@ defmodule Pleroma.User do
|
|||
end
|
||||
|
||||
def force_password_reset_async(user) do
|
||||
BackgroundWorker.enqueue("force_password_reset", %{"user_id" => user.id})
|
||||
BackgroundWorker.new(%{"op" => "force_password_reset", "user_id" => user.id})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
@spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||
|
@ -1218,7 +1221,8 @@ defmodule Pleroma.User do
|
|||
def update_and_set_cache(changeset) do
|
||||
with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
|
||||
if get_change(changeset, :raw_fields) do
|
||||
BackgroundWorker.enqueue("verify_fields_links", %{"user_id" => user.id})
|
||||
BackgroundWorker.new(%{"op" => "verify_fields_links", "user_id" => user.id})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
set_cache(user)
|
||||
|
@ -1589,11 +1593,11 @@ defmodule Pleroma.User do
|
|||
)) ||
|
||||
{:ok, nil} do
|
||||
if duration > 0 do
|
||||
Pleroma.Workers.MuteExpireWorker.enqueue(
|
||||
"unmute_user",
|
||||
%{"muter_id" => muter.id, "mutee_id" => mutee.id},
|
||||
Pleroma.Workers.MuteExpireWorker.new(
|
||||
%{"op" => "unmute_user", "muter_id" => muter.id, "mutee_id" => mutee.id},
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
@cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
|
||||
|
@ -1836,7 +1840,8 @@ defmodule Pleroma.User do
|
|||
defp maybe_filter_on_ap_id(query, _ap_ids), do: query
|
||||
|
||||
def set_activation_async(user, status \\ true) do
|
||||
BackgroundWorker.enqueue("user_activation", %{"user_id" => user.id, "status" => status})
|
||||
BackgroundWorker.new(%{"op" => "user_activation", "user_id" => user.id, "status" => status})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
@spec set_activation([User.t()], boolean()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||
|
@ -1983,7 +1988,9 @@ defmodule Pleroma.User do
|
|||
def delete(%User{} = user) do
|
||||
# Purge the user immediately
|
||||
purge(user)
|
||||
DeleteWorker.enqueue("delete_user", %{"user_id" => user.id})
|
||||
|
||||
DeleteWorker.new(%{"op" => "delete_user", "user_id" => user.id})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
# *Actually* delete the user from the DB
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
defmodule Pleroma.User.Import do
|
||||
use Ecto.Schema
|
||||
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Workers.BackgroundWorker
|
||||
|
@ -12,74 +13,99 @@ defmodule Pleroma.User.Import do
|
|||
require Logger
|
||||
|
||||
@spec perform(atom(), User.t(), list()) :: :ok | list() | {:error, any()}
|
||||
def perform(:mutes_import, %User{} = user, [_ | _] = identifiers) do
|
||||
Enum.map(
|
||||
identifiers,
|
||||
fn identifier ->
|
||||
with {:ok, %User{} = muted_user} <- User.get_or_fetch(identifier),
|
||||
{:ok, _} <- User.mute(user, muted_user) do
|
||||
muted_user
|
||||
else
|
||||
error -> handle_error(:mutes_import, identifier, error)
|
||||
end
|
||||
end
|
||||
)
|
||||
def perform(:mute_import, %User{} = user, actor) do
|
||||
with {:ok, %User{} = muted_user} <- User.get_or_fetch(actor),
|
||||
{_, false} <- {:existing_mute, User.mutes_user?(user, muted_user)},
|
||||
{:ok, _} <- User.mute(user, muted_user) do
|
||||
{:ok, muted_user}
|
||||
else
|
||||
{:existing_mute, true} -> :ok
|
||||
error -> handle_error(:mutes_import, actor, error)
|
||||
end
|
||||
end
|
||||
|
||||
def perform(:blocks_import, %User{} = blocker, [_ | _] = identifiers) do
|
||||
Enum.map(
|
||||
identifiers,
|
||||
fn identifier ->
|
||||
with {:ok, %User{} = blocked} <- User.get_or_fetch(identifier),
|
||||
{:ok, _block} <- CommonAPI.block(blocked, blocker) do
|
||||
blocked
|
||||
else
|
||||
error -> handle_error(:blocks_import, identifier, error)
|
||||
end
|
||||
end
|
||||
)
|
||||
def perform(:block_import, %User{} = user, actor) do
|
||||
with {:ok, %User{} = blocked} <- User.get_or_fetch(actor),
|
||||
{_, false} <- {:existing_block, User.blocks_user?(user, blocked)},
|
||||
{:ok, _block} <- CommonAPI.block(blocked, user) do
|
||||
{:ok, blocked}
|
||||
else
|
||||
{:existing_block, true} -> :ok
|
||||
error -> handle_error(:blocks_import, actor, error)
|
||||
end
|
||||
end
|
||||
|
||||
def perform(:follow_import, %User{} = follower, [_ | _] = identifiers) do
|
||||
Enum.map(
|
||||
identifiers,
|
||||
fn identifier ->
|
||||
with {:ok, %User{} = followed} <- User.get_or_fetch(identifier),
|
||||
{:ok, follower, followed} <- User.maybe_direct_follow(follower, followed),
|
||||
{:ok, _, _, _} <- CommonAPI.follow(followed, follower) do
|
||||
followed
|
||||
else
|
||||
error -> handle_error(:follow_import, identifier, error)
|
||||
end
|
||||
end
|
||||
)
|
||||
def perform(:follow_import, %User{} = user, actor) do
|
||||
with {:ok, %User{} = followed} <- User.get_or_fetch(actor),
|
||||
{_, false} <- {:existing_follow, User.following?(user, followed)},
|
||||
{:ok, user, followed} <- User.maybe_direct_follow(user, followed),
|
||||
{:ok, _, _, _} <- CommonAPI.follow(followed, user) do
|
||||
{:ok, followed}
|
||||
else
|
||||
{:existing_follow, true} -> :ok
|
||||
error -> handle_error(:follow_import, actor, error)
|
||||
end
|
||||
end
|
||||
|
||||
def perform(_, _, _), do: :ok
|
||||
|
||||
defp handle_error(op, user_id, error) do
|
||||
Logger.debug("#{op} failed for #{user_id} with: #{inspect(error)}")
|
||||
error
|
||||
end
|
||||
|
||||
def blocks_import(%User{} = blocker, [_ | _] = identifiers) do
|
||||
BackgroundWorker.enqueue(
|
||||
"blocks_import",
|
||||
%{"user_id" => blocker.id, "identifiers" => identifiers}
|
||||
)
|
||||
def blocks_import(%User{} = user, [_ | _] = actors) do
|
||||
jobs =
|
||||
Repo.checkout(fn ->
|
||||
Enum.reduce(actors, [], fn actor, acc ->
|
||||
{:ok, job} =
|
||||
BackgroundWorker.new(%{
|
||||
"op" => "block_import",
|
||||
"user_id" => user.id,
|
||||
"actor" => actor
|
||||
})
|
||||
|> Oban.insert()
|
||||
|
||||
acc ++ [job]
|
||||
end)
|
||||
end)
|
||||
|
||||
{:ok, jobs}
|
||||
end
|
||||
|
||||
def follow_import(%User{} = follower, [_ | _] = identifiers) do
|
||||
BackgroundWorker.enqueue(
|
||||
"follow_import",
|
||||
%{"user_id" => follower.id, "identifiers" => identifiers}
|
||||
)
|
||||
def follows_import(%User{} = user, [_ | _] = actors) do
|
||||
jobs =
|
||||
Repo.checkout(fn ->
|
||||
Enum.reduce(actors, [], fn actor, acc ->
|
||||
{:ok, job} =
|
||||
BackgroundWorker.new(%{
|
||||
"op" => "follow_import",
|
||||
"user_id" => user.id,
|
||||
"actor" => actor
|
||||
})
|
||||
|> Oban.insert()
|
||||
|
||||
acc ++ [job]
|
||||
end)
|
||||
end)
|
||||
|
||||
{:ok, jobs}
|
||||
end
|
||||
|
||||
def mutes_import(%User{} = user, [_ | _] = identifiers) do
|
||||
BackgroundWorker.enqueue(
|
||||
"mutes_import",
|
||||
%{"user_id" => user.id, "identifiers" => identifiers}
|
||||
)
|
||||
def mutes_import(%User{} = user, [_ | _] = actors) do
|
||||
jobs =
|
||||
Repo.checkout(fn ->
|
||||
Enum.reduce(actors, [], fn actor, acc ->
|
||||
{:ok, job} =
|
||||
BackgroundWorker.new(%{
|
||||
"op" => "mute_import",
|
||||
"user_id" => user.id,
|
||||
"actor" => actor
|
||||
})
|
||||
|> Oban.insert()
|
||||
|
||||
acc ++ [job]
|
||||
end)
|
||||
end)
|
||||
|
||||
{:ok, jobs}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -222,10 +222,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
%{data: %{"expires_at" => %DateTime{} = expires_at}} = activity
|
||||
) do
|
||||
with {:ok, _job} <-
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
|
||||
activity_id: activity.id,
|
||||
expires_at: expires_at
|
||||
}) do
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(
|
||||
%{
|
||||
activity_id: activity.id
|
||||
},
|
||||
scheduled_at: expires_at
|
||||
) do
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
@ -446,10 +448,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
_ <- notify_and_stream(activity) do
|
||||
maybe_federate(activity)
|
||||
|
||||
BackgroundWorker.enqueue("move_following", %{
|
||||
BackgroundWorker.new(%{
|
||||
"op" => "move_following",
|
||||
"origin_id" => origin.id,
|
||||
"target_id" => target.id
|
||||
})
|
||||
|> Oban.insert()
|
||||
|
||||
{:ok, activity}
|
||||
else
|
||||
|
@ -1797,10 +1801,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
# enqueue a task to fetch all pinned objects
|
||||
Enum.each(pins, fn {ap_id, _} ->
|
||||
if is_nil(Object.get_cached_by_ap_id(ap_id)) do
|
||||
Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{
|
||||
Pleroma.Workers.RemoteFetcherWorker.new(%{
|
||||
"op" => "fetch_remote",
|
||||
"id" => ap_id,
|
||||
"depth" => 1
|
||||
})
|
||||
|> Oban.insert()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -63,20 +63,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Follow", "actor" => actor_id} = message) do
|
||||
def filter(%{"type" => "Follow", "actor" => actor_id} = activity) do
|
||||
%User{} = actor = normalize_by_ap_id(actor_id)
|
||||
|
||||
score = determine_if_followbot(actor)
|
||||
|
||||
if score < 0.8 || bot_allowed?(message, actor) do
|
||||
{:ok, message}
|
||||
if score < 0.8 || bot_allowed?(activity, actor) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, "[AntiFollowbotPolicy] Scored #{actor_id} as #{score}"}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -29,17 +29,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
|
|||
defp contains_links?(_), do: false
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
|
||||
def filter(%{"type" => "Create", "actor" => actor, "object" => object} = activity) do
|
||||
with {:ok, %User{local: false} = u} <- User.get_or_fetch_by_ap_id(actor),
|
||||
{:contains_links, true} <- {:contains_links, contains_links?(object)},
|
||||
{:old_user, true} <- {:old_user, old_user?(u)} do
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:ok, %User{local: true}} ->
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
|
||||
{:contains_links, false} ->
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
|
||||
{:old_user, false} ->
|
||||
{:reject, "[AntiLinkSpamPolicy] User has no posts nor followers"}
|
||||
|
@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
|
|||
end
|
||||
|
||||
# in all other cases, pass through
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -22,11 +22,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
|
|||
end
|
||||
|
||||
# copied from HellthreadPolicy
|
||||
defp get_recipient_count(message) do
|
||||
recipients = (message["to"] || []) ++ (message["cc"] || [])
|
||||
defp get_recipient_count(activity) do
|
||||
recipients = (activity["to"] || []) ++ (activity["cc"] || [])
|
||||
|
||||
follower_collection =
|
||||
User.get_cached_by_ap_id(message["actor"] || message["attributedTo"]).follower_address
|
||||
User.get_cached_by_ap_id(activity["actor"] || activity["attributedTo"]).follower_address
|
||||
|
||||
if Enum.member?(recipients, Pleroma.Constants.as_public()) do
|
||||
recipients =
|
||||
|
@ -80,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiMentionSpamPolicy do
|
|||
end
|
||||
|
||||
# in all other cases, pass through
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -38,18 +38,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
|
|||
@query_timeout 500
|
||||
|
||||
@impl true
|
||||
def filter(%{"actor" => actor} = object) do
|
||||
def filter(%{"actor" => actor} = activity) do
|
||||
actor_info = URI.parse(actor)
|
||||
|
||||
with {:ok, object} <- check_rbl(actor_info, object) do
|
||||
{:ok, object}
|
||||
with {:ok, activity} <- check_rbl(actor_info, activity) do
|
||||
{:ok, activity}
|
||||
else
|
||||
_ -> {:reject, "[DNSRBLPolicy]"}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
|
|||
}
|
||||
end
|
||||
|
||||
defp check_rbl(%{host: actor_host}, object) do
|
||||
defp check_rbl(%{host: actor_host}, activity) do
|
||||
with false <- match?(^actor_host, Pleroma.Web.Endpoint.host()),
|
||||
zone when not is_nil(zone) <- Keyword.get(Config.get([:mrf_dnsrbl]), :zone) do
|
||||
query =
|
||||
|
@ -100,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
|
|||
rbl_response = rblquery(query)
|
||||
|
||||
if Enum.empty?(rbl_response) do
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
else
|
||||
Task.start(fn ->
|
||||
reason =
|
||||
|
@ -117,7 +117,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DNSRBLPolicy do
|
|||
:error
|
||||
end
|
||||
else
|
||||
_ -> {:ok, object}
|
||||
_ -> {:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
|
|||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
@impl true
|
||||
def filter(object) do
|
||||
Logger.debug("REJECTING #{inspect(object)}")
|
||||
{:reject, object}
|
||||
def filter(activity) do
|
||||
Logger.debug("REJECTING #{inspect(activity)}")
|
||||
{:reject, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -28,11 +28,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_shortcode], [])
|
||||
end
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def history_awareness, do: :manual
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = message)
|
||||
@impl true
|
||||
def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = activity)
|
||||
when type in ["Create", "Update"] and objtype in Pleroma.Constants.status_object_types() do
|
||||
with {:ok, object} <-
|
||||
Updater.do_with_history(object, fn object ->
|
||||
|
@ -42,13 +42,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
Updater.do_with_history(object, fn object ->
|
||||
{:ok, process_remove(object, :shortcode, config_remove_shortcode())}
|
||||
end),
|
||||
activity <- Map.put(message, "object", object),
|
||||
activity <- Map.put(activity, "object", object),
|
||||
activity <- maybe_delist(activity) do
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def filter(%{"type" => type} = object) when type in Pleroma.Constants.actor_types() do
|
||||
with object <- process_remove(object, :url, config_remove_url()),
|
||||
object <- process_remove(object, :shortcode, config_remove_shortcode()) do
|
||||
|
@ -56,7 +56,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def filter(%{"type" => "EmojiReact"} = object) do
|
||||
with {:ok, _} <-
|
||||
matched_emoji_checker(config_remove_url(), config_remove_shortcode()).(object) do
|
||||
|
@ -67,9 +67,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
def filter(message) do
|
||||
{:ok, message}
|
||||
@impl true
|
||||
def filter(activity) do
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
defp match_string?(string, pattern) when is_binary(pattern) do
|
||||
|
@ -214,7 +214,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
)
|
||||
end
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def describe do
|
||||
mrf_emoji =
|
||||
Pleroma.Config.get(:mrf_emoji, [])
|
||||
|
@ -226,7 +226,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
{:ok, %{mrf_emoji: mrf_emoji}}
|
||||
end
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def config_description do
|
||||
%{
|
||||
key: :mrf_emoji,
|
||||
|
@ -239,7 +239,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
key: :remove_url,
|
||||
type: {:list, :string},
|
||||
description: """
|
||||
A list of patterns which result in emoji whose URL matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
|
||||
A list of patterns which result in emoji whose URL matches being removed from the activity. This will apply to statuses, emoji reactions, and user profiles.
|
||||
|
||||
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||
""",
|
||||
|
@ -249,7 +249,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
key: :remove_shortcode,
|
||||
type: {:list, :string},
|
||||
description: """
|
||||
A list of patterns which result in emoji whose shortcode matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
|
||||
A list of patterns which result in emoji whose shortcode matches being removed from the activity. This will apply to statuses, emoji reactions, and user profiles.
|
||||
|
||||
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||
""",
|
||||
|
@ -259,7 +259,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
key: :federated_timeline_removal_url,
|
||||
type: {:list, :string},
|
||||
description: """
|
||||
A list of patterns which result in message with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
|
||||
A list of patterns which result in activity with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
|
||||
|
||||
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||
""",
|
||||
|
@ -269,7 +269,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
|
|||
key: :federated_timeline_removal_shortcode,
|
||||
type: {:list, :string},
|
||||
description: """
|
||||
A list of patterns which result in message with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
|
||||
A list of patterns which result in activities with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
|
||||
|
||||
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||
""",
|
||||
|
|
|
@ -29,19 +29,19 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
|
|||
|
||||
def filter_by_summary(_in_reply_to, child), do: child
|
||||
|
||||
def filter(%{"type" => type, "object" => child_object} = object)
|
||||
when type in ["Create", "Update"] and is_map(child_object) do
|
||||
def filter(%{"type" => type, "object" => object} = activity)
|
||||
when type in ["Create", "Update"] and is_map(object) do
|
||||
child =
|
||||
child_object["inReplyTo"]
|
||||
object["inReplyTo"]
|
||||
|> Object.normalize(fetch: false)
|
||||
|> filter_by_summary(child_object)
|
||||
|> filter_by_summary(object)
|
||||
|
||||
object = Map.put(object, "object", child)
|
||||
activity = Map.put(activity, "object", child)
|
||||
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
53
lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex
Normal file
53
lib/pleroma/web/activity_pub/mrf/fo_direct_reply.ex
Normal file
|
@ -0,0 +1,53 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.FODirectReply do
|
||||
@moduledoc """
|
||||
FODirectReply alters the scope of replies to activities which are Followers Only to be Direct. The purpose of this policy is to prevent broken threads for followers of the reply author because their response was to a user that they are not also following.
|
||||
"""
|
||||
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
@impl true
|
||||
def filter(
|
||||
%{
|
||||
"type" => "Create",
|
||||
"to" => to,
|
||||
"object" => %{
|
||||
"actor" => actor,
|
||||
"type" => "Note",
|
||||
"inReplyTo" => in_reply_to
|
||||
}
|
||||
} = activity
|
||||
) do
|
||||
with true <- is_binary(in_reply_to),
|
||||
%User{follower_address: followers_collection, local: true} <- User.get_by_ap_id(actor),
|
||||
%Object{} = in_reply_to_object <- Object.get_by_ap_id(in_reply_to),
|
||||
"private" <- Visibility.get_visibility(in_reply_to_object) do
|
||||
direct_to = to -- [followers_collection]
|
||||
|
||||
updated_activity =
|
||||
activity
|
||||
|> Map.put("cc", [])
|
||||
|> Map.put("to", direct_to)
|
||||
|> Map.put("directMessage", true)
|
||||
|> put_in(["object", "cc"], [])
|
||||
|> put_in(["object", "to"], direct_to)
|
||||
|
||||
{:ok, updated_activity}
|
||||
else
|
||||
_ -> {:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
|
@ -11,12 +11,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
|
|||
require Logger
|
||||
|
||||
@impl true
|
||||
def filter(message) do
|
||||
def filter(activity) do
|
||||
with follower_nickname <- Config.get([:mrf_follow_bot, :follower_nickname]),
|
||||
%User{actor_type: "Service"} = follower <-
|
||||
User.get_cached_by_nickname(follower_nickname),
|
||||
%{"type" => "Create", "object" => %{"type" => "Note"}} <- message do
|
||||
try_follow(follower, message)
|
||||
%{"type" => "Create", "object" => %{"type" => "Note"}} <- activity do
|
||||
try_follow(follower, activity)
|
||||
else
|
||||
nil ->
|
||||
Logger.warning(
|
||||
|
@ -24,17 +24,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
|
|||
account does not exist, or the account is not correctly configured as a bot."
|
||||
)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
|
||||
_ ->
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp try_follow(follower, message) do
|
||||
to = Map.get(message, "to", [])
|
||||
cc = Map.get(message, "cc", [])
|
||||
actor = [message["actor"]]
|
||||
defp try_follow(follower, activity) do
|
||||
to = Map.get(activity, "to", [])
|
||||
cc = Map.get(activity, "cc", [])
|
||||
actor = [activity["actor"]]
|
||||
|
||||
Enum.concat([to, cc, actor])
|
||||
|> List.flatten()
|
||||
|
@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.FollowBotPolicy do
|
|||
end
|
||||
end)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -22,7 +22,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do
|
|||
"cc" => cc,
|
||||
"actor" => actor,
|
||||
"object" => object
|
||||
} = message
|
||||
} = activity
|
||||
) do
|
||||
user = User.get_cached_by_ap_id(actor)
|
||||
isbot = check_if_bot(user)
|
||||
|
@ -36,20 +36,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy do
|
|||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|
||||
message =
|
||||
message
|
||||
activity =
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|> Map.put("object", object)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMention do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -79,18 +79,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
|
|||
%{
|
||||
"type" => type,
|
||||
"object" => %{"type" => "Note", "to" => to, "inReplyTo" => in_reply_to}
|
||||
} = object
|
||||
} = activity
|
||||
)
|
||||
when type in ["Create", "Update"] and is_list(to) and is_binary(in_reply_to) do
|
||||
# image-only posts from pleroma apparently reach this MRF without the content field
|
||||
content = object["object"]["content"] || ""
|
||||
content = activity["object"]["content"] || ""
|
||||
|
||||
# Get the replied-to user for sorting
|
||||
replied_to_user = get_replied_to_user(object["object"])
|
||||
replied_to_user = get_replied_to_user(activity["object"])
|
||||
|
||||
mention_users =
|
||||
to
|
||||
|> clean_recipients(object)
|
||||
|> clean_recipients(activity)
|
||||
|> Enum.map(&User.get_cached_by_ap_id/1)
|
||||
|> Enum.reject(&is_nil/1)
|
||||
|> sort_replied_user(replied_to_user)
|
||||
|
@ -126,11 +126,11 @@ defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
|
|||
content
|
||||
end
|
||||
|
||||
{:ok, put_in(object["object"]["content"], content)}
|
||||
{:ok, put_in(activity["object"]["content"], content)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
|
|||
alias Pleroma.Object
|
||||
|
||||
@moduledoc """
|
||||
Reject, TWKN-remove or Set-Sensitive messages with specific hashtags (without the leading #)
|
||||
Reject, TWKN-remove or Set-Sensitive activities with specific hashtags (without the leading #)
|
||||
|
||||
Note: This MRF Policy is always enabled, if you want to disable it you have to set empty lists.
|
||||
"""
|
||||
|
@ -19,40 +19,40 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
|
|||
@impl true
|
||||
def history_awareness, do: :manual
|
||||
|
||||
defp check_reject(message, hashtags) do
|
||||
defp check_reject(activity, hashtags) do
|
||||
if Enum.any?(Config.get([:mrf_hashtag, :reject]), fn match -> match in hashtags end) do
|
||||
{:reject, "[HashtagPolicy] Matches with rejected keyword"}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_ftl_removal(%{"to" => to} = message, hashtags) do
|
||||
defp check_ftl_removal(%{"to" => to} = activity, hashtags) do
|
||||
if Pleroma.Constants.as_public() in to and
|
||||
Enum.any?(Config.get([:mrf_hashtag, :federated_timeline_removal]), fn match ->
|
||||
match in hashtags
|
||||
end) do
|
||||
to = List.delete(to, Pleroma.Constants.as_public())
|
||||
cc = [Pleroma.Constants.as_public() | message["cc"] || []]
|
||||
cc = [Pleroma.Constants.as_public() | activity["cc"] || []]
|
||||
|
||||
message =
|
||||
message
|
||||
activity =
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|> Kernel.put_in(["object", "to"], to)
|
||||
|> Kernel.put_in(["object", "cc"], cc)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_ftl_removal(message, _hashtags), do: {:ok, message}
|
||||
defp check_ftl_removal(activity, _hashtags), do: {:ok, activity}
|
||||
|
||||
defp check_sensitive(message) do
|
||||
defp check_sensitive(activity) do
|
||||
{:ok, new_object} =
|
||||
Object.Updater.do_with_history(message["object"], fn object ->
|
||||
Object.Updater.do_with_history(activity["object"], fn object ->
|
||||
hashtags = Object.hashtags(%Object{data: object})
|
||||
|
||||
if Enum.any?(Config.get([:mrf_hashtag, :sensitive]), fn match -> match in hashtags end) do
|
||||
|
@ -62,11 +62,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
|
|||
end
|
||||
end)
|
||||
|
||||
{:ok, Map.put(message, "object", new_object)}
|
||||
{:ok, Map.put(activity, "object", new_object)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => type, "object" => object} = message) when type in ["Create", "Update"] do
|
||||
def filter(%{"type" => type, "object" => object} = activity)
|
||||
when type in ["Create", "Update"] do
|
||||
history_items =
|
||||
with %{"formerRepresentations" => %{"orderedItems" => items}} <- object do
|
||||
items
|
||||
|
@ -82,23 +83,23 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
|
|||
hashtags = Object.hashtags(%Object{data: object}) ++ historical_hashtags
|
||||
|
||||
if hashtags != [] do
|
||||
with {:ok, message} <- check_reject(message, hashtags),
|
||||
{:ok, message} <-
|
||||
with {:ok, activity} <- check_reject(activity, hashtags),
|
||||
{:ok, activity} <-
|
||||
(if type == "Create" do
|
||||
check_ftl_removal(message, hashtags)
|
||||
check_ftl_removal(activity, hashtags)
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end),
|
||||
{:ok, message} <- check_sensitive(message) do
|
||||
{:ok, message}
|
||||
{:ok, activity} <- check_sensitive(activity) do
|
||||
{:ok, activity}
|
||||
end
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
@ -120,21 +121,21 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
|
|||
%{
|
||||
key: :reject,
|
||||
type: {:list, :string},
|
||||
description: "A list of hashtags which result in message being rejected.",
|
||||
description: "A list of hashtags which result in the activity being rejected.",
|
||||
suggestions: ["foo"]
|
||||
},
|
||||
%{
|
||||
key: :federated_timeline_removal,
|
||||
type: {:list, :string},
|
||||
description:
|
||||
"A list of hashtags which result in message being removed from federated timelines (a.k.a unlisted).",
|
||||
"A list of hashtags which result in the activity being removed from federated timelines (a.k.a unlisted).",
|
||||
suggestions: ["foo"]
|
||||
},
|
||||
%{
|
||||
key: :sensitive,
|
||||
type: {:list, :string},
|
||||
description:
|
||||
"A list of hashtags which result in message being set as sensitive (a.k.a NSFW/R-18)",
|
||||
"A list of hashtags which result in the activity being set as sensitive (a.k.a NSFW/R-18)",
|
||||
suggestions: ["nsfw", "r18"]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -7,54 +7,54 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
|
|||
|
||||
require Pleroma.Constants
|
||||
|
||||
@moduledoc "Block messages with too much mentions (configurable)"
|
||||
@moduledoc "Block activities with too much mentions (configurable)"
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
defp delist_message(message, threshold) when threshold > 0 do
|
||||
follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
|
||||
to = message["to"] || []
|
||||
cc = message["cc"] || []
|
||||
defp delist_activity(activity, threshold) when threshold > 0 do
|
||||
follower_collection = User.get_cached_by_ap_id(activity["actor"]).follower_address
|
||||
to = activity["to"] || []
|
||||
cc = activity["cc"] || []
|
||||
|
||||
follower_collection? = Enum.member?(to ++ cc, follower_collection)
|
||||
|
||||
message =
|
||||
case get_recipient_count(message) do
|
||||
activity =
|
||||
case get_recipient_count(activity) do
|
||||
{:public, recipients}
|
||||
when follower_collection? and recipients > threshold ->
|
||||
message
|
||||
activity
|
||||
|> Map.put("to", [follower_collection])
|
||||
|> Map.put("cc", [Pleroma.Constants.as_public()])
|
||||
|
||||
{:public, recipients} when recipients > threshold ->
|
||||
message
|
||||
activity
|
||||
|> Map.put("to", [])
|
||||
|> Map.put("cc", [Pleroma.Constants.as_public()])
|
||||
|
||||
_ ->
|
||||
message
|
||||
activity
|
||||
end
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
defp delist_message(message, _threshold), do: {:ok, message}
|
||||
defp delist_activity(activity, _threshold), do: {:ok, activity}
|
||||
|
||||
defp reject_message(message, threshold) when threshold > 0 do
|
||||
with {_, recipients} <- get_recipient_count(message) do
|
||||
defp reject_activity(activity, threshold) when threshold > 0 do
|
||||
with {_, recipients} <- get_recipient_count(activity) do
|
||||
if recipients > threshold do
|
||||
{:reject, "[HellthreadPolicy] #{recipients} recipients is over the limit of #{threshold}"}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp reject_message(message, _threshold), do: {:ok, message}
|
||||
defp reject_activity(activity, _threshold), do: {:ok, activity}
|
||||
|
||||
defp get_recipient_count(message) do
|
||||
recipients = (message["to"] || []) ++ (message["cc"] || [])
|
||||
follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
|
||||
defp get_recipient_count(activity) do
|
||||
recipients = (activity["to"] || []) ++ (activity["cc"] || [])
|
||||
follower_collection = User.get_cached_by_ap_id(activity["actor"]).follower_address
|
||||
|
||||
if Enum.member?(recipients, Pleroma.Constants.as_public()) do
|
||||
recipients =
|
||||
|
@ -73,7 +73,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = message)
|
||||
def filter(%{"type" => "Create", "object" => %{"type" => object_type}} = activity)
|
||||
when object_type in ~w{Note Article} do
|
||||
reject_threshold =
|
||||
Pleroma.Config.get(
|
||||
|
@ -83,16 +83,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
|
|||
|
||||
delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
|
||||
|
||||
with {:ok, message} <- reject_message(message, reject_threshold),
|
||||
{:ok, message} <- delist_message(message, delist_threshold) do
|
||||
{:ok, message}
|
||||
with {:ok, activity} <- reject_activity(activity, reject_threshold),
|
||||
{:ok, activity} <- delist_activity(activity, delist_threshold) do
|
||||
{:ok, activity}
|
||||
else
|
||||
e -> e
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe,
|
||||
|
@ -104,13 +104,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
|
|||
key: :mrf_hellthread,
|
||||
related_policy: "Pleroma.Web.ActivityPub.MRF.HellthreadPolicy",
|
||||
label: "MRF Hellthread",
|
||||
description: "Block messages with excessive user mentions",
|
||||
description: "Block activities with excessive user mentions",
|
||||
children: [
|
||||
%{
|
||||
key: :delist_threshold,
|
||||
type: :integer,
|
||||
description:
|
||||
"Number of mentioned users after which the message gets removed from timelines and" <>
|
||||
"Number of mentioned users after which the activity gets removed from timelines and" <>
|
||||
"disables notifications. Set to 0 to disable.",
|
||||
suggestions: [10]
|
||||
},
|
||||
|
@ -118,7 +118,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
|
|||
key: :reject_threshold,
|
||||
type: :integer,
|
||||
description:
|
||||
"Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.",
|
||||
"Number of mentioned users after which the activity gets rejected. Set to 0 to disable.",
|
||||
suggestions: [20]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -48,12 +48,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def history_awareness, do: :auto
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
|
||||
alias Pleroma.Web.ActivityPub.MRF.Utils
|
||||
|
||||
@moduledoc "Reject or Word-Replace messages with a keyword or regex"
|
||||
@moduledoc "Reject or Word-Replace activities with a keyword or regex"
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
|
@ -25,7 +25,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
|> Enum.join("\n")
|
||||
end
|
||||
|
||||
defp check_reject(%{"object" => %{} = object} = message) do
|
||||
defp check_reject(%{"object" => %{} = object} = activity) do
|
||||
with {:ok, _new_object} <-
|
||||
Pleroma.Object.Updater.do_with_history(object, fn object ->
|
||||
payload = object_payload(object)
|
||||
|
@ -35,16 +35,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
end) do
|
||||
{:reject, "[KeywordPolicy] Matches with rejected keyword"}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end) do
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
e -> e
|
||||
end
|
||||
end
|
||||
|
||||
defp check_ftl_removal(%{"type" => "Create", "to" => to, "object" => %{} = object} = message) do
|
||||
defp check_ftl_removal(%{"type" => "Create", "to" => to, "object" => %{} = object} = activity) do
|
||||
check_keyword = fn object ->
|
||||
payload = object_payload(object)
|
||||
|
||||
|
@ -67,24 +67,24 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
|
||||
if Pleroma.Constants.as_public() in to and should_delist?.(object) do
|
||||
to = List.delete(to, Pleroma.Constants.as_public())
|
||||
cc = [Pleroma.Constants.as_public() | message["cc"] || []]
|
||||
cc = [Pleroma.Constants.as_public() | activity["cc"] || []]
|
||||
|
||||
message =
|
||||
message
|
||||
activity =
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_ftl_removal(message) do
|
||||
{:ok, message}
|
||||
defp check_ftl_removal(activity) do
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
defp check_replace(%{"object" => %{} = object} = message) do
|
||||
defp check_replace(%{"object" => %{} = object} = activity) do
|
||||
replace_kw = fn object ->
|
||||
["content", "name", "summary"]
|
||||
|> Enum.filter(fn field -> Map.has_key?(object, field) && object[field] end)
|
||||
|
@ -103,18 +103,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
|
||||
{:ok, object} = Pleroma.Object.Updater.do_with_history(object, replace_kw)
|
||||
|
||||
message = Map.put(message, "object", object)
|
||||
activity = Map.put(activity, "object", object)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => type, "object" => %{"content" => _content}} = message)
|
||||
def filter(%{"type" => type, "object" => %{"content" => _content}} = activity)
|
||||
when type in ["Create", "Update"] do
|
||||
with {:ok, message} <- check_reject(message),
|
||||
{:ok, message} <- check_ftl_removal(message),
|
||||
{:ok, message} <- check_replace(message) do
|
||||
{:ok, message}
|
||||
with {:ok, activity} <- check_reject(activity),
|
||||
{:ok, activity} <- check_ftl_removal(activity),
|
||||
{:ok, activity} <- check_replace(activity) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, nil} -> {:reject, "[KeywordPolicy] "}
|
||||
{:reject, _} = e -> e
|
||||
|
@ -123,7 +123,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
@ -154,13 +154,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
related_policy: "Pleroma.Web.ActivityPub.MRF.KeywordPolicy",
|
||||
label: "MRF Keyword",
|
||||
description:
|
||||
"Reject or Word-Replace messages matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
|
||||
"Reject or Word-Replace activities matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
|
||||
children: [
|
||||
%{
|
||||
key: :reject,
|
||||
type: {:list, :string},
|
||||
description: """
|
||||
A list of patterns which result in message being rejected.
|
||||
A list of patterns which result in the activity being rejected.
|
||||
|
||||
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||
""",
|
||||
|
@ -170,7 +170,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
key: :federated_timeline_removal,
|
||||
type: {:list, :string},
|
||||
description: """
|
||||
A list of patterns which result in message being removed from federated timelines (a.k.a unlisted).
|
||||
A list of patterns which result in the activity being removed from federated timelines (a.k.a unlisted).
|
||||
|
||||
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
|
||||
""",
|
||||
|
|
|
@ -31,7 +31,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
|
|||
HTTP.get(url, [], http_client_opts)
|
||||
end
|
||||
|
||||
defp preload(%{"object" => %{"attachment" => attachments}} = _message) do
|
||||
defp preload(%{"object" => %{"attachment" => attachments}} = _activity) do
|
||||
Enum.each(attachments, fn
|
||||
%{"url" => url} when is_list(url) ->
|
||||
url
|
||||
|
@ -49,15 +49,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => type, "object" => %{"attachment" => attachments} = _object} = message)
|
||||
def filter(%{"type" => type, "object" => %{"attachment" => attachments} = _object} = activity)
|
||||
when type in ["Create", "Update"] and is_list(attachments) and length(attachments) > 0 do
|
||||
preload(message)
|
||||
preload(activity)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -3,25 +3,25 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
|
||||
@moduledoc "Block messages which mention a user"
|
||||
@moduledoc "Block activities which mention a user"
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Create"} = message) do
|
||||
def filter(%{"type" => "Create"} = activity) do
|
||||
reject_actors = Pleroma.Config.get([:mrf_mention, :actors], [])
|
||||
recipients = (message["to"] || []) ++ (message["cc"] || [])
|
||||
recipients = (activity["to"] || []) ++ (activity["cc"] || [])
|
||||
|
||||
if rejected_mention =
|
||||
Enum.find(recipients, fn recipient -> Enum.member?(reject_actors, recipient) end) do
|
||||
{:reject, "[MentionPolicy] Rejected for mention of #{rejected_mention}"}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
|
|||
key: :mrf_mention,
|
||||
related_policy: "Pleroma.Web.ActivityPub.MRF.MentionPolicy",
|
||||
label: "MRF Mention",
|
||||
description: "Block messages which mention a specific user",
|
||||
description: "Block activities which mention a specific user",
|
||||
children: [
|
||||
%{
|
||||
key: :actors,
|
||||
|
|
|
@ -9,20 +9,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoEmptyPolicy do
|
|||
alias Pleroma.Web.Endpoint
|
||||
|
||||
@impl true
|
||||
def filter(%{"actor" => actor} = object) do
|
||||
def filter(%{"actor" => actor} = activity) do
|
||||
with true <- local?(actor),
|
||||
true <- eligible_type?(object),
|
||||
true <- note?(object),
|
||||
false <- has_attachment?(object),
|
||||
true <- only_mentions?(object) do
|
||||
true <- eligible_type?(activity),
|
||||
true <- note?(activity),
|
||||
false <- has_attachment?(activity),
|
||||
true <- only_mentions?(activity) do
|
||||
{:reject, "[NoEmptyPolicy]"}
|
||||
else
|
||||
_ ->
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
defp local?(actor) do
|
||||
if actor |> String.starts_with?("#{Endpoint.url()}") do
|
||||
|
|
|
@ -7,8 +7,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
|
|||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
@impl true
|
||||
def filter(object) do
|
||||
{:ok, object}
|
||||
def filter(activity) do
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -13,15 +13,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
|
|||
def filter(
|
||||
%{
|
||||
"type" => type,
|
||||
"object" => %{"content" => content, "attachment" => _} = _child_object
|
||||
} = object
|
||||
"object" => %{"content" => content, "attachment" => _} = _object
|
||||
} = activity
|
||||
)
|
||||
when type in ["Create", "Update"] and content in [".", "<p>.</p>"] do
|
||||
{:ok, put_in(object, ["object", "content"], "")}
|
||||
{:ok, put_in(activity, ["object", "content"], "")}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -12,20 +12,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
|
|||
def history_awareness, do: :auto
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => type, "object" => child_object} = object)
|
||||
def filter(%{"type" => type, "object" => object} = activity)
|
||||
when type in ["Create", "Update"] do
|
||||
scrub_policy = Pleroma.Config.get([:mrf_normalize_markup, :scrub_policy])
|
||||
|
||||
content =
|
||||
child_object["content"]
|
||||
object["content"]
|
||||
|> HTML.filter_tags(scrub_policy)
|
||||
|
||||
object = put_in(object, ["object", "content"], content)
|
||||
activity = put_in(activity, ["object", "content"], content)
|
||||
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -122,52 +122,52 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
def check_object_nsfw(%{"object" => %{} = child_object} = object) do
|
||||
case check_object_nsfw(child_object) do
|
||||
{:sfw, _} -> {:sfw, object}
|
||||
{:nsfw, _} -> {:nsfw, object}
|
||||
def check_object_nsfw(%{"object" => %{} = object} = activity) do
|
||||
case check_object_nsfw(object) do
|
||||
{:sfw, _} -> {:sfw, activity}
|
||||
{:nsfw, _} -> {:nsfw, activity}
|
||||
end
|
||||
end
|
||||
|
||||
def check_object_nsfw(object), do: {:sfw, object}
|
||||
|
||||
@impl true
|
||||
def filter(object) do
|
||||
with {:sfw, object} <- check_object_nsfw(object) do
|
||||
{:ok, object}
|
||||
def filter(activity) do
|
||||
with {:sfw, activity} <- check_object_nsfw(activity) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:nsfw, _data} -> handle_nsfw(object)
|
||||
{:nsfw, _data} -> handle_nsfw(activity)
|
||||
end
|
||||
end
|
||||
|
||||
defp handle_nsfw(object) do
|
||||
defp handle_nsfw(activity) do
|
||||
if Config.get([@policy, :reject]) do
|
||||
{:reject, object}
|
||||
{:reject, activity}
|
||||
else
|
||||
{:ok,
|
||||
object
|
||||
activity
|
||||
|> maybe_unlist()
|
||||
|> maybe_mark_sensitive()}
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_unlist(object) do
|
||||
defp maybe_unlist(activity) do
|
||||
if Config.get([@policy, :unlist]) do
|
||||
unlist(object)
|
||||
unlist(activity)
|
||||
else
|
||||
object
|
||||
activity
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_mark_sensitive(object) do
|
||||
defp maybe_mark_sensitive(activity) do
|
||||
if Config.get([@policy, :mark_sensitive]) do
|
||||
mark_sensitive(object)
|
||||
mark_sensitive(activity)
|
||||
else
|
||||
object
|
||||
activity
|
||||
end
|
||||
end
|
||||
|
||||
def unlist(%{"to" => to, "cc" => cc, "actor" => actor} = object) do
|
||||
def unlist(%{"to" => to, "cc" => cc, "actor" => actor} = activity) do
|
||||
with %User{} = user <- User.get_cached_by_ap_id(actor) do
|
||||
to =
|
||||
[user.follower_address | to]
|
||||
|
@ -179,7 +179,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
|
|||
|> List.delete(user.follower_address)
|
||||
|> Enum.uniq()
|
||||
|
||||
object
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
else
|
||||
|
@ -187,14 +187,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.NsfwApiPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
def mark_sensitive(%{"object" => child_object} = object) when is_map(child_object) do
|
||||
Map.put(object, "object", mark_sensitive(child_object))
|
||||
def mark_sensitive(%{"object" => object} = activity) when is_map(object) do
|
||||
Map.put(activity, "object", mark_sensitive(object))
|
||||
end
|
||||
|
||||
def mark_sensitive(object) when is_map(object) do
|
||||
tags = (object["tag"] || []) ++ ["nsfw"]
|
||||
def mark_sensitive(activity) when is_map(activity) do
|
||||
tags = (activity["tag"] || []) ++ ["nsfw"]
|
||||
|
||||
object
|
||||
activity
|
||||
|> Map.put("tag", tags)
|
||||
|> Map.put("sensitive", true)
|
||||
end
|
||||
|
|
|
@ -11,12 +11,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
|
|||
@moduledoc "Filter activities depending on their age"
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
defp check_date(%{"object" => %{"published" => published}} = message) do
|
||||
defp check_date(%{"object" => %{"published" => published}} = activity) do
|
||||
with %DateTime{} = now <- DateTime.utc_now(),
|
||||
{:ok, %DateTime{} = then, _} <- DateTime.from_iso8601(published),
|
||||
max_ttl <- Config.get([:mrf_object_age, :threshold]),
|
||||
{:ttl, false} <- {:ttl, DateTime.diff(now, then) > max_ttl} do
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:ttl, true} ->
|
||||
{:reject, nil}
|
||||
|
@ -26,73 +26,73 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
|
|||
end
|
||||
end
|
||||
|
||||
defp check_reject(message, actions) do
|
||||
defp check_reject(activity, actions) do
|
||||
if :reject in actions do
|
||||
{:reject, "[ObjectAgePolicy]"}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_delist(message, actions) do
|
||||
defp check_delist(activity, actions) do
|
||||
if :delist in actions do
|
||||
with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
|
||||
with %User{} = user <- User.get_cached_by_ap_id(activity["actor"]) do
|
||||
to =
|
||||
List.delete(message["to"] || [], Pleroma.Constants.as_public()) ++
|
||||
List.delete(activity["to"] || [], Pleroma.Constants.as_public()) ++
|
||||
[user.follower_address]
|
||||
|
||||
cc =
|
||||
List.delete(message["cc"] || [], user.follower_address) ++
|
||||
List.delete(activity["cc"] || [], user.follower_address) ++
|
||||
[Pleroma.Constants.as_public()]
|
||||
|
||||
message =
|
||||
message
|
||||
activity =
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|> Kernel.put_in(["object", "to"], to)
|
||||
|> Kernel.put_in(["object", "cc"], cc)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
_e ->
|
||||
{:reject, "[ObjectAgePolicy] Unhandled error"}
|
||||
end
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_strip_followers(message, actions) do
|
||||
defp check_strip_followers(activity, actions) do
|
||||
if :strip_followers in actions do
|
||||
with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
|
||||
to = List.delete(message["to"] || [], user.follower_address)
|
||||
cc = List.delete(message["cc"] || [], user.follower_address)
|
||||
with %User{} = user <- User.get_cached_by_ap_id(activity["actor"]) do
|
||||
to = List.delete(activity["to"] || [], user.follower_address)
|
||||
cc = List.delete(activity["cc"] || [], user.follower_address)
|
||||
|
||||
message =
|
||||
message
|
||||
activity =
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|> Kernel.put_in(["object", "to"], to)
|
||||
|> Kernel.put_in(["object", "cc"], cc)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
_e ->
|
||||
{:reject, "[ObjectAgePolicy] Unhandled error"}
|
||||
end
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Create", "object" => %{"published" => _}} = message) do
|
||||
def filter(%{"type" => "Create", "object" => %{"published" => _}} = activity) do
|
||||
with actions <- Config.get([:mrf_object_age, :actions]),
|
||||
{:reject, _} <- check_date(message),
|
||||
{:ok, message} <- check_reject(message, actions),
|
||||
{:ok, message} <- check_delist(message, actions),
|
||||
{:ok, message} <- check_strip_followers(message, actions) do
|
||||
{:ok, message}
|
||||
{:reject, _} <- check_date(activity),
|
||||
{:ok, activity} <- check_reject(activity, actions),
|
||||
{:ok, activity} <- check_delist(activity, actions),
|
||||
{:ok, activity} <- check_strip_followers(activity, actions) do
|
||||
{:ok, activity}
|
||||
else
|
||||
# check_date() is allowed to short-circuit the pipeline
|
||||
e -> e
|
||||
|
@ -100,7 +100,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
@ -131,8 +131,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy do
|
|||
type: {:list, :atom},
|
||||
description:
|
||||
"A list of actions to apply to the post. `:delist` removes the post from public timelines; " <>
|
||||
"`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines, additionally for followers-only it degrades to a direct message; " <>
|
||||
"`:reject` rejects the message entirely",
|
||||
"`:strip_followers` removes followers from the ActivityPub recipient list ensuring they won't be delivered to home timelines, additionally for followers-only it degrades to a direct activity; " <>
|
||||
"`:reject` rejects the activity entirely",
|
||||
suggestions: [:delist, :strip_followers, :reject]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.Policy do
|
||||
@callback filter(map()) :: {:ok | :reject, map()}
|
||||
@callback filter(Pleroma.Activity.t()) :: {:ok | :reject, Pleroma.Activity.t()}
|
||||
@callback describe() :: {:ok | :error, map()}
|
||||
@callback config_description() :: %{
|
||||
optional(:children) => [map()],
|
||||
|
|
60
lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
Normal file
60
lib/pleroma/web/activity_pub/mrf/quiet_reply.ex
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.QuietReply do
|
||||
@moduledoc """
|
||||
QuietReply alters the scope of activities from local users when replying by enforcing them to be "Unlisted" or "Quiet Public". This delivers the activity to all the expected recipients and instances, but it will not be published in the Federated / The Whole Known Network timelines. It will still be published to the Home timelines of the user's followers and visible to anyone who opens the thread.
|
||||
"""
|
||||
require Pleroma.Constants
|
||||
|
||||
alias Pleroma.User
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
@impl true
|
||||
def history_awareness, do: :auto
|
||||
|
||||
@impl true
|
||||
def filter(
|
||||
%{
|
||||
"type" => "Create",
|
||||
"to" => to,
|
||||
"cc" => cc,
|
||||
"object" => %{
|
||||
"actor" => actor,
|
||||
"type" => "Note",
|
||||
"inReplyTo" => in_reply_to
|
||||
}
|
||||
} = activity
|
||||
) do
|
||||
with true <- is_binary(in_reply_to),
|
||||
false <- match?([], cc),
|
||||
%User{follower_address: followers_collection, local: true} <-
|
||||
User.get_by_ap_id(actor) do
|
||||
updated_to =
|
||||
to
|
||||
|> Kernel.++([followers_collection])
|
||||
|> Kernel.--([Pleroma.Constants.as_public()])
|
||||
|
||||
updated_cc = [Pleroma.Constants.as_public()]
|
||||
|
||||
updated_activity =
|
||||
activity
|
||||
|> Map.put("to", updated_to)
|
||||
|> Map.put("cc", updated_cc)
|
||||
|> put_in(["object", "to"], updated_to)
|
||||
|> put_in(["object", "cc"], updated_cc)
|
||||
|
||||
{:ok, updated_activity}
|
||||
else
|
||||
_ -> {:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
|
@ -10,18 +10,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do
|
|||
|
||||
require Pleroma.Constants
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
|
||||
{:ok, Map.put(activity, "object", filter_object(object))}
|
||||
end
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
def filter(object), do: {:ok, object}
|
||||
@impl true
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
||||
@impl Pleroma.Web.ActivityPub.MRF.Policy
|
||||
@impl true
|
||||
def history_awareness, do: :auto
|
||||
|
||||
defp filter_object(%{"quoteUrl" => quote_url} = object) do
|
||||
|
|
|
@ -13,20 +13,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
|
||||
require Pleroma.Constants
|
||||
|
||||
defp check_accept(%{host: actor_host} = _actor_info, object) do
|
||||
defp check_accept(%{host: actor_host} = _actor_info, activity) do
|
||||
accepts =
|
||||
instance_list(:accept)
|
||||
|> MRF.subdomains_regex()
|
||||
|
||||
cond do
|
||||
accepts == [] -> {:ok, object}
|
||||
actor_host == Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, object}
|
||||
MRF.subdomain_match?(accepts, actor_host) -> {:ok, object}
|
||||
accepts == [] -> {:ok, activity}
|
||||
actor_host == Config.get([Pleroma.Web.Endpoint, :url, :host]) -> {:ok, activity}
|
||||
MRF.subdomain_match?(accepts, actor_host) -> {:ok, activity}
|
||||
true -> {:reject, "[SimplePolicy] host not in accept list"}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_reject(%{host: actor_host} = _actor_info, object) do
|
||||
defp check_reject(%{host: actor_host} = _actor_info, activity) do
|
||||
rejects =
|
||||
instance_list(:reject)
|
||||
|> MRF.subdomains_regex()
|
||||
|
@ -34,109 +34,109 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
if MRF.subdomain_match?(rejects, actor_host) do
|
||||
{:reject, "[SimplePolicy] host in reject list"}
|
||||
else
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_media_removal(
|
||||
%{host: actor_host} = _actor_info,
|
||||
%{"type" => type, "object" => %{"attachment" => child_attachment}} = object
|
||||
%{"type" => type, "object" => %{"attachment" => object_attachment}} = activity
|
||||
)
|
||||
when length(child_attachment) > 0 and type in ["Create", "Update"] do
|
||||
when length(object_attachment) > 0 and type in ["Create", "Update"] do
|
||||
media_removal =
|
||||
instance_list(:media_removal)
|
||||
|> MRF.subdomains_regex()
|
||||
|
||||
object =
|
||||
activity =
|
||||
if MRF.subdomain_match?(media_removal, actor_host) do
|
||||
child_object = Map.delete(object["object"], "attachment")
|
||||
Map.put(object, "object", child_object)
|
||||
object = Map.delete(activity["object"], "attachment")
|
||||
Map.put(activity, "object", object)
|
||||
else
|
||||
object
|
||||
activity
|
||||
end
|
||||
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
defp check_media_removal(_actor_info, object), do: {:ok, object}
|
||||
defp check_media_removal(_actor_info, activity), do: {:ok, activity}
|
||||
|
||||
defp check_media_nsfw(
|
||||
%{host: actor_host} = _actor_info,
|
||||
%{
|
||||
"type" => type,
|
||||
"object" => %{} = _child_object
|
||||
} = object
|
||||
"object" => %{} = _object
|
||||
} = activity
|
||||
)
|
||||
when type in ["Create", "Update"] do
|
||||
media_nsfw =
|
||||
instance_list(:media_nsfw)
|
||||
|> MRF.subdomains_regex()
|
||||
|
||||
object =
|
||||
activity =
|
||||
if MRF.subdomain_match?(media_nsfw, actor_host) do
|
||||
Kernel.put_in(object, ["object", "sensitive"], true)
|
||||
Kernel.put_in(activity, ["object", "sensitive"], true)
|
||||
else
|
||||
object
|
||||
activity
|
||||
end
|
||||
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
defp check_media_nsfw(_actor_info, object), do: {:ok, object}
|
||||
defp check_media_nsfw(_actor_info, activity), do: {:ok, activity}
|
||||
|
||||
defp check_ftl_removal(%{host: actor_host} = _actor_info, object) do
|
||||
defp check_ftl_removal(%{host: actor_host} = _actor_info, activity) do
|
||||
timeline_removal =
|
||||
instance_list(:federated_timeline_removal)
|
||||
|> MRF.subdomains_regex()
|
||||
|
||||
object =
|
||||
activity =
|
||||
with true <- MRF.subdomain_match?(timeline_removal, actor_host),
|
||||
user <- User.get_cached_by_ap_id(object["actor"]),
|
||||
true <- Pleroma.Constants.as_public() in object["to"] do
|
||||
to = List.delete(object["to"], Pleroma.Constants.as_public()) ++ [user.follower_address]
|
||||
user <- User.get_cached_by_ap_id(activity["actor"]),
|
||||
true <- Pleroma.Constants.as_public() in activity["to"] do
|
||||
to = List.delete(activity["to"], Pleroma.Constants.as_public()) ++ [user.follower_address]
|
||||
|
||||
cc = List.delete(object["cc"], user.follower_address) ++ [Pleroma.Constants.as_public()]
|
||||
cc = List.delete(activity["cc"], user.follower_address) ++ [Pleroma.Constants.as_public()]
|
||||
|
||||
object
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
else
|
||||
_ -> object
|
||||
_ -> activity
|
||||
end
|
||||
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
defp intersection(list1, list2) do
|
||||
list1 -- list1 -- list2
|
||||
end
|
||||
|
||||
defp check_followers_only(%{host: actor_host} = _actor_info, object) do
|
||||
defp check_followers_only(%{host: actor_host} = _actor_info, activity) do
|
||||
followers_only =
|
||||
instance_list(:followers_only)
|
||||
|> MRF.subdomains_regex()
|
||||
|
||||
object =
|
||||
activity =
|
||||
with true <- MRF.subdomain_match?(followers_only, actor_host),
|
||||
user <- User.get_cached_by_ap_id(object["actor"]) do
|
||||
user <- User.get_cached_by_ap_id(activity["actor"]) do
|
||||
# Don't use Map.get/3 intentionally, these must not be nil
|
||||
fixed_to = object["to"] || []
|
||||
fixed_cc = object["cc"] || []
|
||||
fixed_to = activity["to"] || []
|
||||
fixed_cc = activity["cc"] || []
|
||||
|
||||
to = FollowingRelationship.followers_ap_ids(user, fixed_to)
|
||||
cc = FollowingRelationship.followers_ap_ids(user, fixed_cc)
|
||||
|
||||
object
|
||||
activity
|
||||
|> Map.put("to", intersection([user.follower_address | to], fixed_to))
|
||||
|> Map.put("cc", intersection([user.follower_address | cc], fixed_cc))
|
||||
else
|
||||
_ -> object
|
||||
_ -> activity
|
||||
end
|
||||
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = object) do
|
||||
defp check_report_removal(%{host: actor_host} = _actor_info, %{"type" => "Flag"} = activity) do
|
||||
report_removal =
|
||||
instance_list(:report_removal)
|
||||
|> MRF.subdomains_regex()
|
||||
|
@ -144,39 +144,39 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
if MRF.subdomain_match?(report_removal, actor_host) do
|
||||
{:reject, "[SimplePolicy] host in report_removal list"}
|
||||
else
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_report_removal(_actor_info, object), do: {:ok, object}
|
||||
defp check_report_removal(_actor_info, activity), do: {:ok, activity}
|
||||
|
||||
defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = object) do
|
||||
defp check_avatar_removal(%{host: actor_host} = _actor_info, %{"icon" => _icon} = activity) do
|
||||
avatar_removal =
|
||||
instance_list(:avatar_removal)
|
||||
|> MRF.subdomains_regex()
|
||||
|
||||
if MRF.subdomain_match?(avatar_removal, actor_host) do
|
||||
{:ok, Map.delete(object, "icon")}
|
||||
{:ok, Map.delete(activity, "icon")}
|
||||
else
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_avatar_removal(_actor_info, object), do: {:ok, object}
|
||||
defp check_avatar_removal(_actor_info, activity), do: {:ok, activity}
|
||||
|
||||
defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = object) do
|
||||
defp check_banner_removal(%{host: actor_host} = _actor_info, %{"image" => _image} = activity) do
|
||||
banner_removal =
|
||||
instance_list(:banner_removal)
|
||||
|> MRF.subdomains_regex()
|
||||
|
||||
if MRF.subdomain_match?(banner_removal, actor_host) do
|
||||
{:ok, Map.delete(object, "image")}
|
||||
{:ok, Map.delete(activity, "image")}
|
||||
else
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_banner_removal(_actor_info, object), do: {:ok, object}
|
||||
defp check_banner_removal(_actor_info, activity), do: {:ok, activity}
|
||||
|
||||
defp check_object(%{"object" => object} = activity) do
|
||||
with {:ok, _object} <- filter(object) do
|
||||
|
@ -184,7 +184,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
end
|
||||
end
|
||||
|
||||
defp check_object(object), do: {:ok, object}
|
||||
defp check_object(activity), do: {:ok, activity}
|
||||
|
||||
defp instance_list(config_key) do
|
||||
Config.get([:mrf_simple, config_key])
|
||||
|
@ -192,7 +192,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Delete", "actor" => actor} = object) do
|
||||
def filter(%{"type" => "Delete", "actor" => actor} = activity) do
|
||||
%{host: actor_host} = URI.parse(actor)
|
||||
|
||||
reject_deletes =
|
||||
|
@ -202,54 +202,54 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
if MRF.subdomain_match?(reject_deletes, actor_host) do
|
||||
{:reject, "[SimplePolicy] host in reject_deletes list"}
|
||||
else
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"actor" => actor} = object) do
|
||||
def filter(%{"actor" => actor} = activity) do
|
||||
actor_info = URI.parse(actor)
|
||||
|
||||
with {:ok, object} <- check_accept(actor_info, object),
|
||||
{:ok, object} <- check_reject(actor_info, object),
|
||||
{:ok, object} <- check_media_removal(actor_info, object),
|
||||
{:ok, object} <- check_media_nsfw(actor_info, object),
|
||||
{:ok, object} <- check_ftl_removal(actor_info, object),
|
||||
{:ok, object} <- check_followers_only(actor_info, object),
|
||||
{:ok, object} <- check_report_removal(actor_info, object),
|
||||
{:ok, object} <- check_object(object) do
|
||||
{:ok, object}
|
||||
with {:ok, activity} <- check_accept(actor_info, activity),
|
||||
{:ok, activity} <- check_reject(actor_info, activity),
|
||||
{:ok, activity} <- check_media_removal(actor_info, activity),
|
||||
{:ok, activity} <- check_media_nsfw(actor_info, activity),
|
||||
{:ok, activity} <- check_ftl_removal(actor_info, activity),
|
||||
{:ok, activity} <- check_followers_only(actor_info, activity),
|
||||
{:ok, activity} <- check_report_removal(actor_info, activity),
|
||||
{:ok, activity} <- check_object(activity) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
end
|
||||
end
|
||||
|
||||
def filter(%{"id" => actor, "type" => obj_type} = object)
|
||||
when obj_type in ["Application", "Group", "Organization", "Person", "Service"] do
|
||||
def filter(%{"id" => actor, "type" => actor_type} = activity)
|
||||
when actor_type in ["Application", "Group", "Organization", "Person", "Service"] do
|
||||
actor_info = URI.parse(actor)
|
||||
|
||||
with {:ok, object} <- check_accept(actor_info, object),
|
||||
{:ok, object} <- check_reject(actor_info, object),
|
||||
{:ok, object} <- check_avatar_removal(actor_info, object),
|
||||
{:ok, object} <- check_banner_removal(actor_info, object) do
|
||||
{:ok, object}
|
||||
with {:ok, activity} <- check_accept(actor_info, activity),
|
||||
{:ok, activity} <- check_reject(actor_info, activity),
|
||||
{:ok, activity} <- check_avatar_removal(actor_info, activity),
|
||||
{:ok, activity} <- check_banner_removal(actor_info, activity) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
end
|
||||
end
|
||||
|
||||
def filter(object) when is_binary(object) do
|
||||
uri = URI.parse(object)
|
||||
def filter(activity) when is_binary(activity) do
|
||||
uri = URI.parse(activity)
|
||||
|
||||
with {:ok, object} <- check_accept(uri, object),
|
||||
{:ok, object} <- check_reject(uri, object) do
|
||||
{:ok, object}
|
||||
with {:ok, activity} <- check_accept(uri, activity),
|
||||
{:ok, activity} <- check_reject(uri, activity) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
end
|
||||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
|
|
@ -62,7 +62,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"object" => %{"emoji" => foreign_emojis, "actor" => actor}} = message) do
|
||||
def filter(%{"object" => %{"emoji" => foreign_emojis, "actor" => actor}} = activity) do
|
||||
host = URI.parse(actor).host
|
||||
|
||||
if host != Pleroma.Web.Endpoint.host() and accept_host?(host) do
|
||||
|
@ -97,10 +97,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
@spec config_description :: %{
|
||||
|
|
|
@ -20,20 +20,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"actor" => actor} = message) do
|
||||
def filter(%{"actor" => actor} = activity) do
|
||||
with {:ok, match, subchain} <- lookup_subchain(actor) do
|
||||
Logger.debug(
|
||||
"[SubchainPolicy] Matched #{actor} against #{inspect(match)} with subchain #{inspect(subchain)}"
|
||||
)
|
||||
|
||||
MRF.filter(subchain, message)
|
||||
MRF.filter(subchain, activity)
|
||||
else
|
||||
_e -> {:ok, message}
|
||||
_e -> {:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
@ -45,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
|
|||
related_policy: "Pleroma.Web.ActivityPub.MRF.SubchainPolicy",
|
||||
label: "MRF Subchain",
|
||||
description:
|
||||
"This policy processes messages through an alternate pipeline when a given message matches certain criteria." <>
|
||||
"This policy processes activities through an alternate pipeline when a given activity matches certain criteria." <>
|
||||
" All criteria are configured as a map of regular expressions to lists of policy modules.",
|
||||
children: [
|
||||
%{
|
||||
|
|
|
@ -28,25 +28,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
"mrf_tag:media-force-nsfw",
|
||||
%{
|
||||
"type" => type,
|
||||
"object" => %{"attachment" => child_attachment}
|
||||
} = message
|
||||
"object" => %{"attachment" => object_attachment}
|
||||
} = activity
|
||||
)
|
||||
when length(child_attachment) > 0 and type in ["Create", "Update"] do
|
||||
{:ok, Kernel.put_in(message, ["object", "sensitive"], true)}
|
||||
when length(object_attachment) > 0 and type in ["Create", "Update"] do
|
||||
{:ok, Kernel.put_in(activity, ["object", "sensitive"], true)}
|
||||
end
|
||||
|
||||
defp process_tag(
|
||||
"mrf_tag:media-strip",
|
||||
%{
|
||||
"type" => type,
|
||||
"object" => %{"attachment" => child_attachment} = object
|
||||
} = message
|
||||
"object" => %{"attachment" => object_attachment} = object
|
||||
} = activity
|
||||
)
|
||||
when length(child_attachment) > 0 and type in ["Create", "Update"] do
|
||||
when length(object_attachment) > 0 and type in ["Create", "Update"] do
|
||||
object = Map.delete(object, "attachment")
|
||||
message = Map.put(message, "object", object)
|
||||
activity = Map.put(activity, "object", object)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
|
||||
defp process_tag(
|
||||
|
@ -57,7 +57,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
"cc" => cc,
|
||||
"actor" => actor,
|
||||
"object" => object
|
||||
} = message
|
||||
} = activity
|
||||
) do
|
||||
user = User.get_cached_by_ap_id(actor)
|
||||
|
||||
|
@ -70,15 +70,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|
||||
message =
|
||||
message
|
||||
activity =
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|> Map.put("object", object)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -90,7 +90,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
"cc" => cc,
|
||||
"actor" => actor,
|
||||
"object" => object
|
||||
} = message
|
||||
} = activity
|
||||
) do
|
||||
user = User.get_cached_by_ap_id(actor)
|
||||
|
||||
|
@ -104,26 +104,26 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|
||||
message =
|
||||
message
|
||||
activity =
|
||||
activity
|
||||
|> Map.put("to", to)
|
||||
|> Map.put("cc", cc)
|
||||
|> Map.put("object", object)
|
||||
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
end
|
||||
end
|
||||
|
||||
defp process_tag(
|
||||
"mrf_tag:disable-remote-subscription",
|
||||
%{"type" => "Follow", "actor" => actor} = message
|
||||
%{"type" => "Follow", "actor" => actor} = activity
|
||||
) do
|
||||
user = User.get_cached_by_ap_id(actor)
|
||||
|
||||
if user.local == true do
|
||||
{:ok, message}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject,
|
||||
"[TagPolicy] Follow from #{actor} tagged with mrf_tag:disable-remote-subscription"}
|
||||
|
@ -133,14 +133,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow", "actor" => actor}),
|
||||
do: {:reject, "[TagPolicy] Follow from #{actor} tagged with mrf_tag:disable-any-subscription"}
|
||||
|
||||
defp process_tag(_, message), do: {:ok, message}
|
||||
defp process_tag(_, activity), do: {:ok, activity}
|
||||
|
||||
def filter_message(actor, message) do
|
||||
def filter_activity(actor, activity) do
|
||||
User.get_cached_by_ap_id(actor)
|
||||
|> get_tags()
|
||||
|> Enum.reduce({:ok, message}, fn
|
||||
tag, {:ok, message} ->
|
||||
process_tag(tag, message)
|
||||
|> Enum.reduce({:ok, activity}, fn
|
||||
tag, {:ok, activity} ->
|
||||
process_tag(tag, activity)
|
||||
|
||||
_, error ->
|
||||
error
|
||||
|
@ -148,15 +148,15 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"object" => target_actor, "type" => "Follow"} = message),
|
||||
do: filter_message(target_actor, message)
|
||||
def filter(%{"object" => target_actor, "type" => "Follow"} = activity),
|
||||
do: filter_activity(target_actor, activity)
|
||||
|
||||
@impl true
|
||||
def filter(%{"actor" => actor, "type" => type} = message) when type in ["Create", "Update"],
|
||||
do: filter_message(actor, message)
|
||||
def filter(%{"actor" => actor, "type" => type} = activity) when type in ["Create", "Update"],
|
||||
do: filter_activity(actor, activity)
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
|
|
|
@ -8,18 +8,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
|
|||
@moduledoc "Accept-list of users from specified instances"
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
defp filter_by_list(object, []), do: {:ok, object}
|
||||
defp filter_by_list(activity, []), do: {:ok, activity}
|
||||
|
||||
defp filter_by_list(%{"actor" => actor} = object, allow_list) do
|
||||
defp filter_by_list(%{"actor" => actor} = activity, allow_list) do
|
||||
if actor in allow_list do
|
||||
{:ok, object}
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, "[UserAllowListPolicy] #{actor} not in the list"}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"actor" => actor} = object) do
|
||||
def filter(%{"actor" => actor} = activity) do
|
||||
actor_info = URI.parse(actor)
|
||||
|
||||
allow_list =
|
||||
|
@ -28,10 +28,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
|
|||
[]
|
||||
)
|
||||
|
||||
filter_by_list(object, allow_list)
|
||||
filter_by_list(activity, allow_list)
|
||||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
|
|
|
@ -3,38 +3,38 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
|
||||
@moduledoc "Filter messages which belong to certain activity vocabularies"
|
||||
@moduledoc "Filter activities which belong to certain activity vocabularies"
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Undo", "object" => child_message} = message) do
|
||||
with {:ok, _} <- filter(child_message) do
|
||||
{:ok, message}
|
||||
def filter(%{"type" => "Undo", "object" => object} = activity) do
|
||||
with {:ok, _} <- filter(object) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
end
|
||||
end
|
||||
|
||||
def filter(%{"type" => message_type} = message) do
|
||||
def filter(%{"type" => activity_type} = activity) do
|
||||
with accepted_vocabulary <- Pleroma.Config.get([:mrf_vocabulary, :accept]),
|
||||
rejected_vocabulary <- Pleroma.Config.get([:mrf_vocabulary, :reject]),
|
||||
{_, true} <-
|
||||
{:accepted,
|
||||
Enum.empty?(accepted_vocabulary) || Enum.member?(accepted_vocabulary, message_type)},
|
||||
Enum.empty?(accepted_vocabulary) || Enum.member?(accepted_vocabulary, activity_type)},
|
||||
{_, false} <-
|
||||
{:rejected,
|
||||
length(rejected_vocabulary) > 0 && Enum.member?(rejected_vocabulary, message_type)},
|
||||
{:ok, _} <- filter(message["object"]) do
|
||||
{:ok, message}
|
||||
length(rejected_vocabulary) > 0 && Enum.member?(rejected_vocabulary, activity_type)},
|
||||
{:ok, _} <- filter(activity["object"]) do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:reject, _} = e -> e
|
||||
{:accepted, _} -> {:reject, "[VocabularyPolicy] #{message_type} not in accept list"}
|
||||
{:rejected, _} -> {:reject, "[VocabularyPolicy] #{message_type} in reject list"}
|
||||
{:accepted, _} -> {:reject, "[VocabularyPolicy] #{activity_type} not in accept list"}
|
||||
{:rejected, _} -> {:reject, "[VocabularyPolicy] #{activity_type} in reject list"}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(message), do: {:ok, message}
|
||||
def filter(activity), do: {:ok, activity}
|
||||
|
||||
@impl true
|
||||
def describe,
|
||||
|
@ -46,20 +46,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.VocabularyPolicy do
|
|||
key: :mrf_vocabulary,
|
||||
related_policy: "Pleroma.Web.ActivityPub.MRF.VocabularyPolicy",
|
||||
label: "MRF Vocabulary",
|
||||
description: "Filter messages which belong to certain activity vocabularies",
|
||||
description: "Filter activities which belong to certain activity vocabularies",
|
||||
children: [
|
||||
%{
|
||||
key: :accept,
|
||||
type: {:list, :string},
|
||||
description:
|
||||
"A list of ActivityStreams terms to accept. If empty, all supported messages are accepted.",
|
||||
"A list of ActivityStreams terms to accept. If empty, all supported activities are accepted.",
|
||||
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
||||
},
|
||||
%{
|
||||
key: :reject,
|
||||
type: {:list, :string},
|
||||
description:
|
||||
"A list of ActivityStreams terms to reject. If empty, no messages are rejected.",
|
||||
"A list of ActivityStreams terms to reject. If empty, no activities are rejected.",
|
||||
suggestions: ["Create", "Follow", "Mention", "Announce", "Like"]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptRejectValidator do
|
|||
|
||||
defp validate_data(cng) do
|
||||
cng
|
||||
|> validate_required([:id, :type, :actor, :to, :cc, :object])
|
||||
|> validate_required([:id, :type, :actor, :to, :object])
|
||||
|> validate_inclusion(:type, ["Accept", "Reject"])
|
||||
|> validate_actor_presence()
|
||||
|> validate_object_presence(allowed_types: ["Follow"])
|
||||
|
|
|
@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator do
|
|||
|
||||
defp validate_data(cng) do
|
||||
cng
|
||||
|> validate_required([:id, :type, :actor, :to, :cc, :object])
|
||||
|> validate_required([:id, :type, :actor, :to, :object])
|
||||
|> validate_inclusion(:type, ["Block"])
|
||||
|> CommonValidations.validate_actor_presence()
|
||||
|> CommonValidations.validate_actor_presence(field_name: :object)
|
||||
|
|
|
@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator do
|
|||
|
||||
defp validate_data(cng) do
|
||||
cng
|
||||
|> validate_required([:id, :type, :actor, :to, :cc, :object])
|
||||
|> validate_required([:id, :type, :actor, :to, :object])
|
||||
|> validate_inclusion(:type, ["Follow"])
|
||||
|> validate_inclusion(:state, ~w{pending reject accept})
|
||||
|> validate_actor_presence()
|
||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Publisher.Prepared
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
alias Pleroma.Workers.PublisherWorker
|
||||
|
@ -30,11 +31,11 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
"""
|
||||
@spec enqueue_one(map(), Keyword.t()) :: {:ok, %Oban.Job{}}
|
||||
def enqueue_one(%{} = params, worker_args \\ []) do
|
||||
PublisherWorker.enqueue(
|
||||
"publish_one",
|
||||
%{"params" => params},
|
||||
PublisherWorker.new(
|
||||
%{"op" => "publish_one", "params" => params},
|
||||
worker_args
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -76,14 +77,13 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
end
|
||||
|
||||
@doc """
|
||||
Publish a single message to a peer. Takes a struct with the following
|
||||
parameters set:
|
||||
|
||||
Prepare an activity for publishing from an Oban job
|
||||
* `inbox`: the inbox to publish to
|
||||
* `activity_id`: the internal activity id
|
||||
* `cc`: the cc recipients relevant to this inbox (optional)
|
||||
"""
|
||||
def publish_one(%{inbox: inbox, activity_id: activity_id} = params) do
|
||||
@spec prepare_one(map()) :: Prepared.t()
|
||||
def prepare_one(%{inbox: inbox, activity_id: activity_id} = params) do
|
||||
activity = Activity.get_by_id_with_user_actor(activity_id)
|
||||
actor = activity.user_actor
|
||||
|
||||
|
@ -93,7 +93,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
|
||||
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
|
||||
|
||||
cc = Map.get(params, :cc)
|
||||
cc = Map.get(params, :cc, [])
|
||||
|
||||
json =
|
||||
data
|
||||
|
@ -113,27 +113,54 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
date: date
|
||||
})
|
||||
|
||||
%Prepared{
|
||||
activity_id: activity_id,
|
||||
json: json,
|
||||
date: date,
|
||||
signature: signature,
|
||||
digest: digest,
|
||||
inbox: inbox,
|
||||
unreachable_since: params[:unreachable_since]
|
||||
}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Publish a single message to a peer. Takes a struct with the following
|
||||
parameters set:
|
||||
* `activity_id`: the activity id
|
||||
* `json`: the json payload
|
||||
* `date`: the signed date from Pleroma.Signature.signed_date()
|
||||
* `signature`: the signature from Pleroma.Signature.sign/2
|
||||
* `digest`: base64 encoded the hash of the json payload prefixed with "SHA-256="
|
||||
* `inbox`: the inbox URI of this delivery
|
||||
* `unreachable_since`: timestamp the instance was marked unreachable
|
||||
|
||||
"""
|
||||
def publish_one(%Prepared{} = p) do
|
||||
with {:ok, %{status: code}} = result when code in 200..299 <-
|
||||
HTTP.post(
|
||||
inbox,
|
||||
json,
|
||||
p.inbox,
|
||||
p.json,
|
||||
[
|
||||
{"Content-Type", "application/activity+json"},
|
||||
{"Date", date},
|
||||
{"signature", signature},
|
||||
{"digest", digest}
|
||||
{"Date", p.date},
|
||||
{"signature", p.signature},
|
||||
{"digest", p.digest}
|
||||
]
|
||||
) do
|
||||
if not Map.has_key?(params, :unreachable_since) || params[:unreachable_since] do
|
||||
Instances.set_reachable(inbox)
|
||||
if not is_nil(p.unreachable_since) do
|
||||
Instances.set_reachable(p.inbox)
|
||||
end
|
||||
|
||||
result
|
||||
else
|
||||
{_post_result, %{status: code} = response} = e ->
|
||||
unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
|
||||
Logger.metadata(activity: activity_id, inbox: inbox, status: code)
|
||||
Logger.error("Publisher failed to inbox #{inbox} with status #{code}")
|
||||
if is_nil(p.unreachable_since) do
|
||||
Instances.set_unreachable(p.inbox)
|
||||
end
|
||||
|
||||
Logger.metadata(activity: p.activity_id, inbox: p.inbox, status: code)
|
||||
Logger.error("Publisher failed to inbox #{p.inbox} with status #{code}")
|
||||
|
||||
case response do
|
||||
%{status: 400} -> {:cancel, :bad_request}
|
||||
|
@ -152,9 +179,12 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
connection_pool_snooze()
|
||||
|
||||
e ->
|
||||
unless params[:unreachable_since], do: Instances.set_unreachable(inbox)
|
||||
Logger.metadata(activity: activity_id, inbox: inbox)
|
||||
Logger.error("Publisher failed to inbox #{inbox} #{inspect(e)}")
|
||||
if is_nil(p.unreachable_since) do
|
||||
Instances.set_unreachable(p.inbox)
|
||||
end
|
||||
|
||||
Logger.metadata(activity: p.activity_id, inbox: p.inbox)
|
||||
Logger.error("Publisher failed to inbox #{p.inbox} #{inspect(e)}")
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
|
8
lib/pleroma/web/activity_pub/publisher/prepared.ex
Normal file
8
lib/pleroma/web/activity_pub/publisher/prepared.ex
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.Publisher.Prepared do
|
||||
@type t :: %__MODULE__{}
|
||||
defstruct [:activity_id, :json, :date, :signature, :digest, :inbox, :unreachable_since]
|
||||
end
|
|
@ -223,10 +223,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
if Pleroma.Web.Federator.allowed_thread_distance?(reply_depth) and
|
||||
object.data["replies"] != nil do
|
||||
for reply_id <- object.data["replies"] do
|
||||
Pleroma.Workers.RemoteFetcherWorker.enqueue("fetch_remote", %{
|
||||
Pleroma.Workers.RemoteFetcherWorker.new(%{
|
||||
"op" => "fetch_remote",
|
||||
"id" => reply_id,
|
||||
"depth" => reply_depth
|
||||
})
|
||||
|> Oban.insert()
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -410,10 +412,12 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
{:ok, expires_at} =
|
||||
Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime.cast(meta[:expires_at])
|
||||
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
|
||||
activity_id: meta[:activity_id],
|
||||
expires_at: expires_at
|
||||
})
|
||||
Pleroma.Workers.PurgeExpiredActivity.enqueue(
|
||||
%{
|
||||
activity_id: meta[:activity_id]
|
||||
},
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
end
|
||||
|
||||
{:ok, object, meta}
|
||||
|
|
|
@ -498,22 +498,6 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
}
|
||||
end
|
||||
|
||||
def identity_proofs_operation do
|
||||
%Operation{
|
||||
tags: ["Retrieve account information"],
|
||||
summary: "Identity proofs",
|
||||
operationId: "AccountController.identity_proofs",
|
||||
# Validators complains about unused path params otherwise
|
||||
parameters: [
|
||||
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
|
||||
],
|
||||
description: "Not implemented",
|
||||
responses: %{
|
||||
200 => empty_array_response()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def familiar_followers_operation do
|
||||
%Operation{
|
||||
tags: ["Retrieve account information"],
|
||||
|
|
|
@ -85,9 +85,11 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
|
|||
|
||||
def subscribe_operation do
|
||||
%Operation{
|
||||
deprecated: true,
|
||||
tags: ["Account actions"],
|
||||
summary: "Subscribe",
|
||||
description: "Receive notifications for all statuses posted by the account.",
|
||||
description:
|
||||
"Receive notifications for all statuses posted by the account. Deprecated, use `notify: true` in follow operation instead.",
|
||||
operationId: "PleromaAPI.AccountController.subscribe",
|
||||
parameters: [id_param()],
|
||||
security: [%{"oAuth" => ["follow", "write:follows"]}],
|
||||
|
@ -100,9 +102,11 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
|
|||
|
||||
def unsubscribe_operation do
|
||||
%Operation{
|
||||
deprecated: true,
|
||||
tags: ["Account actions"],
|
||||
summary: "Unsubscribe",
|
||||
description: "Stop receiving notifications for all statuses posted by the account.",
|
||||
description:
|
||||
"Stop receiving notifications for all statuses posted by the account. Deprecated, use `notify: false` in follow operation instead.",
|
||||
operationId: "PleromaAPI.AccountController.unsubscribe",
|
||||
parameters: [id_param()],
|
||||
security: [%{"oAuth" => ["follow", "write:follows"]}],
|
||||
|
|
|
@ -130,7 +130,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
if activity.data["state"] == "reject" do
|
||||
{:error, :rejected}
|
||||
else
|
||||
{:ok, follower, followed, activity}
|
||||
{:ok, followed, follower, activity}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -559,11 +559,11 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]),
|
||||
_ <- Pleroma.Notification.mark_context_as_read(user, activity.data["context"]) do
|
||||
if expires_in > 0 do
|
||||
Pleroma.Workers.MuteExpireWorker.enqueue(
|
||||
"unmute_conversation",
|
||||
%{"user_id" => user.id, "activity_id" => activity.id},
|
||||
Pleroma.Workers.MuteExpireWorker.new(
|
||||
%{"op" => "unmute_conversation", "user_id" => user.id, "activity_id" => activity.id},
|
||||
schedule_in: expires_in
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
{:ok, activity}
|
||||
|
|
|
@ -35,22 +35,30 @@ defmodule Pleroma.Web.Federator do
|
|||
end
|
||||
|
||||
# Client API
|
||||
def incoming_ap_doc(%{params: _params, req_headers: _req_headers} = args) do
|
||||
job_args = Enum.into(args, %{}, fn {k, v} -> {Atom.to_string(k), v} end)
|
||||
|
||||
ReceiverWorker.enqueue(
|
||||
"incoming_ap_doc",
|
||||
Map.put(job_args, "timeout", :timer.seconds(20)),
|
||||
def incoming_ap_doc(%{params: params, req_headers: req_headers}) do
|
||||
ReceiverWorker.new(
|
||||
%{
|
||||
"op" => "incoming_ap_doc",
|
||||
"req_headers" => req_headers,
|
||||
"params" => params,
|
||||
"timeout" => :timer.seconds(20)
|
||||
},
|
||||
priority: 2
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
def incoming_ap_doc(%{"type" => "Delete"} = params) do
|
||||
ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params}, priority: 3, queue: :slow)
|
||||
ReceiverWorker.new(%{"op" => "incoming_ap_doc", "params" => params},
|
||||
priority: 3,
|
||||
queue: :slow
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
def incoming_ap_doc(params) do
|
||||
ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params})
|
||||
ReceiverWorker.new(%{"op" => "incoming_ap_doc", "params" => params})
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
@ -60,9 +68,10 @@ defmodule Pleroma.Web.Federator do
|
|||
|
||||
@impl true
|
||||
def publish(%Pleroma.Activity{data: %{"type" => type}} = activity) do
|
||||
PublisherWorker.enqueue("publish", %{"activity_id" => activity.id},
|
||||
PublisherWorker.new(%{"op" => "publish", "activity_id" => activity.id},
|
||||
priority: publish_priority(type)
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
defp publish_priority("Delete"), do: 3
|
||||
|
@ -71,7 +80,10 @@ defmodule Pleroma.Web.Federator do
|
|||
# Job Worker Callbacks
|
||||
|
||||
@spec perform(atom(), any()) :: {:ok, any()} | {:error, any()}
|
||||
def perform(:publish_one, params), do: Publisher.publish_one(params)
|
||||
def perform(:publish_one, params) do
|
||||
Publisher.prepare_one(params)
|
||||
|> Publisher.publish_one()
|
||||
end
|
||||
|
||||
def perform(:publish, activity) do
|
||||
Logger.debug(fn -> "Running publish for #{activity.data["id"]}" end)
|
||||
|
|
|
@ -22,7 +22,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.ListView
|
||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||
alias Pleroma.Web.MastodonAPI.MastodonAPIController
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.OAuth.OAuthController
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
|
@ -51,7 +50,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["read:accounts"]}
|
||||
when action in [:verify_credentials, :endorsements, :identity_proofs]
|
||||
when action in [:verify_credentials, :endorsements]
|
||||
)
|
||||
|
||||
plug(
|
||||
|
@ -660,7 +659,4 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
defp get_familiar_followers(user, current_user) do
|
||||
User.get_familiar_followers(user, current_user)
|
||||
end
|
||||
|
||||
@doc "GET /api/v1/identity_proofs"
|
||||
def identity_proofs(conn, params), do: MastodonAPIController.empty_array(conn, params)
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Web.MastodonAPI.MarkerController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
|
@ -30,9 +31,16 @@ defmodule Pleroma.Web.MastodonAPI.MarkerController do
|
|||
def upsert(%{assigns: %{user: user}, body_params: params} = conn, _) do
|
||||
params = Map.new(params, fn {key, value} -> {to_string(key), value} end)
|
||||
|
||||
with {:ok, result} <- Pleroma.Marker.upsert(user, params),
|
||||
with {:ok, _} <- mark_notifications_read(user, params),
|
||||
{:ok, result} <- Pleroma.Marker.upsert(user, params),
|
||||
markers <- Map.values(result) do
|
||||
render(conn, "markers.json", %{markers: markers})
|
||||
end
|
||||
end
|
||||
|
||||
defp mark_notifications_read(user, %{"notifications" => %{last_read_id: last_read_id}}) do
|
||||
Pleroma.Notification.set_read_up_to(user, last_read_id)
|
||||
end
|
||||
|
||||
defp mark_notifications_read(_, _), do: {:ok, :noop}
|
||||
end
|
||||
|
|
|
@ -18,10 +18,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
|||
if not User.following?(follower, followed) do
|
||||
CommonAPI.follow(followed, follower)
|
||||
else
|
||||
{:ok, follower, followed, nil}
|
||||
{:ok, followed, follower, nil}
|
||||
end
|
||||
|
||||
with {:ok, follower, _followed, _} <- result do
|
||||
with {:ok, _followed, follower, _} <- result do
|
||||
options = cast_params(params)
|
||||
set_reblogs_visibility(options[:reblogs], result)
|
||||
set_subscription(options[:notify], result)
|
||||
|
@ -29,19 +29,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
|||
end
|
||||
end
|
||||
|
||||
defp set_reblogs_visibility(false, {:ok, follower, followed, _}) do
|
||||
defp set_reblogs_visibility(false, {:ok, followed, follower, _}) do
|
||||
CommonAPI.hide_reblogs(followed, follower)
|
||||
end
|
||||
|
||||
defp set_reblogs_visibility(_, {:ok, follower, followed, _}) do
|
||||
defp set_reblogs_visibility(_, {:ok, followed, follower, _}) do
|
||||
CommonAPI.show_reblogs(followed, follower)
|
||||
end
|
||||
|
||||
defp set_subscription(true, {:ok, follower, followed, _}) do
|
||||
defp set_subscription(true, {:ok, followed, follower, _}) do
|
||||
User.subscribe(follower, followed)
|
||||
end
|
||||
|
||||
defp set_subscription(false, {:ok, follower, followed, _}) do
|
||||
defp set_subscription(false, {:ok, followed, follower, _}) do
|
||||
User.unsubscribe(follower, followed)
|
||||
end
|
||||
|
||||
|
|
|
@ -100,11 +100,10 @@ defmodule Pleroma.Web.OAuth.Token do
|
|||
def create(%App{} = app, %User{} = user, attrs \\ %{}) do
|
||||
with {:ok, token} <- do_create(app, user, attrs) do
|
||||
if Pleroma.Config.get([:oauth2, :clean_expired_tokens]) do
|
||||
Pleroma.Workers.PurgeExpiredToken.enqueue(%{
|
||||
token_id: token.id,
|
||||
valid_until: DateTime.from_naive!(token.valid_until, "Etc/UTC"),
|
||||
mod: __MODULE__
|
||||
})
|
||||
Pleroma.Workers.PurgeExpiredToken.new(%{token_id: token.id, mod: __MODULE__},
|
||||
scheduled_at: DateTime.from_naive!(token.valid_until, "Etc/UTC")
|
||||
)
|
||||
|> Oban.insert()
|
||||
end
|
||||
|
||||
{:ok, token}
|
||||
|
|
|
@ -38,8 +38,8 @@ defmodule Pleroma.Web.PleromaAPI.UserImportController do
|
|||
|> Enum.map(&(&1 |> String.trim() |> String.trim_leading("@")))
|
||||
|> Enum.reject(&(&1 == ""))
|
||||
|
||||
User.Import.follow_import(follower, identifiers)
|
||||
json(conn, "job started")
|
||||
User.Import.follows_import(follower, identifiers)
|
||||
json(conn, "jobs started")
|
||||
end
|
||||
|
||||
def blocks(
|
||||
|
@ -55,7 +55,7 @@ defmodule Pleroma.Web.PleromaAPI.UserImportController do
|
|||
|
||||
defp do_block(%{assigns: %{user: blocker}} = conn, list) do
|
||||
User.Import.blocks_import(blocker, prepare_user_identifiers(list))
|
||||
json(conn, "job started")
|
||||
json(conn, "jobs started")
|
||||
end
|
||||
|
||||
def mutes(
|
||||
|
@ -71,7 +71,7 @@ defmodule Pleroma.Web.PleromaAPI.UserImportController do
|
|||
|
||||
defp do_mute(%{assigns: %{user: user}} = conn, list) do
|
||||
User.Import.mutes_import(user, prepare_user_identifiers(list))
|
||||
json(conn, "job started")
|
||||
json(conn, "jobs started")
|
||||
end
|
||||
|
||||
defp prepare_user_identifiers(list) do
|
||||
|
|
|
@ -28,6 +28,7 @@ defmodule Pleroma.Web.Push do
|
|||
@spec send(Pleroma.Notification.t()) ::
|
||||
{:ok, Oban.Job.t()} | {:error, Oban.Job.changeset() | term()}
|
||||
def send(notification) do
|
||||
WebPusherWorker.enqueue("web_push", %{"notification_id" => notification.id})
|
||||
WebPusherWorker.new(%{"op" => "web_push", "notification_id" => notification.id})
|
||||
|> Oban.insert()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -648,7 +648,6 @@ defmodule Pleroma.Web.Router do
|
|||
get("/accounts/relationships", AccountController, :relationships)
|
||||
get("/accounts/familiar_followers", AccountController, :familiar_followers)
|
||||
get("/accounts/:id/lists", AccountController, :lists)
|
||||
get("/accounts/:id/identity_proofs", AccountController, :identity_proofs)
|
||||
get("/endorsements", AccountController, :endorsements)
|
||||
get("/blocks", AccountController, :blocks)
|
||||
get("/mutes", AccountController, :mutes)
|
||||
|
|
|
@ -109,7 +109,25 @@ defmodule Pleroma.Web.StreamerView do
|
|||
|> Jason.encode!()
|
||||
end
|
||||
|
||||
def render("follow_relationships_update.json", item, topic) do
|
||||
def render(
|
||||
"follow_relationships_update.json",
|
||||
%{follower: follower, following: following} = item,
|
||||
topic
|
||||
) do
|
||||
following_follower_count =
|
||||
if Enum.any?([following.hide_followers_count, following.hide_followers]) do
|
||||
0
|
||||
else
|
||||
following.follower_count
|
||||
end
|
||||
|
||||
following_following_count =
|
||||
if Enum.any?([following.hide_follows_count, following.hide_follows]) do
|
||||
0
|
||||
else
|
||||
following.following_count
|
||||
end
|
||||
|
||||
%{
|
||||
stream: render("stream.json", %{topic: topic}),
|
||||
event: "pleroma:follow_relationships_update",
|
||||
|
@ -117,14 +135,14 @@ defmodule Pleroma.Web.StreamerView do
|
|||
%{
|
||||
state: item.state,
|
||||
follower: %{
|
||||
id: item.follower.id,
|
||||
follower_count: item.follower.follower_count,
|
||||
following_count: item.follower.following_count
|
||||
id: follower.id,
|
||||
follower_count: follower.follower_count,
|
||||
following_count: follower.following_count
|
||||
},
|
||||
following: %{
|
||||
id: item.following.id,
|
||||
follower_count: item.following.follower_count,
|
||||
following_count: item.following.following_count
|
||||
id: following.id,
|
||||
follower_count: following_follower_count,
|
||||
following_count: following_following_count
|
||||
}
|
||||
}
|
||||
|> Jason.encode!()
|
||||
|
|
|
@ -8,9 +8,9 @@ defmodule Pleroma.Workers.AttachmentsCleanupWorker do
|
|||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
|
||||
use Pleroma.Workers.WorkerHelper, queue: "slow"
|
||||
use Oban.Worker, queue: :slow
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def perform(%Job{
|
||||
args: %{
|
||||
"op" => "cleanup_attachments",
|
||||
|
@ -31,7 +31,7 @@ defmodule Pleroma.Workers.AttachmentsCleanupWorker do
|
|||
|
||||
def perform(%Job{args: %{"op" => "cleanup_attachments", "object" => _object}}), do: {:ok, :skip}
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(900)
|
||||
|
||||
defp do_clean({object_ids, attachment_urls}) do
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
defmodule Pleroma.Workers.BackgroundWorker do
|
||||
alias Pleroma.User
|
||||
|
||||
use Pleroma.Workers.WorkerHelper, queue: "background"
|
||||
use Oban.Worker, queue: :background
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
|
||||
def perform(%Job{args: %{"op" => "user_activation", "user_id" => user_id, "status" => status}}) do
|
||||
user = User.get_cached_by_id(user_id)
|
||||
|
@ -19,10 +19,10 @@ defmodule Pleroma.Workers.BackgroundWorker do
|
|||
User.perform(:force_password_reset, user)
|
||||
end
|
||||
|
||||
def perform(%Job{args: %{"op" => op, "user_id" => user_id, "identifiers" => identifiers}})
|
||||
when op in ["blocks_import", "follow_import", "mutes_import"] do
|
||||
def perform(%Job{args: %{"op" => op, "user_id" => user_id, "actor" => actor}})
|
||||
when op in ["block_import", "follow_import", "mute_import"] do
|
||||
user = User.get_cached_by_id(user_id)
|
||||
{:ok, User.Import.perform(String.to_existing_atom(op), user, identifiers)}
|
||||
User.Import.perform(String.to_existing_atom(op), user, actor)
|
||||
end
|
||||
|
||||
def perform(%Job{
|
||||
|
@ -39,6 +39,6 @@ defmodule Pleroma.Workers.BackgroundWorker do
|
|||
User.perform(:verify_fields_links, user)
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
def timeout(_job), do: :timer.seconds(15)
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(900)
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ defmodule Pleroma.Workers.BackupWorker do
|
|||
alias Pleroma.Config.Getting, as: Config
|
||||
alias Pleroma.User.Backup
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def perform(%Job{
|
||||
args: %{"op" => "process", "backup_id" => backup_id}
|
||||
}) do
|
||||
|
@ -32,7 +32,7 @@ defmodule Pleroma.Workers.BackupWorker do
|
|||
end
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def timeout(_job), do: Config.get([Backup, :timeout], :timer.minutes(30))
|
||||
|
||||
defp has_email?(user) do
|
||||
|
|
|
@ -18,7 +18,7 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorker do
|
|||
|
||||
require Logger
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def perform(_job) do
|
||||
config = Config.get([:email_notifications, :digest])
|
||||
|
||||
|
@ -59,6 +59,6 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorker do
|
|||
User.touch_last_digest_emailed_at(user)
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(5)
|
||||
end
|
||||
|
|
|
@ -9,9 +9,9 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorker do
|
|||
|
||||
import Ecto.Query
|
||||
|
||||
use Pleroma.Workers.WorkerHelper, queue: "background"
|
||||
use Oban.Worker, queue: :background
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def perform(_job) do
|
||||
if Pleroma.Config.get([Pleroma.Emails.NewUsersDigestEmail, :enabled]) do
|
||||
today = NaiveDateTime.utc_now() |> Timex.beginning_of_day()
|
||||
|
@ -61,6 +61,6 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorker do
|
|||
:ok
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(5)
|
||||
end
|
||||
|
|
|
@ -6,10 +6,9 @@ defmodule Pleroma.Workers.DeleteWorker do
|
|||
alias Pleroma.Instances.Instance
|
||||
alias Pleroma.User
|
||||
|
||||
use Pleroma.Workers.WorkerHelper, queue: "slow"
|
||||
|
||||
@impl Oban.Worker
|
||||
use Oban.Worker, queue: :slow
|
||||
|
||||
@impl true
|
||||
def perform(%Job{args: %{"op" => "delete_user", "user_id" => user_id}}) do
|
||||
user = User.get_cached_by_id(user_id)
|
||||
User.perform(:delete, user)
|
||||
|
@ -19,6 +18,6 @@ defmodule Pleroma.Workers.DeleteWorker do
|
|||
Instance.perform(:delete_instance, host)
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(900)
|
||||
end
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Workers.MailerWorker do
|
||||
use Pleroma.Workers.WorkerHelper, queue: "background"
|
||||
use Oban.Worker, queue: :background
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def perform(%Job{args: %{"op" => "email", "encoded_email" => encoded_email, "config" => config}}) do
|
||||
encoded_email
|
||||
|> Base.decode64!()
|
||||
|
@ -13,6 +13,6 @@ defmodule Pleroma.Workers.MailerWorker do
|
|||
|> Pleroma.Emails.Mailer.deliver(config)
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(5)
|
||||
end
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Workers.MuteExpireWorker do
|
||||
use Pleroma.Workers.WorkerHelper, queue: "background"
|
||||
use Oban.Worker, queue: :background
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def perform(%Job{args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id}}) do
|
||||
Pleroma.User.unmute(muter_id, mutee_id)
|
||||
:ok
|
||||
|
@ -18,6 +18,6 @@ defmodule Pleroma.Workers.MuteExpireWorker do
|
|||
:ok
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(5)
|
||||
end
|
||||
|
|
|
@ -6,13 +6,13 @@ defmodule Pleroma.Workers.PollWorker do
|
|||
@moduledoc """
|
||||
Generates notifications when a poll ends.
|
||||
"""
|
||||
use Pleroma.Workers.WorkerHelper, queue: "background"
|
||||
use Oban.Worker, queue: :background
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def perform(%Job{args: %{"op" => "poll_end", "activity_id" => activity_id}}) do
|
||||
with %Activity{} = activity <- find_poll_activity(activity_id),
|
||||
{:ok, notifications} <- Notification.create_poll_notifications(activity) do
|
||||
|
@ -23,7 +23,7 @@ defmodule Pleroma.Workers.PollWorker do
|
|||
end
|
||||
end
|
||||
|
||||
@impl Oban.Worker
|
||||
@impl true
|
||||
def timeout(_job), do: :timer.seconds(5)
|
||||
|
||||
defp find_poll_activity(activity_id) do
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue