aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/bookmark_folder.ex
blob: 14d37e1972c57ddbc4522ecca250f56b01c1e555 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Pleroma: A lightweight social networking server
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only

defmodule Pleroma.BookmarkFolder do
  use Ecto.Schema

  import Ecto.Changeset
  import Ecto.Query

  alias Pleroma.BookmarkFolder
  alias Pleroma.Emoji
  alias Pleroma.Repo
  alias Pleroma.User

  @type t :: %__MODULE__{}
  @primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}

  schema "bookmark_folders" do
    field(:name, :string)
    field(:emoji, :string)

    belongs_to(:user, User, type: FlakeId.Ecto.CompatType)

    timestamps()
  end

  def get_by_id(id), do: Repo.get_by(BookmarkFolder, id: id)

  def create(user_id, name, emoji \\ nil) do
    %BookmarkFolder{}
    |> cast(
      %{
        user_id: user_id,
        name: name,
        emoji: emoji
      },
      [:user_id, :name, :emoji]
    )
    |> validate_required([:user_id, :name])
    |> fix_emoji()
    |> validate_emoji()
    |> unique_constraint([:user_id, :name])
    |> Repo.insert()
  end

  def update(folder_id, name, emoji \\ nil) do
    get_by_id(folder_id)
    |> cast(
      %{
        name: name,
        emoji: emoji
      },
      [:name, :emoji]
    )
    |> fix_emoji()
    |> validate_emoji()
    |> unique_constraint([:user_id, :name])
    |> Repo.update()
  end

  defp fix_emoji(changeset) do
    with {:emoji_field, emoji} when is_binary(emoji) <-
           {:emoji_field, get_field(changeset, :emoji)},
         {:fixed_emoji, emoji} <-
           {:fixed_emoji,
            emoji
            |> Pleroma.Emoji.fully_qualify_emoji()
            |> Pleroma.Emoji.maybe_quote()} do
      put_change(changeset, :emoji, emoji)
    else
      {:emoji_field, _} -> changeset
    end
  end

  defp validate_emoji(changeset) do
    validate_change(changeset, :emoji, fn
      :emoji, nil ->
        []

      :emoji, emoji ->
        if Emoji.unicode?(emoji) or valid_local_custom_emoji?(emoji) do
          []
        else
          [emoji: "Invalid emoji"]
        end
    end)
  end

  defp valid_local_custom_emoji?(emoji) do
    with %{file: _path} <- Emoji.get(emoji) do
      true
    else
      _ -> false
    end
  end

  def delete(folder_id) do
    BookmarkFolder
    |> Repo.get_by(id: folder_id)
    |> Repo.delete()
  end

  def for_user(user_id) do
    BookmarkFolder
    |> where(user_id: ^user_id)
    |> Repo.all()
  end

  def belongs_to_user?(folder_id, user_id) do
    BookmarkFolder
    |> where(id: ^folder_id, user_id: ^user_id)
    |> Repo.exists?()
  end
end