dd1bc53ed93a901df112d7f5cac46c4ca0e53444
[akkoma] / lib / pleroma / web / activity_pub / object_validators / tag_validator.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do
6 use Ecto.Schema
7
8 alias Pleroma.EctoType.ActivityPub.ObjectValidators
9
10 import Ecto.Changeset
11
12 @primary_key false
13 embedded_schema do
14 # Common
15 field(:type, :string)
16 field(:name, :string)
17
18 # Mention, Hashtag
19 field(:href, ObjectValidators.Uri)
20
21 # Emoji
22 embeds_one :icon, IconObjectValidator, primary_key: false do
23 field(:type, :string)
24 field(:url, ObjectValidators.Uri)
25 end
26
27 field(:updated, ObjectValidators.DateTime)
28 field(:id, ObjectValidators.Uri)
29 end
30
31 def cast_and_validate(data) do
32 data
33 |> cast_data()
34 end
35
36 def cast_data(data) do
37 %__MODULE__{}
38 |> changeset(data)
39 end
40
41 def changeset(struct, %{"type" => "Mention"} = data) do
42 struct
43 |> cast(data, [:type, :name, :href])
44 |> validate_required([:type, :href])
45 end
46
47 def changeset(struct, %{"type" => "Hashtag", "name" => name} = data) do
48 name =
49 cond do
50 "#" <> name -> name
51 name -> name
52 end
53 |> String.downcase()
54
55 data = Map.put(data, "name", name)
56
57 struct
58 |> cast(data, [:type, :name, :href])
59 |> validate_required([:type, :name])
60 end
61
62 def changeset(struct, %{"type" => "Emoji"} = data) do
63 data = Map.put(data, "name", String.trim(data["name"], ":"))
64
65 struct
66 |> cast(data, [:type, :name, :updated, :id])
67 |> cast_embed(:icon, with: &icon_changeset/2)
68 |> validate_required([:type, :name, :icon])
69 end
70
71 def changeset(struct, %{"type" => "Book"} = data) do
72 data =
73 if Map.has_key?(data, "title") do
74 Map.put(data, "name", data["title"])
75 else
76 data
77 end
78
79 struct
80 |> cast(data, [:type, :name])
81 |> validate_required([:type, :name])
82 end
83
84 def changeset(struct, %{"type" => "Edition"} = data) do
85 # Sometimes it's title, sometimes name
86 # Don't ask me.
87 data =
88 if Map.has_key?(data, "title") do
89 Map.put(data, "name", data["title"])
90 else
91 data
92 end
93
94 struct
95 |> cast(data, [:type, :name])
96 |> validate_required([:type, :name])
97 end
98
99 def changeset(struct, %{"type" => "Work"} = data) do
100 data =
101 if Map.has_key?(data, "title") do
102 Map.put(data, "name", data["title"])
103 else
104 data
105 end
106
107 struct
108 |> cast(data, [:type, :name])
109 |> validate_required([:type, :name])
110 end
111
112 def changeset(struct, %{"type" => "Author"} = data) do
113 struct
114 |> cast(data, [:type, :name])
115 |> validate_required([:type, :name])
116 end
117
118 def icon_changeset(struct, data) do
119 struct
120 |> cast(data, [:type, :url])
121 |> validate_inclusion(:type, ~w[Image])
122 |> validate_required([:type, :url])
123 end
124 end