User.Query.build(%{followers: user, deactivated: false})
end
- def get_followers_query(user, page) do
+ def get_followers_query(%User{} = user, page) do
user
|> get_followers_query(nil)
|> User.Query.paginate(page, 20)
end
@spec get_followers_query(User.t()) :: Ecto.Query.t()
- def get_followers_query(user), do: get_followers_query(user, nil)
+ def get_followers_query(%User{} = user), do: get_followers_query(user, nil)
@spec get_followers(User.t(), pos_integer() | nil) :: {:ok, list(User.t())}
- def get_followers(user, page \\ nil) do
+ def get_followers(%User{} = user, page \\ nil) do
user
|> get_followers_query(page)
|> Repo.all()
end
@spec get_external_followers(User.t(), pos_integer() | nil) :: {:ok, list(User.t())}
- def get_external_followers(user, page \\ nil) do
+ def get_external_followers(%User{} = user, page \\ nil) do
user
|> get_followers_query(page)
|> User.Query.build(%{external: true})
|> Repo.all()
end
- def get_followers_ids(user, page \\ nil) do
+ def get_followers_ids(%User{} = user, page \\ nil) do
user
|> get_followers_query(page)
|> select([u], u.id)
User.Query.build(%{friends: user, deactivated: false})
end
- def get_friends_query(user, page) do
+ def get_friends_query(%User{} = user, page) do
user
|> get_friends_query(nil)
|> User.Query.paginate(page, 20)
end
@spec get_friends_query(User.t()) :: Ecto.Query.t()
- def get_friends_query(user), do: get_friends_query(user, nil)
+ def get_friends_query(%User{} = user), do: get_friends_query(user, nil)
- def get_friends(user, page \\ nil) do
+ def get_friends(%User{} = user, page \\ nil) do
user
|> get_friends_query(page)
|> Repo.all()
end
- def get_friends_ap_ids(user) do
+ def get_friends_ap_ids(%User{} = user) do
user
|> get_friends_query(nil)
|> select([u], u.ap_id)
|> Repo.all()
end
- def get_friends_ids(user, page \\ nil) do
+ def get_friends_ids(%User{} = user, page \\ nil) do
user
|> get_friends_query(page)
|> select([u], u.id)
|> Repo.all()
end
- @spec mute(User.t(), User.t(), boolean()) ::
+ @spec mute(User.t(), User.t(), map()) ::
{:ok, list(UserRelationship.t())} | {:error, String.t()}
- def mute(%User{} = muter, %User{} = mutee, notifications? \\ true) do
- add_to_mutes(muter, mutee, notifications?)
+ def mute(%User{} = muter, %User{} = mutee, params \\ %{}) do
+ notifications? = Map.get(params, :notifications, true)
+ expires_in = Map.get(params, :expires_in, 0)
+
+ with {:ok, user_mute} <- UserRelationship.create_mute(muter, mutee),
+ {:ok, user_notification_mute} <-
+ (notifications? && UserRelationship.create_notification_mute(muter, mutee)) ||
+ {:ok, nil} do
+ if expires_in > 0 do
+ Pleroma.Workers.MuteExpireWorker.enqueue(
+ "unmute_user",
+ %{"muter_id" => muter.id, "mutee_id" => mutee.id},
+ schedule_in: expires_in
+ )
+ end
+
+ {:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
+ end
end
def unmute(%User{} = muter, %User{} = mutee) do
- remove_from_mutes(muter, mutee)
+ with {:ok, user_mute} <- UserRelationship.delete_mute(muter, mutee),
+ {:ok, user_notification_mute} <-
+ UserRelationship.delete_notification_mute(muter, mutee) do
+ {:ok, [user_mute, user_notification_mute]}
+ end
end
def subscribe(%User{} = subscriber, %User{} = target) do
max_pinned_statuses = Config.get([:instance, :max_pinned_statuses], 0)
params = %{pinned_activities: user.pinned_activities ++ [id]}
+ # if pinned activity was scheduled for deletion, we remove job
+ if expiration = Pleroma.Workers.PurgeExpiredActivity.get_expiration(id) do
+ Oban.cancel_job(expiration.id)
+ end
+
user
|> cast(params, [:pinned_activities])
|> validate_length(:pinned_activities,
|> update_and_set_cache()
end
- def remove_pinnned_activity(user, %Pleroma.Activity{id: id}) do
+ def remove_pinnned_activity(user, %Pleroma.Activity{id: id, data: data}) do
params = %{pinned_activities: List.delete(user.pinned_activities, id)}
+ # if pinned activity was scheduled for deletion, we reschedule it for deletion
+ if data["expires_at"] do
+ {:ok, expires_at, _} = DateTime.from_iso8601(data["expires_at"])
+
+ Pleroma.Workers.PurgeExpiredActivity.enqueue(%{
+ activity_id: id,
+ expires_at: expires_at
+ })
+ end
+
user
|> cast(params, [:pinned_activities])
|> update_and_set_cache()
UserRelationship.delete_block(user, blocked)
end
- defp add_to_mutes(%User{} = user, %User{} = muted_user, notifications?) do
- with {:ok, user_mute} <- UserRelationship.create_mute(user, muted_user),
- {:ok, user_notification_mute} <-
- (notifications? && UserRelationship.create_notification_mute(user, muted_user)) ||
- {:ok, nil} do
- {:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
- end
- end
-
- defp remove_from_mutes(user, %User{} = muted_user) do
- with {:ok, user_mute} <- UserRelationship.delete_mute(user, muted_user),
- {:ok, user_notification_mute} <-
- UserRelationship.delete_notification_mute(user, muted_user) do
- {:ok, [user_mute, user_notification_mute]}
- end
- end
-
def set_invisible(user, invisible) do
params = %{invisible: invisible}
defmodule Pleroma.Web.CommonAPI do
alias Pleroma.Activity
- alias Pleroma.ActivityExpiration
alias Pleroma.Conversation.Participation
alias Pleroma.Formatter
alias Pleroma.Object
def check_expiry_date({:ok, nil} = res), do: res
def check_expiry_date({:ok, in_seconds}) do
- expiry = NaiveDateTime.utc_now() |> NaiveDateTime.add(in_seconds)
+ expiry = DateTime.add(DateTime.utc_now(), in_seconds)
- if ActivityExpiration.expires_late_enough?(expiry) do
+ if Pleroma.Workers.PurgeExpiredActivity.expires_late_enough?(expiry) do
{:ok, expiry}
else
{:error, "Expiry date is too soon"}
end
end
- def add_mute(user, activity) do
+ def add_mute(user, activity, params \\ %{}) do
+ expires_in = Map.get(params, :expires_in, 0)
+
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},
+ schedule_in: expires_in
+ )
+ end
+
{:ok, activity}
else
{:error, _} -> {:error, dgettext("errors", "conversation is already muted")}
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.CommonAPITest do
- use Pleroma.DataCase
use Oban.Testing, repo: Pleroma.Repo
+ use Pleroma.DataCase
alias Pleroma.Activity
alias Pleroma.Chat
test "it can handle activities that expire" do
user = insert(:user)
- expires_at =
- NaiveDateTime.utc_now()
- |> NaiveDateTime.truncate(:second)
- |> NaiveDateTime.add(1_000_000, :second)
+ expires_at = DateTime.add(DateTime.utc_now(), 1_000_000)
assert {:ok, activity} = CommonAPI.post(user, %{status: "chai", expires_in: 1_000_000})
- assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id)
- assert expiration.scheduled_at == expires_at
+ assert_enqueued(
+ worker: Pleroma.Workers.PurgeExpiredActivity,
+ args: %{activity_id: activity.id},
+ scheduled_at: expires_at
+ )
end
end
assert CommonAPI.thread_muted?(user, activity)
end
+ test "add expiring mute", %{user: user, activity: activity} do
+ {:ok, _} = CommonAPI.add_mute(user, activity, %{expires_in: 60})
+ assert CommonAPI.thread_muted?(user, activity)
+
+ worker = Pleroma.Workers.MuteExpireWorker
+ args = %{"op" => "unmute_conversation", "user_id" => user.id, "activity_id" => activity.id}
+
+ assert_enqueued(
+ worker: worker,
+ args: args
+ )
+
+ assert :ok = perform_job(worker, args)
+ refute CommonAPI.thread_muted?(user, activity)
+ end
+
test "remove mute", %{user: user, activity: activity} do
CommonAPI.add_mute(user, activity)
{:ok, _} = CommonAPI.remove_mute(user, activity)