summaryrefslogtreecommitdiff
path: root/lib/pleroma/activity_expiration.ex
blob: 955f0578ee65ed896907dfb1df35fd58c99437f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# 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