diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index 5e0d1aa8e..4ef036f34 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -103,7 +103,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do meta ) when objtype in ~w[Question Answer Audio Video Image Event Article Note Page] do - with {:ok, object_data} <- cast_and_apply_and_stringify_with_history(object), + with {:ok, object_data} <- + cast_and_apply_and_stringify_with_history(object, activity_data: create_activity), meta = Keyword.put(meta, :object_data, object_data), {:ok, create_activity} <- create_activity @@ -213,40 +214,42 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do def validate(o, m), do: {:error, {:validator_not_set, {o, m}}} - def cast_and_apply_and_stringify_with_history(object) do + def cast_and_apply_and_stringify_with_history(object, meta \\ []) do do_separate_with_history(object, fn object -> - with {:ok, object_data} <- cast_and_apply(object), + with {:ok, object_data} <- cast_and_apply(object, meta), object_data <- object_data |> stringify_keys() do {:ok, object_data} end end) end - def cast_and_apply(%{"type" => "ChatMessage"} = object) do + def cast_and_apply(object, meta \\ []) + + def cast_and_apply(%{"type" => "ChatMessage"} = object, _) do ChatMessageValidator.cast_and_apply(object) end - def cast_and_apply(%{"type" => "Question"} = object) do + def cast_and_apply(%{"type" => "Question"} = object, _) do QuestionValidator.cast_and_apply(object) end - def cast_and_apply(%{"type" => "Answer"} = object) do + def cast_and_apply(%{"type" => "Answer"} = object, _) do AnswerValidator.cast_and_apply(object) end - def cast_and_apply(%{"type" => type} = object) when type in ~w[Audio Image Video] do + def cast_and_apply(%{"type" => type} = object, _) when type in ~w[Audio Image Video] do AudioImageVideoValidator.cast_and_apply(object) end - def cast_and_apply(%{"type" => "Event"} = object) do - EventValidator.cast_and_apply(object) + def cast_and_apply(%{"type" => "Event"} = object, meta) do + EventValidator.cast_and_apply(object, meta) end - def cast_and_apply(%{"type" => type} = object) when type in ~w[Article Note Page] do - ArticleNotePageValidator.cast_and_apply(object) + def cast_and_apply(%{"type" => type} = object, meta) when type in ~w[Article Note Page] do + ArticleNotePageValidator.cast_and_apply(object, meta) end - def cast_and_apply(o), do: {:error, {:validator_not_set, o}} + def cast_and_apply(o, _), do: {:error, {:validator_not_set, o}} def stringify_keys(object) when is_struct(object) do object diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex index 73101f20f..9e6a1b0fb 100644 --- a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex @@ -28,21 +28,21 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do field(:replies, {:array, ObjectValidators.ObjectID}, default: []) end - def cast_and_apply(data) do + def cast_and_apply(data, meta \\ []) do data - |> cast_data + |> cast_data(meta) |> apply_action(:insert) end - def cast_and_validate(data) do + def cast_and_validate(data, meta \\ []) do data - |> cast_data() + |> cast_data(meta) |> validate_data() end - def cast_data(data) do + def cast_data(data, meta \\ []) do %__MODULE__{} - |> changeset(data) + |> changeset(data, meta) end defp fix_url(%{"url" => url} = data) when is_bitstring(url), do: data @@ -76,7 +76,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do def fix_attachments(data), do: data - defp fix(data) do + defp fix(data, meta) do data |> CommonFixes.fix_actor() |> CommonFixes.fix_object_defaults() @@ -86,11 +86,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do |> fix_attachments() |> Transmogrifier.fix_emoji() |> Transmogrifier.fix_content_map() - |> Transmogrifier.maybe_add_language() + |> CommonFixes.maybe_add_language(meta) end - def changeset(struct, data) do - data = fix(data) + def changeset(struct, data, meta \\ []) do + data = fix(data, meta) struct |> cast(data, __schema__(:fields) -- [:attachment, :tag]) diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex index add46d561..66e44afe6 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex @@ -10,6 +10,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Utils + import Pleroma.Web.CommonAPI.Utils, only: [is_good_locale_code?: 1] + def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do {:ok, data} = ObjectValidators.Recipients.cast(message[field] || field_fallback) @@ -76,4 +78,44 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do Map.put(data, "to", to) end + + def maybe_add_language(object, meta \\ []) do + language = + [ + get_language_from_context(object), + get_language_from_context(Keyword.get(meta, :activity_data)), + get_language_from_content_map(object) + ] + |> Enum.find(&is_good_locale_code?(&1)) + + if language do + Map.put(object, "language", language) + else + object + end + end + + defp get_language_from_context(%{"@context" => context}) when is_list(context) do + case context + |> Enum.find(fn + %{"@language" => language} -> language != "und" + _ -> nil + end) do + %{"@language" => language} -> language + _ -> nil + end + end + + defp get_language_from_context(_), do: nil + + defp get_language_from_content_map(%{"contentMap" => content_map, "content" => source_content}) do + content_groups = Map.to_list(content_map) + + case Enum.find(content_groups, fn {_, content} -> content == source_content end) do + {language, _} -> language + _ -> nil + end + end + + defp get_language_from_content_map(_), do: nil end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 732d878c4..fd7059dea 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -22,7 +22,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do alias Pleroma.Web.Federator import Ecto.Query - import Pleroma.Web.CommonAPI.Utils, only: [is_good_locale_code?: 1] import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1] require Logger @@ -44,7 +43,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> fix_content_map() |> fix_addressing() |> fix_summary() - |> maybe_add_language() end def fix_summary(%{"summary" => nil} = object) do @@ -459,7 +457,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do |> strip_internal_fields() |> fix_type(fetch_options) |> fix_in_reply_to(fetch_options) - |> maybe_add_language_from_activity(data) data = Map.put(data, "object", object) options = Keyword.put(options, :local, false) @@ -966,56 +963,4 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end defp maybe_add_content_map(object), do: object - - def maybe_add_language(object) do - language = - [ - get_language_from_context(object), - get_language_from_content_map(object), - get_language_from_content(object) - ] - |> Enum.find(&is_good_locale_code?(&1)) - - if language do - Map.put(object, "language", language) - else - object - end - end - - def maybe_add_language_from_activity(object, activity) do - language = get_language_from_context(activity) - - if is_good_locale_code?(language) do - Map.put(object, "language", language) - else - object - end - end - - defp get_language_from_context(%{"@context" => context}) when is_list(context) do - case context - |> Enum.find(fn - %{"@language" => language} -> language != "und" - _ -> nil - end) do - %{"@language" => language} -> language - _ -> nil - end - end - - defp get_language_from_context(_), do: nil - - defp get_language_from_content_map(%{"contentMap" => content_map, "content" => source_content}) do - content_groups = Map.to_list(content_map) - - case Enum.find(content_groups, fn {_, content} -> content == source_content end) do - {language, _} -> language - _ -> nil - end - end - - defp get_language_from_content_map(_), do: nil - - defp get_language_from_content(_), do: nil end