From fcf3c9057ec1c49a0c9a400985c1dde4a5d7e9db Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 8 Mar 2022 18:21:20 -0500 Subject: [PATCH] Implement visibility filtering for announcements --- lib/pleroma/announcement.ex | 34 +++++++++ .../20220308012601_create_announcements.exs | 2 + test/pleroma/announcement_test.exs | 71 +++++++++++++++++++ test/support/factory.ex | 7 +- 4 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 test/pleroma/announcement_test.exs diff --git a/lib/pleroma/announcement.ex b/lib/pleroma/announcement.ex index b0e787fe0..b3c88b441 100644 --- a/lib/pleroma/announcement.ex +++ b/lib/pleroma/announcement.ex @@ -6,6 +6,7 @@ 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 @@ -15,16 +16,36 @@ defmodule Pleroma.Announcement do schema "announcements" do field(:data, :map) + field(:starts_at, :naive_datetime) + field(:ends_at, :naive_datetime) timestamps() end def change(struct, params \\ %{}) do struct + |> validate_params() |> cast(params, [:data]) |> validate_required([:data]) end + defp validate_params(params) do + base_struct = %{ + "content" => "", + "all_day" => false + } + + merged_data = + Map.merge(base_struct, params.data) + |> Map.take(["content", "all_day"]) + + %{ + data: merged_data, + starts_at: Map.get(params, "starts_at"), + ends_at: Map.get(params, "ends_at") + } + end + def add(params) do changeset = change(%__MODULE__{}, params) @@ -86,4 +107,17 @@ def render_json(announcement, opts \\ []) do base |> Map.merge(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(NaiveDateTime.utc_now()) + end end diff --git a/priv/repo/migrations/20220308012601_create_announcements.exs b/priv/repo/migrations/20220308012601_create_announcements.exs index e7c3b10a3..9f273fda9 100644 --- a/priv/repo/migrations/20220308012601_create_announcements.exs +++ b/priv/repo/migrations/20220308012601_create_announcements.exs @@ -5,6 +5,8 @@ def change do create_if_not_exists table(:announcements, primary_key: false) do add(:id, :uuid, primary_key: true) add(:data, :map) + add(:starts_at, :naive_datetime) + add(:ends_at, :naive_datetime) timestamps() end diff --git a/test/pleroma/announcement_test.exs b/test/pleroma/announcement_test.exs new file mode 100644 index 000000000..aa00f804b --- /dev/null +++ b/test/pleroma/announcement_test.exs @@ -0,0 +1,71 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.AnnouncementTest do + alias Pleroma.Announcement + + use Pleroma.DataCase, async: true + + import Pleroma.Factory + + describe "list_all_visible_when/1" do + setup do: {:ok, time: NaiveDateTime.utc_now()} + + test "with no start or end time", %{time: time} do + _announcement = insert(:announcement) + + assert [_] = Announcement.list_all_visible_when(time) + end + + test "with start time before current", %{time: time} do + before_now = NaiveDateTime.add(time, -10, :second) + + _announcement = insert(:announcement, %{starts_at: before_now}) + + assert [_] = Announcement.list_all_visible_when(time) + end + + test "with start time after current", %{time: time} do + after_now = NaiveDateTime.add(time, 10, :second) + + _announcement = insert(:announcement, %{starts_at: after_now}) + + assert [] = Announcement.list_all_visible_when(time) + end + + test "with end time after current", %{time: time} do + after_now = NaiveDateTime.add(time, 10, :second) + + _announcement = insert(:announcement, %{ends_at: after_now}) + + assert [_] = Announcement.list_all_visible_when(time) + end + + test "with end time before current", %{time: time} do + before_now = NaiveDateTime.add(time, -10, :second) + + _announcement = insert(:announcement, %{ends_at: before_now}) + + assert [] = Announcement.list_all_visible_when(time) + end + + test "with both start and end time", %{time: time} do + before_now = NaiveDateTime.add(time, -10, :second) + after_now = NaiveDateTime.add(time, 10, :second) + + _announcement = insert(:announcement, %{starts_at: before_now, ends_at: after_now}) + + assert [_] = Announcement.list_all_visible_when(time) + end + + test "with both start and end time, current not in the range", %{time: time} do + before_now = NaiveDateTime.add(time, -10, :second) + after_now = NaiveDateTime.add(time, 10, :second) + + _announcement = insert(:announcement, %{starts_at: after_now, ends_at: before_now}) + + assert [] = Announcement.list_all_visible_when(time) + end + end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index 85ea49cb2..620102bbb 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -628,11 +628,10 @@ def filter_factory do } end - def announcement_factory do + def announcement_factory(params \\ %{}, data \\ %{}) do %Pleroma.Announcement{ - data: %{ - "content" => "test announcement" - } + data: Map.merge(%{"content" => "test announcement"}, data) } + |> Map.merge(params) end end