Handle scheduled_at
on status creation.
This commit is contained in:
parent
7bf622ce73
commit
b3870df51f
4 changed files with 75 additions and 6 deletions
|
@ -31,7 +31,7 @@ defmodule Pleroma.Activity do
|
||||||
field(:data, :map)
|
field(:data, :map)
|
||||||
field(:local, :boolean, default: true)
|
field(:local, :boolean, default: true)
|
||||||
field(:actor, :string)
|
field(:actor, :string)
|
||||||
field(:recipients, {:array, :string})
|
field(:recipients, {:array, :string}, default: [])
|
||||||
has_many(:notifications, Notification, on_delete: :delete_all)
|
has_many(:notifications, Notification, on_delete: :delete_all)
|
||||||
|
|
||||||
# Attention: this is a fake relation, don't try to preload it blindly and expect it to work!
|
# Attention: this is a fake relation, don't try to preload it blindly and expect it to work!
|
||||||
|
|
|
@ -12,6 +12,8 @@ defmodule Pleroma.ScheduledActivity do
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
@min_offset :timer.minutes(5)
|
||||||
|
|
||||||
schema "scheduled_activities" do
|
schema "scheduled_activities" do
|
||||||
belongs_to(:user, User, type: Pleroma.FlakeId)
|
belongs_to(:user, User, type: Pleroma.FlakeId)
|
||||||
field(:scheduled_at, :naive_datetime)
|
field(:scheduled_at, :naive_datetime)
|
||||||
|
@ -30,6 +32,20 @@ def update_changeset(%ScheduledActivity{} = scheduled_activity, attrs) do
|
||||||
|> cast(attrs, [:scheduled_at])
|
|> cast(attrs, [:scheduled_at])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def far_enough?(scheduled_at) when is_binary(scheduled_at) do
|
||||||
|
with {:ok, scheduled_at} <- Ecto.Type.cast(:naive_datetime, scheduled_at) do
|
||||||
|
far_enough?(scheduled_at)
|
||||||
|
else
|
||||||
|
_ -> false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def far_enough?(scheduled_at) do
|
||||||
|
now = NaiveDateTime.utc_now()
|
||||||
|
diff = NaiveDateTime.diff(scheduled_at, now, :millisecond)
|
||||||
|
diff > @min_offset
|
||||||
|
end
|
||||||
|
|
||||||
def new(%User{} = user, attrs) do
|
def new(%User{} = user, attrs) do
|
||||||
%ScheduledActivity{user_id: user.id}
|
%ScheduledActivity{user_id: user.id}
|
||||||
|> changeset(attrs)
|
|> changeset(attrs)
|
||||||
|
|
|
@ -425,12 +425,29 @@ def post_status(%{assigns: %{user: user}} = conn, %{"status" => _} = params) do
|
||||||
_ -> Ecto.UUID.generate()
|
_ -> Ecto.UUID.generate()
|
||||||
end
|
end
|
||||||
|
|
||||||
{:ok, activity} =
|
scheduled_at = params["scheduled_at"]
|
||||||
Cachex.fetch!(:idempotency_cache, idempotency_key, fn _ -> CommonAPI.post(user, params) end)
|
|
||||||
|
|
||||||
conn
|
if scheduled_at && ScheduledActivity.far_enough?(scheduled_at) do
|
||||||
|> put_view(StatusView)
|
{:ok, scheduled_activity} =
|
||||||
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
Cachex.fetch!(:idempotency_cache, idempotency_key, fn _ ->
|
||||||
|
ScheduledActivity.create(user, %{"params" => params, "scheduled_at" => scheduled_at})
|
||||||
|
end)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_view(ScheduledActivityView)
|
||||||
|
|> render("show.json", %{scheduled_activity: scheduled_activity})
|
||||||
|
else
|
||||||
|
params = Map.drop(params, ["scheduled_at"])
|
||||||
|
|
||||||
|
{:ok, activity} =
|
||||||
|
Cachex.fetch!(:idempotency_cache, idempotency_key, fn _ ->
|
||||||
|
CommonAPI.post(user, params)
|
||||||
|
end)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_view(StatusView)
|
||||||
|
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def delete_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
|
|
|
@ -2410,6 +2410,42 @@ test "redirects to the getting-started page when referer is not present", %{conn
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "scheduled activities" do
|
describe "scheduled activities" do
|
||||||
|
test "creates a scheduled activity", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/statuses", %{
|
||||||
|
"status" => "scheduled",
|
||||||
|
"scheduled_at" => scheduled_at
|
||||||
|
})
|
||||||
|
|
||||||
|
assert %{"scheduled_at" => expected_scheduled_at} = json_response(conn, 200)
|
||||||
|
assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(scheduled_at)
|
||||||
|
assert [] == Repo.all(Activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "skips the scheduling and creates the activity if scheduled_at is earlier than 5 minutes from now",
|
||||||
|
%{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
scheduled_at =
|
||||||
|
NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(5) - 1, :millisecond)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/statuses", %{
|
||||||
|
"status" => "not scheduled",
|
||||||
|
"scheduled_at" => scheduled_at
|
||||||
|
})
|
||||||
|
|
||||||
|
assert %{"content" => "not scheduled"} = json_response(conn, 200)
|
||||||
|
assert [] == Repo.all(ScheduledActivity)
|
||||||
|
end
|
||||||
|
|
||||||
test "shows scheduled activities", %{conn: conn} do
|
test "shows scheduled activities", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
|
scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||||
|
|
Loading…
Reference in a new issue