end
end
+ def mention_tag(%User{id: id} = user, nickname, opts \\ []) do
+ user_url = user.uri || user.ap_id
+ nickname_text = get_nickname_text(nickname, opts)
+
+ :span
+ |> Phoenix.HTML.Tag.content_tag(
+ Phoenix.HTML.Tag.content_tag(
+ :a,
+ ["@", Phoenix.HTML.Tag.content_tag(:span, nickname_text)],
+ "data-user": id,
+ class: "u-url mention",
+ href: user_url,
+ rel: "ugc"
+ ),
+ class: "h-card"
+ )
+ |> Phoenix.HTML.safe_to_string()
+ end
+
def mention_handler("@" <> nickname, buffer, opts, acc) do
case User.get_cached_by_nickname(nickname) do
- %User{id: id} = user ->
- user_url = user.uri || user.ap_id
- nickname_text = get_nickname_text(nickname, opts)
-
- link =
- Phoenix.HTML.Tag.content_tag(
- :span,
- Phoenix.HTML.Tag.content_tag(
- :a,
- ["@", Phoenix.HTML.Tag.content_tag(:span, nickname_text)],
- "data-user": id,
- class: "u-url mention",
- href: user_url,
- rel: "ugc"
- ),
- class: "h-card"
- )
- |> Phoenix.HTML.safe_to_string()
+ %User{id: _id} = user ->
+ link = mention_tag(user, nickname, opts)
{link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}}
defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
use Ecto.Schema
-
+ alias Pleroma.User
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object.Fetcher
alias Pleroma.Web.CommonAPI.Utils
defp fix_replies(data), do: data
+ defp remote_mention_resolver(%{"tag" => tags}, "@" <> nickname = mention, buffer, opts, acc) do
+ with mention_tag <-
+ Enum.find(tags, fn t -> t["type"] == "Mention" && t["name"] == mention end),
+ false <- is_nil(mention_tag),
+ {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(mention_tag["href"]) do
+ link = Pleroma.Formatter.mention_tag(user, nickname, opts)
+ {link, %{acc | mentions: MapSet.put(acc.mentions, {"@" <> nickname, user})}}
+ else
+ _ -> {buffer, acc}
+ end
+ end
+
# https://github.com/misskey-dev/misskey/pull/8787
defp fix_misskey_content(
%{"source" => %{"mediaType" => "text/x.misskeymarkdown", "content" => content}} = object
) do
- {linked, _, _} = Utils.format_input(content, "text/x.misskeymarkdown")
+ mention_handler = fn nick, buffer, opts, acc ->
+ remote_mention_resolver(object, nick, buffer, opts, acc)
+ end
+
+ {linked, _, _} =
+ Utils.format_input(content, "text/x.misskeymarkdown", mention_handler: mention_handler)
+
Map.put(object, "content", linked)
end
defp fix_misskey_content(%{"_misskey_content" => content} = object) do
- {linked, _, _} = Utils.format_input(content, "text/x.misskeymarkdown")
+ mention_handler = fn nick, buffer, opts, acc ->
+ remote_mention_resolver(object, nick, buffer, opts, acc)
+ end
+
+ {linked, _, _} =
+ Utils.format_input(content, "text/x.misskeymarkdown", mention_handler: mention_handler)
object
|> Map.put("source", %{
"type": "Note",
"attributedTo": "https://misskey.local.live/users/92hzkskwgy",
"summary": null,
- "content": "<p><a href=\"https://akkoma.local.live/users/akkoma_user\" class=\"u-url mention\">@akkoma_user@akkoma.local.live</a><span> linkifylink </span><a href=\"https://misskey.local.live/tags/dancedance\" rel=\"tag\">#dancedance</a><span> </span><i><span> mfm goes here</span></i><span> <br><br>## aaa</span></p>",
+ "content": "this gets replaced",
"source": {
- "content": "@akkoma_user linkifylink #dancedance $[jelly mfm goes here] \n\n## aaa",
+ "content": "@akkoma_user @remote_user @oops_not_a_mention linkifylink #dancedance $[jelly mfm goes here] \n\n## aaa",
"mediaType": "text/x.misskeymarkdown"
},
"published": "2022-07-10T15:37:36.368Z",
"type": "Mention",
"href": "http://localhost:4001/users/akkoma_user",
"name": "@akkoma_user"
+ },
+ {
+ "type": "Mention",
+ "href": "http://misskey.local.live/users/remote_user",
+ "name": "@remote_user"
}
]
}
end
test "a misskey MFM status with a content field should work and be linked", _ do
- local_user = insert(:user, %{nickname: "akkoma_user"})
+ local_user =
+ insert(:user, %{nickname: "akkoma_user", ap_id: "http://localhost:4001/users/akkoma_user"})
+
+ remote_user =
+ insert(:user, %{
+ nickname: "remote_user",
+ ap_id: "http://misskey.local.live/users/remote_user"
+ })
insert(:user, %{ap_id: "https://misskey.local.live/users/92hzkskwgy"})
|> File.read!()
|> Jason.decode!()
- expected_content =
- "<span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{local_user.id}\" href=\"#{local_user.ap_id}\" rel=\"ugc\">@<span>akkoma_user</span></a></span> linkifylink <a class=\"hashtag\" data-tag=\"dancedance\" href=\"http://localhost:4001/tag/dancedance\" rel=\"tag ugc\">#dancedance</a> $[jelly mfm goes here] <br><br>## aaa"
-
%{
valid?: true,
changes: %{
- content: ^expected_content,
+ content: content,
source: %{
- "content" => "@akkoma_user linkifylink #dancedance $[jelly mfm goes here] \n\n## aaa",
+ "content" =>
+ "@akkoma_user @remote_user @oops_not_a_mention linkifylink #dancedance $[jelly mfm goes here] \n\n## aaa",
"mediaType" => "text/x.misskeymarkdown"
}
}
} = ArticleNotePageValidator.cast_and_validate(note)
+
+ assert content =~
+ "<span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{local_user.id}\" href=\"#{local_user.ap_id}\" rel=\"ugc\">@<span>akkoma_user</span></a></span>"
+
+ assert content =~
+ "<span class=\"h-card\"><a class=\"u-url mention\" data-user=\"#{remote_user.id}\" href=\"#{remote_user.ap_id}\" rel=\"ugc\">@<span>remote_user</span></a></span>"
+
+ assert content =~ "@oops_not_a_mention"
+ assert content =~ "$[jelly mfm goes here] <br><br>## aaa"
end
test "a misskey MFM status with a _misskey_content field should work and be linked", _ do
- local_user = insert(:user, %{nickname: "akkoma_user"})
+ local_user =
+ insert(:user, %{nickname: "akkoma_user", ap_id: "http://localhost:4001/users/akkoma_user"})
insert(:user, %{ap_id: "https://misskey.local.live/users/92hzkskwgy"})