total rebase
[anni] / lib / pleroma / bookmark.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.Bookmark do
6   use Ecto.Schema
7
8   import Ecto.Changeset
9   import Ecto.Query
10
11   alias Pleroma.Activity
12   alias Pleroma.Bookmark
13   alias Pleroma.BookmarkFolder
14   alias Pleroma.Repo
15   alias Pleroma.User
16
17   @type t :: %__MODULE__{}
18
19   schema "bookmarks" do
20     belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
21     belongs_to(:activity, Activity, type: FlakeId.Ecto.CompatType)
22     belongs_to(:folder, BookmarkFolder, type: FlakeId.Ecto.CompatType)
23
24     timestamps()
25   end
26
27   @spec create(Ecto.UUID.t(), Ecto.UUID.t()) ::
28           {:ok, Bookmark.t()} | {:error, Ecto.Changeset.t()}
29   def create(user_id, activity_id, folder_id \\ nil) do
30     attrs = %{
31       user_id: user_id,
32       activity_id: activity_id,
33       folder_id: folder_id
34     }
35
36     %Bookmark{}
37     |> cast(attrs, [:user_id, :activity_id, :folder_id])
38     |> validate_required([:user_id, :activity_id])
39     |> unique_constraint(:activity_id, name: :bookmarks_user_id_activity_id_index)
40     |> Repo.insert(
41       on_conflict: [set: [folder_id: folder_id]],
42       conflict_target: [:user_id, :activity_id]
43     )
44   end
45
46   @spec for_user_query(Ecto.UUID.t()) :: Ecto.Query.t()
47   def for_user_query(user_id, folder_id \\ nil) do
48     Bookmark
49     |> where(user_id: ^user_id)
50     |> maybe_filter_by_folder(folder_id)
51     |> join(:inner, [b], activity in assoc(b, :activity))
52     |> preload([b, a], activity: a)
53   end
54
55   defp maybe_filter_by_folder(query, nil), do: query
56
57   defp maybe_filter_by_folder(query, folder_id) do
58     query
59     |> where(folder_id: ^folder_id)
60   end
61
62   def get(user_id, activity_id) do
63     Bookmark
64     |> where(user_id: ^user_id)
65     |> where(activity_id: ^activity_id)
66     |> Repo.one()
67   end
68
69   @spec destroy(Ecto.UUID.t(), Ecto.UUID.t()) ::
70           {:ok, Bookmark.t()} | {:error, Ecto.Changeset.t()}
71   def destroy(user_id, activity_id) do
72     from(b in Bookmark,
73       where: b.user_id == ^user_id,
74       where: b.activity_id == ^activity_id
75     )
76     |> Repo.one()
77     |> Repo.delete()
78   end
79
80   def set_folder(bookmark, folder_id) do
81     bookmark
82     |> cast(%{folder_id: folder_id}, [:folder_id])
83     |> validate_required([:folder_id])
84     |> Repo.update()
85   end
86 end