Merge branch 'develop' into gitlab-mr-iid-4381
This commit is contained in:
commit
e2f744bd68
9 changed files with 168 additions and 7 deletions
1
changelog.d/list-emoji.add
Normal file
1
changelog.d/list-emoji.add
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Allow attaching emojis to user lists
|
||||||
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.List do
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Emoji
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
|
|
@ -18,14 +19,53 @@ defmodule Pleroma.List do
|
||||||
field(:following, {:array, :string}, default: [])
|
field(:following, {:array, :string}, default: [])
|
||||||
field(:ap_id, :string)
|
field(:ap_id, :string)
|
||||||
field(:exclusive, :boolean, default: false)
|
field(:exclusive, :boolean, default: false)
|
||||||
|
field(:emoji, :string)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_changeset(list, attrs \\ %{}) do
|
def update_changeset(list, attrs \\ %{}) do
|
||||||
list
|
list
|
||||||
|> cast(attrs, [:title, :exclusive])
|
|> cast(attrs, [:title, :exclusive, :emoji])
|
||||||
|> validate_required([:title])
|
|> validate_required([:title])
|
||||||
|
|> fix_emoji()
|
||||||
|
|> validate_emoji()
|
||||||
|
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
|
||||||
|
|> Emoji.fully_qualify_emoji()
|
||||||
|
|> 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
|
end
|
||||||
|
|
||||||
def follow_changeset(list, attrs \\ %{}) do
|
def follow_changeset(list, attrs \\ %{}) do
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,8 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do
|
||||||
responses: %{
|
responses: %{
|
||||||
200 => Operation.response("List", "application/json", List),
|
200 => Operation.response("List", "application/json", List),
|
||||||
400 => Operation.response("Error", "application/json", ApiError),
|
400 => Operation.response("Error", "application/json", ApiError),
|
||||||
404 => Operation.response("Error", "application/json", ApiError)
|
404 => Operation.response("Error", "application/json", ApiError),
|
||||||
|
422 => Operation.response("Error", "application/json", ApiError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
@ -175,7 +176,8 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do
|
||||||
exclusive: %Schema{
|
exclusive: %Schema{
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Whether members of the list should be removed from the “Home” feed"
|
description: "Whether members of the list should be removed from the “Home” feed"
|
||||||
}
|
},
|
||||||
|
emoji: %Schema{type: :string, description: "List emoji", nullable: true}
|
||||||
},
|
},
|
||||||
required: [:title]
|
required: [:title]
|
||||||
},
|
},
|
||||||
|
|
@ -194,7 +196,8 @@ defmodule Pleroma.Web.ApiSpec.ListOperation do
|
||||||
exclusive: %Schema{
|
exclusive: %Schema{
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Whether members of the list should be removed from the “Home” feed"
|
description: "Whether members of the list should be removed from the “Home” feed"
|
||||||
}
|
},
|
||||||
|
emoji: %Schema{type: :string, description: "List emoji", nullable: true}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
required: true
|
required: true
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,26 @@ defmodule Pleroma.Web.ApiSpec.Schemas.List do
|
||||||
exclusive: %Schema{
|
exclusive: %Schema{
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
description: "Whether members of the list should be removed from the “Home” feed"
|
description: "Whether members of the list should be removed from the “Home” feed"
|
||||||
|
},
|
||||||
|
pleroma: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
emoji: %Schema{type: :string, description: "List emoji", nullable: true},
|
||||||
|
emoji_url: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "URL of the list emoji if it's a custom emoji, null otherwise",
|
||||||
|
nullable: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
example: %{
|
example: %{
|
||||||
"id" => "12249",
|
"id" => "12249",
|
||||||
"title" => "Friends"
|
"title" => "Friends",
|
||||||
|
"pleroma" => %{
|
||||||
|
"emoji" => nil,
|
||||||
|
"emoji_url" => nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.MastodonAPI.ListView do
|
defmodule Pleroma.Web.MastodonAPI.ListView do
|
||||||
use Pleroma.Web, :view
|
use Pleroma.Web, :view
|
||||||
|
|
||||||
|
alias Pleroma.Emoji
|
||||||
alias Pleroma.Web.MastodonAPI.ListView
|
alias Pleroma.Web.MastodonAPI.ListView
|
||||||
|
|
||||||
def render("index.json", %{lists: lists} = opts) do
|
def render("index.json", %{lists: lists} = opts) do
|
||||||
|
|
@ -11,10 +13,29 @@ defmodule Pleroma.Web.MastodonAPI.ListView do
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("show.json", %{list: list}) do
|
def render("show.json", %{list: list}) do
|
||||||
|
{emoji, emoji_url} = get_emoji(list.emoji)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
id: to_string(list.id),
|
id: to_string(list.id),
|
||||||
title: list.title,
|
title: list.title,
|
||||||
exclusive: list.exclusive
|
exclusive: list.exclusive,
|
||||||
|
pleroma: %{
|
||||||
|
emoji: emoji,
|
||||||
|
emoji_url: emoji_url
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_emoji(nil), do: {nil, nil}
|
||||||
|
|
||||||
|
defp get_emoji(emoji) do
|
||||||
|
if Emoji.unicode?(emoji) do
|
||||||
|
{emoji, nil}
|
||||||
|
else
|
||||||
|
case Emoji.get(emoji) do
|
||||||
|
nil -> {nil, nil}
|
||||||
|
emoji_data -> {emoji, Emoji.local_url(emoji_data.file)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddEmojiToLists do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:lists) do
|
||||||
|
add(:emoji, :string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -23,6 +23,29 @@ defmodule Pleroma.ListTest do
|
||||||
assert changeset.errors == [title: {"can't be blank", [validation: :required]}]
|
assert changeset.errors == [title: {"can't be blank", [validation: :required]}]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "creating a list with an emoji" do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, %Pleroma.List{} = list} = Pleroma.List.create(%{title: "title", emoji: "🕓"}, user)
|
||||||
|
%Pleroma.List{emoji: emoji} = Pleroma.List.get(list.id, user)
|
||||||
|
assert emoji == "🕓"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "validates emoji" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
assert {:error, changeset} =
|
||||||
|
Pleroma.List.create(%{title: "title", emoji: "not an emoji"}, user)
|
||||||
|
|
||||||
|
assert changeset.errors == [emoji: {"Invalid emoji", []}]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "updating a list's emoji" do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, list} = Pleroma.List.create(%{title: "title"}, user)
|
||||||
|
{:ok, %{emoji: emoji}} = Pleroma.List.update(list, %{emoji: "🕓"})
|
||||||
|
assert "🕓" == emoji
|
||||||
|
end
|
||||||
|
|
||||||
test "getting a list not belonging to the user" do
|
test "getting a list not belonging to the user" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,16 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
|
||||||
|> json_response_and_validate_schema(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "creating a list with an emoji" do
|
||||||
|
%{conn: conn} = oauth_access(["write:lists"])
|
||||||
|
|
||||||
|
assert %{"title" => "cuties", "pleroma" => %{"emoji" => "🕓", "emoji_url" => nil}} =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/lists", %{"title" => "cuties", "emoji" => "🕓"})
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
end
|
||||||
|
|
||||||
test "renders error for invalid params" do
|
test "renders error for invalid params" do
|
||||||
%{conn: conn} = oauth_access(["write:lists"])
|
%{conn: conn} = oauth_access(["write:lists"])
|
||||||
|
|
||||||
|
|
@ -31,6 +41,18 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
|
||||||
json_response_and_validate_schema(conn, 400)
|
json_response_and_validate_schema(conn, 400)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "renders error for an invalid emoji" do
|
||||||
|
%{conn: conn} = oauth_access(["write:lists"])
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/lists", %{"title" => "cuties", "emoji" => "not an emoji"})
|
||||||
|
|
||||||
|
assert %{"error" => "Invalid emoji"} =
|
||||||
|
json_response_and_validate_schema(conn, :unprocessable_entity)
|
||||||
|
end
|
||||||
|
|
||||||
test "listing a user's lists" do
|
test "listing a user's lists" do
|
||||||
%{conn: conn} = oauth_access(["read:lists", "write:lists"])
|
%{conn: conn} = oauth_access(["read:lists", "write:lists"])
|
||||||
|
|
||||||
|
|
@ -159,6 +181,17 @@ defmodule Pleroma.Web.MastodonAPI.ListControllerTest do
|
||||||
|> json_response_and_validate_schema(:ok)
|
|> json_response_and_validate_schema(:ok)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "updating a list's emoji" do
|
||||||
|
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
||||||
|
{:ok, list} = Pleroma.List.create(%{title: "name"}, user)
|
||||||
|
|
||||||
|
assert %{"pleroma" => %{"emoji" => "🕓", "emoji_url" => nil}} =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> put("/api/v1/lists/#{list.id}", %{"title" => "name", "emoji" => "🕓"})
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
end
|
||||||
|
|
||||||
test "validates title when renaming a list" do
|
test "validates title when renaming a list" do
|
||||||
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
%{user: user, conn: conn} = oauth_access(["write:lists"])
|
||||||
{:ok, list} = Pleroma.List.create(%{title: "name"}, user)
|
{:ok, list} = Pleroma.List.create(%{title: "name"}, user)
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,28 @@ defmodule Pleroma.Web.MastodonAPI.ListViewTest do
|
||||||
expected = %{
|
expected = %{
|
||||||
id: to_string(list.id),
|
id: to_string(list.id),
|
||||||
title: title,
|
title: title,
|
||||||
exclusive: false
|
exclusive: false,
|
||||||
|
pleroma: %{
|
||||||
|
emoji: nil,
|
||||||
|
emoji_url: nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert expected == ListView.render("show.json", %{list: list})
|
assert expected == ListView.render("show.json", %{list: list})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "show with a unicode emoji" do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, list} = Pleroma.List.create(%{title: "mortal enemies", emoji: "🕓"}, user)
|
||||||
|
|
||||||
|
assert %{
|
||||||
|
pleroma: %{
|
||||||
|
emoji: "🕓",
|
||||||
|
emoji_url: nil
|
||||||
|
}
|
||||||
|
} = ListView.render("show.json", %{list: list})
|
||||||
|
end
|
||||||
|
|
||||||
test "index" do
|
test "index" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue