163 lines
3.8 KiB
Elixir
163 lines
3.8 KiB
Elixir
# Pleroma: A lightweight social networking server
|
|
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
defmodule Pleroma.Announcement do
|
|
use Ecto.Schema
|
|
|
|
import Ecto.Changeset, only: [cast: 3, validate_required: 2]
|
|
import Ecto.Query
|
|
|
|
alias Pleroma.AnnouncementReadRelationship
|
|
alias Pleroma.Repo
|
|
|
|
@type t :: %__MODULE__{}
|
|
@primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
|
|
|
|
schema "announcements" do
|
|
field(:data, :map)
|
|
field(:starts_at, :utc_datetime)
|
|
field(:ends_at, :utc_datetime)
|
|
field(:rendered, :map)
|
|
|
|
timestamps(type: :utc_datetime)
|
|
end
|
|
|
|
@doc "Generates changeset for %Pleroma.Announcement{}"
|
|
@spec changeset(%__MODULE__{}, map()) :: %Ecto.Changeset{}
|
|
def changeset(announcement \\ %__MODULE__{}, params \\ %{data: %{}}) do
|
|
announcement
|
|
|> cast(validate_params(announcement, params), [:data, :starts_at, :ends_at, :rendered])
|
|
|> validate_required([:data])
|
|
end
|
|
|
|
defp validate_params(announcement, params) do
|
|
base_data =
|
|
%{
|
|
"content" => "",
|
|
"all_day" => false
|
|
}
|
|
|> Map.merge((announcement && announcement.data) || %{})
|
|
|
|
merged_data =
|
|
Map.merge(base_data, params.data)
|
|
|> Map.take(["content", "all_day"])
|
|
|
|
params
|
|
|> Map.merge(%{data: merged_data})
|
|
|> add_rendered_properties()
|
|
end
|
|
|
|
def add_rendered_properties(params) do
|
|
{content_html, _, _} =
|
|
Pleroma.Web.CommonAPI.Utils.format_input(params.data["content"], "text/plain",
|
|
mentions_format: :full
|
|
)
|
|
|
|
rendered = %{
|
|
"content" => content_html
|
|
}
|
|
|
|
params
|
|
|> Map.put(:rendered, rendered)
|
|
end
|
|
|
|
def add(params) do
|
|
changeset = changeset(%__MODULE__{}, params)
|
|
|
|
Repo.insert(changeset)
|
|
end
|
|
|
|
def update(announcement, params) do
|
|
changeset = changeset(announcement, params)
|
|
|
|
Repo.update(changeset)
|
|
end
|
|
|
|
def list_all do
|
|
__MODULE__
|
|
|> Repo.all()
|
|
end
|
|
|
|
def list_paginated(%{limit: limited_number, offset: offset_number}) do
|
|
__MODULE__
|
|
|> limit(^limited_number)
|
|
|> offset(^offset_number)
|
|
|> Repo.all()
|
|
end
|
|
|
|
def get_by_id(id) do
|
|
Repo.get_by(__MODULE__, id: id)
|
|
end
|
|
|
|
def delete_by_id(id) do
|
|
with announcement when not is_nil(announcement) <- get_by_id(id),
|
|
{:ok, _} <- Repo.delete(announcement) do
|
|
:ok
|
|
else
|
|
_ ->
|
|
:error
|
|
end
|
|
end
|
|
|
|
def read_by?(announcement, user) do
|
|
AnnouncementReadRelationship.exists?(user, announcement)
|
|
end
|
|
|
|
def mark_read_by(announcement, user) do
|
|
AnnouncementReadRelationship.mark_read(user, announcement)
|
|
end
|
|
|
|
def render_json(announcement, opts \\ []) do
|
|
extra_params =
|
|
case Keyword.fetch(opts, :for) do
|
|
{:ok, user} when not is_nil(user) ->
|
|
%{read: read_by?(announcement, user)}
|
|
|
|
_ ->
|
|
%{}
|
|
end
|
|
|
|
admin_extra_params =
|
|
case Keyword.fetch(opts, :admin) do
|
|
{:ok, true} ->
|
|
%{pleroma: %{raw_content: announcement.data["content"]}}
|
|
|
|
_ ->
|
|
%{}
|
|
end
|
|
|
|
base = %{
|
|
id: announcement.id,
|
|
content: announcement.rendered["content"],
|
|
starts_at: announcement.starts_at,
|
|
ends_at: announcement.ends_at,
|
|
all_day: announcement.data["all_day"],
|
|
published_at: announcement.inserted_at,
|
|
updated_at: announcement.updated_at,
|
|
mentions: [],
|
|
statuses: [],
|
|
tags: [],
|
|
emojis: [],
|
|
reactions: []
|
|
}
|
|
|
|
base
|
|
|> Map.merge(extra_params)
|
|
|> Map.merge(admin_extra_params)
|
|
end
|
|
|
|
# "visible" means:
|
|
# starts_at < time < ends_at
|
|
def list_all_visible_when(time) do
|
|
__MODULE__
|
|
|> where([a], is_nil(a.starts_at) or a.starts_at < ^time)
|
|
|> where([a], is_nil(a.ends_at) or a.ends_at > ^time)
|
|
|> Repo.all()
|
|
end
|
|
|
|
def list_all_visible do
|
|
list_all_visible_when(DateTime.now("Etc/UTC") |> elem(1))
|
|
end
|
|
end
|