Add language support on /api/v1/statuses

This commit is contained in:
FloatingGhost 2023-01-02 02:15:38 +00:00
parent 6965a2f163
commit f86bf16430
6 changed files with 64 additions and 5 deletions

11
lib/pleroma/iso639.ex Normal file
View file

@ -0,0 +1,11 @@
defmodule Pleroma.ISO639 do
@file "priv/language-codes.json"
@data File.read!(@file)
|> Jason.decode!()
for %{"alpha2" => alpha2} <- @data do
def valid_alpha2?(unquote(alpha2)), do: true
end
def valid_alpha2?(_alpha2), do: false
end

View file

@ -30,6 +30,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
field(:replies, {:array, ObjectValidators.ObjectID}, default: []) field(:replies, {:array, ObjectValidators.ObjectID}, default: [])
field(:source, :map) field(:source, :map)
field(:content_map, :map)
end end
def cast_and_apply(data) do def cast_and_apply(data) do
@ -146,6 +147,20 @@ defp fix_source(%{"source" => source} = object) when is_binary(source) do
defp fix_source(object), do: object defp fix_source(object), do: object
defp fix_content_map_languages(%{"contentMap" => content_map} = object)
when is_map(content_map) do
# Only allow valid languages
content_map =
content_map
|> Enum.reject(fn {lang, content} ->
!Pleroma.ISO639.valid_alpha2?(lang)
end)
Map.put(object, "contentMap", content_map)
end
defp fix_content_map_languages(object), do: object
defp fix(data) do defp fix(data) do
data data
|> CommonFixes.fix_actor() |> CommonFixes.fix_actor()
@ -158,6 +173,7 @@ defp fix(data) do
|> Transmogrifier.fix_attachments() |> Transmogrifier.fix_attachments()
|> Transmogrifier.fix_emoji() |> Transmogrifier.fix_emoji()
|> Transmogrifier.fix_content_map() |> Transmogrifier.fix_content_map()
|> fix_content_map_languages()
end end
def changeset(struct, data) do def changeset(struct, data) do

View file

@ -22,6 +22,8 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
attachments: [], attachments: [],
in_reply_to: nil, in_reply_to: nil,
in_reply_to_conversation: nil, in_reply_to_conversation: nil,
language: nil,
content_map: %{},
quote_id: nil, quote_id: nil,
quote: nil, quote: nil,
visibility: nil, visibility: nil,
@ -58,6 +60,7 @@ def create(user, params) do
|> with_valid(&visibility/1) |> with_valid(&visibility/1)
|> with_valid(&quote_id/1) |> with_valid(&quote_id/1)
|> content() |> content()
|> with_valid(&language/1)
|> with_valid(&to_and_cc/1) |> with_valid(&to_and_cc/1)
|> with_valid(&context/1) |> with_valid(&context/1)
|> sensitive() |> sensitive()
@ -133,6 +136,17 @@ defp quote_id(%{params: %{quote_id: %Activity{} = quote}} = draft) do
defp quote_id(draft), do: draft defp quote_id(draft), do: draft
defp language(%{params: %{language: language}, content_html: content} = draft)
when is_binary(language) do
if Pleroma.ISO639.valid_alpha2?(language) do
%__MODULE__{draft | content_map: %{language => content}}
else
add_error(draft, dgettext("errors", "Invalid language"))
end
end
defp language(draft), do: draft
defp visibility(%{params: params} = draft) do defp visibility(%{params: params} = draft) do
case CommonAPI.get_visibility(params, draft.in_reply_to, draft.in_reply_to_conversation) do case CommonAPI.get_visibility(params, draft.in_reply_to, draft.in_reply_to_conversation) do
{visibility, "direct"} when visibility != "direct" -> {visibility, "direct"} when visibility != "direct" ->
@ -224,6 +238,7 @@ defp object(draft) do
"mediaType" => Utils.get_content_type(draft.params[:content_type]) "mediaType" => Utils.get_content_type(draft.params[:content_type])
}) })
|> Map.put("generator", draft.params[:generator]) |> Map.put("generator", draft.params[:generator])
|> Map.put("contentMap", draft.content_map)
%__MODULE__{draft | object: object} %__MODULE__{draft | object: object}
end end

View file

@ -169,6 +169,7 @@ def render(
|> Enum.map(fn user -> AccountView.render("mention.json", %{user: user}) end) |> Enum.map(fn user -> AccountView.render("mention.json", %{user: user}) end)
{pinned?, pinned_at} = pin_data(object, user) {pinned?, pinned_at} = pin_data(object, user)
lang = language(object)
%{ %{
id: to_string(activity.id), id: to_string(activity.id),
@ -199,7 +200,7 @@ def render(
mentions: mentions, mentions: mentions,
tags: reblogged[:tags] || [], tags: reblogged[:tags] || [],
application: build_application(object.data["generator"]), application: build_application(object.data["generator"]),
language: nil, language: lang,
emojis: [], emojis: [],
pleroma: %{ pleroma: %{
local: activity.local, local: activity.local,
@ -357,6 +358,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
{pinned?, pinned_at} = pin_data(object, user) {pinned?, pinned_at} = pin_data(object, user)
quote = Activity.get_quoted_activity_from_object(object) quote = Activity.get_quoted_activity_from_object(object)
lang = language(object)
%{ %{
id: to_string(activity.id), id: to_string(activity.id),
@ -391,7 +393,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
mentions: mentions, mentions: mentions,
tags: build_tags(tags), tags: build_tags(tags),
application: build_application(object.data["generator"]), application: build_application(object.data["generator"]),
language: nil, language: lang,
emojis: build_emojis(object.data["emoji"]), emojis: build_emojis(object.data["emoji"]),
quote_id: if(quote, do: quote.id, else: nil), quote_id: if(quote, do: quote.id, else: nil),
quote: maybe_render_quote(quote, opts), quote: maybe_render_quote(quote, opts),
@ -784,4 +786,12 @@ defp get_source_content_type(%{"mediaType" => type} = _source) do
defp get_source_content_type(_source) do defp get_source_content_type(_source) do
Utils.get_content_type(nil) Utils.get_content_type(nil)
end end
defp language(%Object{data: %{"contentMap" => contentMap}}) when is_map(contentMap) do
contentMap
|> Map.keys()
|> Enum.at(0)
end
defp language(_), do: nil
end end

1
priv/language-codes.json Normal file

File diff suppressed because one or more lines are too long

View file

@ -67,11 +67,17 @@ test "posting a status", %{conn: conn} do
|> post("/api/v1/statuses", %{ |> post("/api/v1/statuses", %{
"status" => "cofe", "status" => "cofe",
"spoiler_text" => "2hu", "spoiler_text" => "2hu",
"sensitive" => "0" "sensitive" => "0",
"language" => "ja"
}) })
assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = assert %{
json_response_and_validate_schema(conn_one, 200) "content" => "cofe",
"id" => id,
"spoiler_text" => "2hu",
"sensitive" => false,
"language" => "ja"
} = json_response_and_validate_schema(conn_one, 200)
assert Activity.get_by_id(id) assert Activity.get_by_id(id)