# Pleroma: A lightweight social networking server # Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.ActivityExpiration do use Ecto.Schema alias Pleroma.Activity alias Pleroma.ActivityExpiration alias Pleroma.Repo import Ecto.Changeset import Ecto.Query @type t :: %__MODULE__{} @min_activity_lifetime :timer.hours(1) schema "activity_expirations" do belongs_to(:activity, Activity, type: FlakeId.Ecto.CompatType) field(:scheduled_at, :naive_datetime) end def changeset(%ActivityExpiration{} = expiration, attrs, validate_scheduled_at) do expiration |> cast(attrs, [:scheduled_at]) |> validate_required([:scheduled_at]) |> validate_scheduled_at(validate_scheduled_at) end def get_by_activity_id(activity_id) do ActivityExpiration |> where([exp], exp.activity_id == ^activity_id) |> Repo.one() end def create(%Activity{} = activity, scheduled_at, validate_scheduled_at \\ true) do %ActivityExpiration{activity_id: activity.id} |> changeset(%{scheduled_at: scheduled_at}, validate_scheduled_at) |> Repo.insert() end def due_expirations(offset \\ 0) do naive_datetime = NaiveDateTime.utc_now() |> NaiveDateTime.add(offset, :millisecond) ActivityExpiration |> where([exp], exp.scheduled_at < ^naive_datetime) |> limit(50) |> preload(:activity) |> Repo.all() |> Enum.reject(fn %{activity: activity} -> Activity.pinned_by_actor?(activity) end) end def validate_scheduled_at(changeset, false), do: changeset def validate_scheduled_at(changeset, true) do validate_change(changeset, :scheduled_at, fn _, scheduled_at -> if not expires_late_enough?(scheduled_at) do [scheduled_at: "an ephemeral activity must live for at least one hour"] else [] end end) end def expires_late_enough?(scheduled_at) do now = NaiveDateTime.utc_now() diff = NaiveDateTime.diff(scheduled_at, now, :millisecond) diff > @min_activity_lifetime end end