Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85825793
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
28 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/pleroma/ecto_type/activity_pub/object_validators/map_of_string.ex b/lib/pleroma/ecto_type/activity_pub/object_validators/map_of_string.ex
deleted file mode 100644
index c36fe00b5..000000000
--- a/lib/pleroma/ecto_type/activity_pub/object_validators/map_of_string.ex
+++ /dev/null
@@ -1,27 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.MapOfString do
- use Ecto.Type
-
- alias Pleroma.MultiLanguage
-
- def type, do: :map
-
- def cast(%{} = object) do
- with {status, %{} = data} when status in [:modified, :ok] <-
- MultiLanguage.validate_map(object) do
- {:ok, data}
- else
- {_, nil} -> {:ok, nil}
- {:error, _} -> :error
- end
- end
-
- def cast(_), do: :error
-
- def dump(data), do: {:ok, data}
-
- def load(data), do: {:ok, data}
-end
diff --git a/lib/pleroma/multi_language.ex b/lib/pleroma/multi_language.ex
index ca69b7981..15c34832b 100644
--- a/lib/pleroma/multi_language.ex
+++ b/lib/pleroma/multi_language.ex
@@ -1,92 +1,81 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MultiLanguage do
+ import Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCode,
+ only: [good_locale_code?: 1]
+
defp template(:multi), do: Pleroma.Config.get([__MODULE__, :template])
defp template(:single), do: Pleroma.Config.get([__MODULE__, :single_line_template])
defp sep(:multi), do: Pleroma.Config.get([__MODULE__, :separator])
defp sep(:single), do: Pleroma.Config.get([__MODULE__, :single_line_separator])
- def is_good_locale_code?(code) do
- code
- |> String.codepoints()
- |> Enum.all?(&valid_char?/1)
- end
-
- # [a-zA-Z0-9-]
- defp valid_char?(char) do
- ("a" <= char and char <= "z") or
- ("A" <= char and char <= "Z") or
- ("0" <= char and char <= "9") or
- char == "-"
- end
-
def validate_map(%{} = object) do
{status, data} =
object
|> Enum.reduce({:ok, %{}}, fn
{lang, value}, {status, acc} when is_binary(lang) and is_binary(value) ->
- if is_good_locale_code?(lang) do
+ if good_locale_code?(lang) do
{status, Map.put(acc, lang, value)}
else
{:modified, acc}
end
_, {_status, acc} ->
{:modified, acc}
end)
if data == %{} do
{status, nil}
else
{status, data}
end
end
def validate_map(_), do: {:error, nil}
def map_to_str(data, opts \\ []) do
map_to_str_impl(data, if(opts[:multiline], do: :multi, else: :single))
end
defp map_to_str_impl(data, mode) do
with ks <- Map.keys(data),
[_, _ | _] <- ks,
ks <- Enum.sort(ks) do
template = template(mode)
ks
|> Enum.map(fn lang ->
format_template(template, %{code: lang, content: data[lang]})
end)
|> Enum.join(sep(mode))
else
[lang] -> data[lang]
_ -> nil
end
end
def str_to_map(data, opts \\ []) do
with lang when is_binary(lang) <- opts[:lang],
- true <- is_good_locale_code?(lang) do
+ true <- good_locale_code?(lang) do
%{lang => data}
else
_ ->
%{"und" => data}
end
end
def format_template(template, %{code: code, content: content}) do
template
|> String.replace(
["{code}", "{content}"],
fn
"{code}" -> code
"{content}" -> content
end,
global: true
)
end
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
index d81718123..884cb8f4a 100644
--- a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
@@ -1,99 +1,99 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
use Ecto.Schema
alias Pleroma.EctoType.ActivityPub.ObjectValidators
import Ecto.Changeset
@primary_key false
embedded_schema do
field(:id, :string)
field(:type, :string, default: "Link")
field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
field(:name, :string)
- field(:nameMap, ObjectValidators.MapOfString)
+ field(:nameMap, ObjectValidators.ContentLanguageMap)
field(:summary, :string)
- field(:summaryMap, ObjectValidators.MapOfString)
+ field(:summaryMap, ObjectValidators.ContentLanguageMap)
field(:blurhash, :string)
embeds_many :url, UrlObjectValidator, primary_key: false do
field(:type, :string, default: "Link")
field(:href, ObjectValidators.Uri)
field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
field(:width, :integer)
field(:height, :integer)
end
end
def cast_and_validate(data) do
data
|> cast_data()
|> validate_data()
end
def cast_data(data) do
%__MODULE__{}
|> changeset(data)
end
def changeset(struct, data) do
data =
data
|> fix_media_type()
|> fix_url()
struct
|> cast(data, [:id, :type, :mediaType, :name, :nameMap, :summary, :summaryMap, :blurhash])
|> cast_embed(:url, with: &url_changeset/2, required: true)
|> validate_inclusion(:type, ~w[Link Document Audio Image Video])
|> validate_required([:type, :mediaType])
end
def url_changeset(struct, data) do
data = fix_media_type(data)
struct
|> cast(data, [:type, :href, :mediaType, :width, :height])
|> validate_inclusion(:type, ["Link"])
|> validate_required([:type, :href, :mediaType])
end
def fix_media_type(data) do
Map.put_new(data, "mediaType", data["mimeType"] || "application/octet-stream")
end
defp handle_href(href, mediaType, data) do
[
%{
"href" => href,
"type" => "Link",
"mediaType" => mediaType,
"width" => data["width"],
"height" => data["height"]
}
]
end
defp fix_url(data) do
cond do
is_binary(data["url"]) ->
Map.put(data, "url", handle_href(data["url"], data["mediaType"], data))
is_binary(data["href"]) and data["url"] == nil ->
Map.put(data, "url", handle_href(data["href"], data["mediaType"], data))
true ->
data
end
end
defp validate_data(cng) do
cng
|> validate_inclusion(:type, ~w[Document Audio Image Video])
|> validate_required([:mediaType, :type])
end
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
index b626ccca6..881ab35a6 100644
--- a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex
@@ -1,73 +1,73 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator
# Activities and Objects, except (Create)ChatMessage
defmacro message_fields do
quote bind_quoted: binding() do
field(:type, :string)
field(:id, ObjectValidators.ObjectID, primary_key: true)
field(:to, ObjectValidators.Recipients, default: [])
field(:cc, ObjectValidators.Recipients, default: [])
field(:bto, ObjectValidators.Recipients, default: [])
field(:bcc, ObjectValidators.Recipients, default: [])
end
end
defmacro activity_fields do
quote bind_quoted: binding() do
field(:object, ObjectValidators.ObjectID)
field(:actor, ObjectValidators.ObjectID)
end
end
# All objects except Answer and ChatMessage
defmacro object_fields do
quote bind_quoted: binding() do
field(:content, :string)
field(:contentMap, ObjectValidators.ContentLanguageMap)
field(:published, ObjectValidators.DateTime)
field(:updated, ObjectValidators.DateTime)
field(:emoji, ObjectValidators.Emoji, default: %{})
embeds_many(:attachment, AttachmentValidator)
end
end
# Basically objects that aren't ChatMessage and Answer
defmacro status_object_fields do
quote bind_quoted: binding() do
# TODO: Remove actor on objects
field(:actor, ObjectValidators.ObjectID)
field(:attributedTo, ObjectValidators.ObjectID)
embeds_many(:tag, TagValidator)
field(:name, :string)
- field(:nameMap, ObjectValidators.MapOfString)
+ field(:nameMap, ObjectValidators.ContentLanguageMap)
field(:summary, :string)
- field(:summaryMap, ObjectValidators.MapOfString)
+ field(:summaryMap, ObjectValidators.ContentLanguageMap)
field(:context, :string)
field(:sensitive, :boolean, default: false)
field(:replies_count, :integer, default: 0)
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:quotes_count, :integer, default: 0)
field(:language, ObjectValidators.LanguageCode)
field(:inReplyTo, ObjectValidators.ObjectID)
field(:quoteUrl, ObjectValidators.ObjectID)
field(:url, ObjectValidators.BareUri)
field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])
end
end
end
diff --git a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex
index 2f80fb9b9..6927cd71f 100644
--- a/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/question_options_validator.ex
@@ -1,50 +1,50 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionOptionsValidator do
use Ecto.Schema
import Ecto.Changeset
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
@primary_key false
embedded_schema do
field(:name, :string)
field(:nameRendered, :string)
- field(:nameMap, ObjectValidators.MapOfString)
+ field(:nameMap, ObjectValidators.ContentLanguageMap)
embeds_one :replies, Replies, primary_key: false do
field(:totalItems, :integer)
field(:type, :string, default: "Collection")
end
field(:type, :string, default: "Note")
end
defp fix(data) do
data
# name is used in Answers, so better not change it
|> CommonFixes.fix_multilang_field("nameRendered", "nameMap", multiline: false)
end
def changeset(struct, data) do
data = fix(data)
struct
|> cast(data, [:name, :nameRendered, :nameMap, :type])
|> cast_embed(:replies, with: &replies_changeset/2)
|> validate_inclusion(:type, ["Note"])
|> validate_required([:name, :type])
end
def replies_changeset(struct, data) do
struct
|> cast(data, [:totalItems, :type])
|> validate_inclusion(:type, ["Collection"])
|> validate_required([:type])
end
end
diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex
index c94d5197b..890321923 100644
--- a/lib/pleroma/web/common_api/activity_draft.ex
+++ b/lib/pleroma/web/common_api/activity_draft.ex
@@ -1,432 +1,449 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.CommonAPI.ActivityDraft do
alias Pleroma.Activity
alias Pleroma.Conversation.Participation
alias Pleroma.Language.LanguageDetector
alias Pleroma.MultiLanguage
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils
import Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCode,
only: [good_locale_code?: 1]
import Pleroma.Web.Gettext
import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
@type t :: %__MODULE__{}
defstruct valid?: true,
errors: [],
user: nil,
params: %{},
- language: nil,
status: nil,
status_map: nil,
summary: nil,
summary_map: nil,
full_payload: nil,
attachments: [],
in_reply_to: nil,
in_reply_to_conversation: nil,
quote_post: nil,
visibility: nil,
expires_at: nil,
extra: nil,
emoji: %{},
content_html: nil,
content_html_map: nil,
mentions: [],
tags: [],
to: [],
cc: [],
context: nil,
sensitive: false,
+ language: nil,
object: nil,
preview?: false,
changes: %{}
def new(user, params) do
%__MODULE__{user: user}
|> put_params(params)
end
def create(user, params) do
user
|> new(params)
- |> language()
|> status()
|> summary()
|> with_valid(&attachments/1)
|> with_valid(&full_payload/1)
|> expires_at()
|> poll()
|> with_valid(&in_reply_to/1)
|> with_valid(&in_reply_to_conversation/1)
|> with_valid("e_post/1)
|> with_valid(&visibility/1)
|> with_valid(&content/1)
|> with_valid("ing_visibility/1)
|> with_valid(&to_and_cc/1)
|> with_valid(&context/1)
|> with_valid(&language/1)
|> sensitive()
|> with_valid(&object/1)
|> preview?()
|> with_valid(&changes/1)
|> validate()
end
def listen(user, params) do
user
|> new(params)
|> visibility()
|> to_and_cc()
|> context()
|> listen_object()
|> with_valid(&changes/1)
|> validate()
end
defp listen_object(draft) do
object =
draft.params
|> Map.take([:album, :artist, :title, :length])
|> Map.put(:externalLink, Map.get(draft.params, :external_link))
|> Map.new(fn {key, value} -> {to_string(key), value} end)
|> Map.put("type", "Audio")
|> Map.put("to", draft.to)
|> Map.put("cc", draft.cc)
|> Map.put("actor", draft.user.ap_id)
%__MODULE__{draft | object: object}
end
defp put_params(draft, params) do
params = Map.put_new(params, :in_reply_to_status_id, params[:in_reply_to_id])
%__MODULE__{draft | params: params}
end
- defp language(draft) do
- language =
- with language <- draft.params[:language],
- true <- good_locale_code?(language) do
- language
- else
- _ -> LanguageDetector.detect(draft.content_html <> " " <> draft.summary)
- end
-
- %__MODULE__{draft | language: language}
- end
-
defp status(%{params: %{status_map: %{} = status_map}} = draft) do
with {:ok, %{}} <- MultiLanguage.validate_map(status_map) do
%__MODULE__{draft | status_map: status_map}
else
_ -> add_error(draft, dgettext("errors", "status_map is not a valid multilang map"))
end
end
defp status(%{params: %{status: status}} = draft) do
%__MODULE__{draft | status: String.trim(status)}
end
defp summary(%{params: %{spoiler_text_map: %{} = spoiler_text_map}} = draft) do
with {:ok, %{}} <- MultiLanguage.validate_map(spoiler_text_map) do
%__MODULE__{draft | summary_map: spoiler_text_map}
else
_ -> add_error(draft, dgettext("errors", "spoiler_text_map is not a valid multilang map"))
end
end
defp summary(%{params: params} = draft) do
%__MODULE__{draft | summary: Map.get(params, :spoiler_text, "")}
end
- defp full_payload(%{status: status, status_map: nil} = draft) do
- full_payload(%__MODULE__{
- draft
- | status_map: MultiLanguage.str_to_map(status, lang: draft.language)
- })
- end
-
- defp full_payload(%{summary: summary, summary_map: nil} = draft) do
- full_payload(%__MODULE__{
- draft
- | summary_map: MultiLanguage.str_to_map(summary, lang: draft.language)
- })
- end
-
- defp full_payload(%{status_map: %{} = status_map, summary_map: %{} = summary_map} = draft) do
- status = status_map |> Enum.reduce("", fn {_lang, content}, acc -> acc <> " " <> content end)
+ # defp full_payload(%{status: status, status_map: nil} = draft) do
+ # full_payload(%__MODULE__{
+ # draft
+ # | status_map: MultiLanguage.str_to_map(status, lang: draft.language)
+ # })
+ # end
+
+ # defp full_payload(%{summary: summary, summary_map: nil} = draft) do
+ # full_payload(%__MODULE__{
+ # draft
+ # | summary_map: MultiLanguage.str_to_map(summary, lang: draft.language)
+ # })
+ # end
+
+ defp full_payload(draft) do
+ status =
+ with %{} <- draft.status_map do
+ draft.status_map
+ |> Enum.reduce("", fn {_lang, content}, acc -> acc <> " " <> content end)
+ else
+ _ -> draft.status
+ end
summary =
- summary_map |> Enum.reduce("", fn {_lang, content}, acc -> acc <> " " <> content end)
+ with %{} <- draft.summary_map do
+ draft.summary_map
+ |> Enum.reduce("", fn {_lang, content}, acc -> acc <> " " <> content end)
+ else
+ _ -> draft.summary || ""
+ end
full_payload = String.trim(status <> summary)
case Utils.validate_character_limit(full_payload, draft.attachments) do
:ok -> %__MODULE__{draft | full_payload: full_payload}
{:error, message} -> add_error(draft, message)
end
end
defp attachments(%{params: params} = draft) do
attachments = Utils.attachments_from_ids(params, draft.user)
draft = %__MODULE__{draft | attachments: attachments}
case Utils.validate_attachments_count(attachments) do
:ok -> draft
{:error, message} -> add_error(draft, message)
end
end
defp in_reply_to(%{params: %{in_reply_to_status_id: ""}} = draft), do: draft
defp in_reply_to(%{params: %{in_reply_to_status_id: id}} = draft) when is_binary(id) do
# If a post was deleted all its activities (except the newly added Delete) are purged too,
# thus lookup by Create db ID will yield nil just as if it never existed in the first place.
#
# We allow replying to Announce here, due to a Pleroma-FE quirk where if presented with
# an Announce id it will render it as if it was just the normal referenced post, but
# use the Announce id for replies in the in_reply_to_id key of a POST request to
# /api/v1/statuses, or as an :id in /api/v1/statuses/:id/*.
# TODO: Fix this quirk in FE and remove here and other affected places
with %Activity{} = activity <- Activity.get_by_id(id),
true <- Visibility.visible_for_user?(activity, draft.user),
{_, type} when type in ["Create", "Announce"] <- {:type, activity.data["type"]} do
%__MODULE__{draft | in_reply_to: activity}
else
nil ->
add_error(draft, dgettext("errors", "Cannot reply to a deleted status"))
false ->
add_error(draft, dgettext("errors", "Record not found"))
{:type, type} ->
add_error(
draft,
dgettext("errors", "Can only reply to posts, not %{type} activities",
type: inspect(type)
)
)
end
end
defp in_reply_to(%{params: %{in_reply_to_status_id: %Activity{} = in_reply_to}} = draft) do
%__MODULE__{draft | in_reply_to: in_reply_to}
end
defp in_reply_to(draft), do: draft
defp quote_post(%{params: %{quoted_status_id: id}} = draft) when not_empty_string(id) do
case Activity.get_by_id_with_object(id) do
%Activity{} = activity ->
%__MODULE__{draft | quote_post: activity}
_ ->
draft
end
end
defp quote_post(%{params: %{quote_id: id}} = draft) when not_empty_string(id) do
quote_post(%{draft | params: Map.put(draft.params, :quoted_status_id, id)})
end
defp quote_post(draft), do: draft
defp in_reply_to_conversation(draft) do
in_reply_to_conversation = Participation.get(draft.params[:in_reply_to_conversation_id])
%__MODULE__{draft | in_reply_to_conversation: in_reply_to_conversation}
end
defp visibility(%{params: params} = draft) do
case CommonAPI.get_visibility(params, draft.in_reply_to, draft.in_reply_to_conversation) do
{visibility, "direct"} when visibility != "direct" ->
add_error(draft, dgettext("errors", "The message visibility must be direct"))
{visibility, _} ->
%__MODULE__{draft | visibility: visibility}
end
end
defp can_quote?(_draft, _object, visibility) when visibility in ~w(public unlisted local) do
true
end
defp can_quote?(draft, object, "private") do
draft.user.ap_id == object.data["actor"]
end
defp can_quote?(_, _, _) do
false
end
defp quoting_visibility(%{quote_post: %Activity{}} = draft) do
with %Object{} = object <- Object.normalize(draft.quote_post, fetch: false),
true <- can_quote?(draft, object, Visibility.get_visibility(object)) do
draft
else
_ -> add_error(draft, dgettext("errors", "Cannot quote private message"))
end
end
defp quoting_visibility(draft), do: draft
defp expires_at(draft) do
case CommonAPI.check_expiry_date(draft.params[:expires_in]) do
{:ok, expires_at} -> %__MODULE__{draft | expires_at: expires_at}
{:error, message} -> add_error(draft, message)
end
end
defp poll(draft) do
case Utils.make_poll_data(draft.params) do
{:ok, {poll, poll_emoji}} ->
%__MODULE__{draft | extra: poll, emoji: Map.merge(draft.emoji, poll_emoji)}
{:error, message} ->
add_error(draft, message)
end
end
defp content(%{mentions: mentions} = draft) do
{content_html_or_map, mentioned_users, tags} = Utils.make_content_html(draft)
{content_html, content_html_map} = differentiate_string_map(content_html_or_map)
mentioned_ap_ids =
Enum.map(mentioned_users, fn {_, mentioned_user} -> mentioned_user.ap_id end)
mentions =
mentions
|> Kernel.++(mentioned_ap_ids)
|> Utils.get_addressed_users(draft.params[:to])
%__MODULE__{
draft
| content_html: content_html,
content_html_map: content_html_map,
mentions: mentions,
tags: tags
}
end
defp to_and_cc(draft) do
{to, cc} = Utils.get_to_and_cc(draft)
%__MODULE__{draft | to: to, cc: cc}
end
defp context(draft) do
context = Utils.make_context(draft.in_reply_to, draft.in_reply_to_conversation)
%__MODULE__{draft | context: context}
end
defp sensitive(draft) do
sensitive = draft.params[:sensitive]
%__MODULE__{draft | sensitive: sensitive}
end
+ defp language(draft) do
+ language =
+ with language <- draft.params[:language],
+ true <- good_locale_code?(language) do
+ language
+ end
+
+ cond do
+ language != nil ->
+ %__MODULE__{draft | language: language}
+
+ draft.status_map != nil ->
+ add_error(draft, dgettext("errors", "valid language is required when using status_map"))
+
+ true ->
+ %__MODULE__{draft | language: LanguageDetector.detect(draft.content_html <> " " <> draft.summary || "")}
+ end
+ end
+
defp object(draft) do
emoji = Map.merge(Pleroma.Emoji.Formatter.get_emoji_map(draft.full_payload), draft.emoji)
# Sometimes people create posts with subject containing emoji,
# since subjects are usually copied this will result in a broken
# subject when someone replies from an instance that does not have
# the emoji or has it under different shortcode. This is an attempt
# to mitigate this by copying emoji from inReplyTo if they are present
# in the subject.
summary_emoji =
with %Activity{} <- draft.in_reply_to,
%Object{data: %{"tag" => [_ | _] = tag}} <- Object.normalize(draft.in_reply_to) do
Enum.reduce(tag, %{}, fn
%{"type" => "Emoji", "name" => name, "icon" => %{"url" => url}}, acc ->
if String.contains?(draft.summary, name) do
Map.put(acc, name, url)
else
acc
end
_, acc ->
acc
end)
else
_ -> %{}
end
emoji = Map.merge(emoji, summary_emoji)
{:ok, note_data, _meta} = Builder.note(draft)
object =
note_data
|> Map.put("emoji", emoji)
|> Map.put(
"source",
Map.merge(get_source_map(draft), %{
"mediaType" => Utils.get_content_type(draft.params[:content_type])
})
)
|> Map.put("generator", draft.params[:generator])
|> Map.put("language", draft.language)
%__MODULE__{draft | object: object}
end
defp preview?(draft) do
preview? = Pleroma.Web.Utils.Params.truthy_param?(draft.params[:preview])
%__MODULE__{draft | preview?: preview?}
end
defp changes(draft) do
direct? = draft.visibility == "direct"
additional = %{"cc" => draft.cc, "directMessage" => direct?}
additional =
case draft.expires_at do
%DateTime{} = expires_at -> Map.put(additional, "expires_at", expires_at)
_ -> additional
end
changes =
%{
to: draft.to,
actor: draft.user,
context: draft.context,
object: draft.object,
additional: additional
}
|> Utils.maybe_add_list_data(draft.user, draft.visibility)
%__MODULE__{draft | changes: changes}
end
defp with_valid(%{valid?: true} = draft, func), do: func.(draft)
defp with_valid(draft, _func), do: draft
defp add_error(draft, message) do
%__MODULE__{draft | valid?: false, errors: [message | draft.errors]}
end
defp validate(%{valid?: true} = draft), do: {:ok, draft}
defp validate(%{errors: [message | _]}), do: {:error, message}
defp differentiate_string_map(%{} = map), do: {nil, map}
defp differentiate_string_map(str) when is_binary(str), do: {str, nil}
defp get_source_map(%{status_map: %{} = status_map} = _draft) do
%{
"content" => Pleroma.MultiLanguage.map_to_str(status_map, mutiline: true),
"contentMap" => status_map
}
end
defp get_source_map(%{status: status} = _draft) do
%{"content" => status}
end
end
diff --git a/test/pleroma/ecto_type/activity_pub/object_validators/map_of_string_test.exs b/test/pleroma/ecto_type/activity_pub/object_validators/map_of_string_test.exs
deleted file mode 100644
index 4ee179dc8..000000000
--- a/test/pleroma/ecto_type/activity_pub/object_validators/map_of_string_test.exs
+++ /dev/null
@@ -1,55 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.MapOfStringTest do
- alias Pleroma.EctoType.ActivityPub.ObjectValidators.MapOfString
- use Pleroma.DataCase, async: true
-
- test "it validates" do
- data = %{
- "en-US" => "mew mew",
- "en-GB" => "meow meow"
- }
-
- assert {:ok, ^data} = MapOfString.cast(data)
- end
-
- test "it validates empty strings" do
- data = %{
- "en-US" => "mew mew",
- "en-GB" => ""
- }
-
- assert {:ok, ^data} = MapOfString.cast(data)
- end
-
- test "it ignores non-strings within the map" do
- data = %{
- "en-US" => "mew mew",
- "en-GB" => 123
- }
-
- assert {:ok, validated_data} = MapOfString.cast(data)
-
- assert validated_data == %{"en-US" => "mew mew"}
- end
-
- test "it ignores bad locale codes" do
- data = %{
- "en-US" => "mew mew",
- "en_GB" => "meow meow",
- "en<<#@!$#!@%!GB" => "meow meow"
- }
-
- assert {:ok, validated_data} = MapOfString.cast(data)
-
- assert validated_data == %{"en-US" => "mew mew"}
- end
-
- test "it complains with non-map data" do
- assert :error = MapOfString.cast("mew")
- assert :error = MapOfString.cast(["mew"])
- assert :error = MapOfString.cast([%{"en-US" => "mew"}])
- end
-end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Oct 30, 3:05 AM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1799298
Default Alt Text
(28 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline