- `content_type`: string, contain the MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint.
- `to`: A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for for post visibility are not affected by this and will still apply.
- `visibility`: string, besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`.
+- `expires_on`: datetime (iso8601), sets when the posted activity should expire. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated.
## PATCH `/api/v1/update_credentials`
alias Pleroma.FlakeId
alias Pleroma.Repo
+ import Ecto.Changeset
import Ecto.Query
@type t :: %__MODULE__{}
field(:scheduled_at, :naive_datetime)
end
+ def changeset(%ActivityExpiration{} = expiration, attrs) do
+ expiration
+ |> cast(attrs, [:scheduled_at])
+ |> validate_required([: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) do
+ %ActivityExpiration{activity_id: activity.id}
+ |> changeset(%{scheduled_at: scheduled_at})
+ |> Repo.insert()
+ end
+
def due_expirations(offset \\ 0) do
naive_datetime =
NaiveDateTime.utc_now()
defmodule Pleroma.Web.CommonAPI do
alias Pleroma.Activity
+ alias Pleroma.ActivityExpiration
alias Pleroma.Formatter
alias Pleroma.Object
alias Pleroma.ThreadMute
context <- make_context(in_reply_to),
cw <- data["spoiler_text"] || "",
sensitive <- data["sensitive"] || Enum.member?(tags, {"#nsfw", "nsfw"}),
+ {:ok, expires_at} <- Ecto.Type.cast(:naive_datetime, data["expires_at"]),
full_payload <- String.trim(status <> cw),
:ok <- validate_character_limit(full_payload, attachments, limit),
object <-
preview? = Pleroma.Web.ControllerHelper.truthy_param?(data["preview"]) || false
direct? = visibility == "direct"
- %{
- to: to,
- actor: user,
- context: context,
- object: object,
- additional: %{"cc" => cc, "directMessage" => direct?}
- }
- |> maybe_add_list_data(user, visibility)
- |> ActivityPub.create(preview?)
+ result =
+ %{
+ to: to,
+ actor: user,
+ context: context,
+ object: object,
+ additional: %{"cc" => cc, "directMessage" => direct?}
+ }
+ |> maybe_add_list_data(user, visibility)
+ |> ActivityPub.create(preview?)
+
+ if expires_at do
+ with {:ok, activity} <- result do
+ ActivityExpiration.create(activity, expires_at)
+ end
+ end
+
+ result
else
{:private_to_public, true} ->
{:error, dgettext("errors", "The message visibility must be direct")}
end
defp expiration_offset_by_minutes(attrs, minutes) do
+ scheduled_at =
+ NaiveDateTime.utc_now()
+ |> NaiveDateTime.add(:timer.minutes(minutes), :millisecond)
+ |> NaiveDateTime.truncate(:second)
+
%Pleroma.ActivityExpiration{}
|> Map.merge(attrs)
- |> Map.put(
- :scheduled_at,
- NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(minutes), :millisecond)
- )
+ |> Map.put(:scheduled_at, scheduled_at)
end
def expiration_in_the_past_factory(attrs \\ %{}) do
Pleroma.Config.put([:instance, :limit], limit)
end
+
+ 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_iso8601 = expires_at |> NaiveDateTime.to_iso8601()
+
+ assert {:ok, activity} =
+ CommonAPI.post(user, %{"status" => "chai", "expires_at" => expires_at_iso8601})
+
+ assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id)
+ assert expiration.scheduled_at == expires_at
+ end
end
describe "reactions" do
alias Ecto.Changeset
alias Pleroma.Activity
+ alias Pleroma.ActivityExpiration
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
assert %{"id" => third_id} = json_response(conn_three, 200)
refute id == third_id
+
+ # An activity that will expire:
+ expires_at =
+ NaiveDateTime.utc_now()
+ |> NaiveDateTime.add(:timer.minutes(120), :millisecond)
+ |> NaiveDateTime.truncate(:second)
+
+ conn_four =
+ conn
+ |> post("api/v1/statuses", %{
+ "status" => "oolong",
+ "expires_at" => expires_at
+ })
+
+ assert %{"id" => fourth_id} = json_response(conn_four, 200)
+ assert activity = Activity.get_by_id(fourth_id)
+ assert expiration = ActivityExpiration.get_by_activity_id(fourth_id)
+ assert expiration.scheduled_at == expires_at
end
test "replying to a status", %{conn: conn} do