d97c5e72826c240de8f6b3b456a1cfdbf9d591dd
[akkoma] / lib / pleroma / announcement.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Announcement do
6 use Ecto.Schema
7
8 import Ecto.Changeset, only: [cast: 3, validate_required: 2]
9 import Ecto.Query
10
11 alias Pleroma.AnnouncementReadRelationship
12 alias Pleroma.Repo
13
14 @type t :: %__MODULE__{}
15 @primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
16
17 schema "announcements" do
18 field(:data, :map)
19 field(:starts_at, :utc_datetime)
20 field(:ends_at, :utc_datetime)
21 field(:rendered, :map)
22
23 timestamps(type: :utc_datetime)
24 end
25
26 def change(struct, params \\ %{}) do
27 struct
28 |> cast(validate_params(struct, params), [:data, :starts_at, :ends_at, :rendered])
29 |> validate_required([:data])
30 end
31
32 defp validate_params(struct, params) do
33 base_data =
34 %{
35 "content" => "",
36 "all_day" => false
37 }
38 |> Map.merge((struct && struct.data) || %{})
39
40 merged_data =
41 Map.merge(base_data, params.data)
42 |> Map.take(["content", "all_day"])
43
44 params
45 |> Map.merge(%{data: merged_data})
46 |> add_rendered_properties()
47 end
48
49 def add_rendered_properties(params) do
50 {content_html, _, _} =
51 Pleroma.Web.CommonAPI.Utils.format_input(params.data["content"], "text/plain",
52 mentions_format: :full
53 )
54
55 rendered = %{
56 "content" => content_html
57 }
58
59 params
60 |> Map.put(:rendered, rendered)
61 end
62
63 def add(params) do
64 changeset = change(%__MODULE__{}, params)
65
66 Repo.insert(changeset)
67 end
68
69 def update(announcement, params) do
70 changeset = change(announcement, params)
71
72 Repo.update(changeset)
73 end
74
75 def list_all do
76 __MODULE__
77 |> Repo.all()
78 end
79
80 def list_paginated(%{limit: limited_number, offset: offset_number}) do
81 __MODULE__
82 |> limit(^limited_number)
83 |> offset(^offset_number)
84 |> Repo.all()
85 end
86
87 def get_by_id(id) do
88 Repo.get_by(__MODULE__, id: id)
89 end
90
91 def delete_by_id(id) do
92 with announcement when not is_nil(announcement) <- get_by_id(id),
93 {:ok, _} <- Repo.delete(announcement) do
94 :ok
95 else
96 _ ->
97 :error
98 end
99 end
100
101 def read_by?(announcement, user) do
102 AnnouncementReadRelationship.exists?(user, announcement)
103 end
104
105 def mark_read_by(announcement, user) do
106 AnnouncementReadRelationship.mark_read(user, announcement)
107 end
108
109 def render_json(announcement, opts \\ []) do
110 extra_params =
111 case Keyword.fetch(opts, :for) do
112 {:ok, user} when not is_nil(user) ->
113 %{read: read_by?(announcement, user)}
114
115 _ ->
116 %{}
117 end
118
119 admin_extra_params =
120 case Keyword.fetch(opts, :admin) do
121 {:ok, true} ->
122 %{pleroma: %{raw_content: announcement.data["content"]}}
123
124 _ ->
125 %{}
126 end
127
128 base = %{
129 id: announcement.id,
130 content: announcement.rendered["content"],
131 starts_at: announcement.starts_at,
132 ends_at: announcement.ends_at,
133 all_day: announcement.data["all_day"],
134 published_at: announcement.inserted_at,
135 updated_at: announcement.updated_at,
136 mentions: [],
137 statuses: [],
138 tags: [],
139 emojis: [],
140 reactions: []
141 }
142
143 base
144 |> Map.merge(extra_params)
145 |> Map.merge(admin_extra_params)
146 end
147
148 # "visible" means:
149 # starts_at < time < ends_at
150 def list_all_visible_when(time) do
151 __MODULE__
152 |> where([a], is_nil(a.starts_at) or a.starts_at < ^time)
153 |> where([a], is_nil(a.ends_at) or a.ends_at > ^time)
154 |> Repo.all()
155 end
156
157 def list_all_visible do
158 list_all_visible_when(DateTime.now("Etc/UTC") |> elem(1))
159 end
160 end