pre-link MFM content
Some checks failed
ci/woodpecker/push/release Pipeline was successful
ci/woodpecker/push/lint Pipeline was successful
ci/woodpecker/push/test Pipeline failed

This commit is contained in:
FloatingGhost 2022-07-10 17:18:53 +01:00
parent 291543d1cb
commit 705a8a1fe9
6 changed files with 129 additions and 14 deletions

View file

@ -133,7 +133,7 @@ def html_escape(text, "text/html") do
HTML.filter_tags(text) HTML.filter_tags(text)
end end
def html_escape(text, "text/plain") do def html_escape(text, format) when format in ["text/plain", "text/x.misskeymarkdown"] do
Regex.split(@link_regex, text, include_captures: true) Regex.split(@link_regex, text, include_captures: true)
|> Enum.map_every(2, fn chunk -> |> Enum.map_every(2, fn chunk ->
{:safe, part} = Phoenix.HTML.html_escape(chunk) {:safe, part} = Phoenix.HTML.html_escape(chunk)

View file

@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object.Fetcher alias Pleroma.Object.Fetcher
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations alias Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
@ -81,12 +82,21 @@ defp fix_replies(%{"replies" => %{"first" => first}} = data) do
defp fix_replies(data), do: data defp fix_replies(data), do: data
# https://github.com/misskey-dev/misskey/pull/8787 # https://github.com/misskey-dev/misskey/pull/8787
defp fix_misskey_content(%{"source" => %{"mediaType" => "text/x.misskeymarkdown"}} = object), defp fix_misskey_content(
do: object %{"source" => %{"mediaType" => "text/x.misskeymarkdown", "content" => content}} = object
) do
{linked, _, _} = Utils.format_input(content, "text/x.misskeymarkdown")
put_in(object, ["source", "content"], linked)
end
defp fix_misskey_content(%{"_misskey_content" => content} = object) do defp fix_misskey_content(%{"_misskey_content" => content} = object) do
{linked, _, _} = Utils.format_input(content, "text/x.misskeymarkdown")
object object
|> Map.put("source", %{"content" => content, "mediaType" => "text/x.misskeymarkdown"}) |> Map.put("source", %{
"content" => linked,
"mediaType" => "text/x.misskeymarkdown"
})
|> Map.delete("_misskey_content") |> Map.delete("_misskey_content")
end end

View file

@ -259,7 +259,8 @@ def format_input(text, format, options \\ [])
@doc """ @doc """
Formatting text to plain text, BBCode, HTML, or Markdown Formatting text to plain text, BBCode, HTML, or Markdown
""" """
def format_input(text, "text/plain", options) do def format_input(text, format, options)
when format in ["text/plain", "text/x.misskeymarkdown"] do
text text
|> Formatter.html_escape("text/plain") |> Formatter.html_escape("text/plain")
|> Formatter.linkify(options) |> Formatter.linkify(options)
@ -291,15 +292,6 @@ def format_input(text, "text/markdown", options) do
|> Formatter.html_escape("text/html") |> Formatter.html_escape("text/html")
end end
def format_input(text, "text/x.misskeymarkdown", options) do
text
|> Formatter.html_escape("text/plain")
|> Formatter.linkify(options)
|> (fn {text, mentions, tags} ->
{String.replace(text, ~r/\r?\n/, "<br>"), mentions, tags}
end).()
end
def format_naive_asctime(date) do def format_naive_asctime(date) do
date |> DateTime.from_naive!("Etc/UTC") |> format_asctime date |> DateTime.from_naive!("Etc/UTC") |> format_asctime
end end

View file

@ -0,0 +1,31 @@
{
"id": "https://misskey.local.live/notes/92j1n3owja",
"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>",
"_misskey_content": "@akkoma_user linkifylink #dancedance $[jelly mfm goes here] \n\n## aaa",
"published": "2022-07-10T15:37:36.368Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://misskey.local.live/users/92hzkskwgy/followers",
"http://localhost:4001/users/akkoma_user"
],
"inReplyTo": null,
"attachment": [],
"sensitive": false,
"tag": [
{
"type": "Hashtag",
"href": "https://misskey.local.live/tags/dancedance",
"name": "#dancedance"
},
{
"type": "Mention",
"href": "http://localhost:4001/users/akkoma_user",
"name": "@akkoma_user"
}
]
}

34
test/fixtures/misskey/mfm_x_format.json vendored Normal file
View file

@ -0,0 +1,34 @@
{
"id": "https://misskey.local.live/notes/92j1n3owja",
"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>",
"source": {
"content": "@akkoma_user linkifylink #dancedance $[jelly mfm goes here] \n\n## aaa",
"mediaType": "text/x.misskeymarkdown"
},
"published": "2022-07-10T15:37:36.368Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://misskey.local.live/users/92hzkskwgy/followers",
"http://localhost:4001/users/akkoma_user"
],
"inReplyTo": null,
"attachment": [],
"sensitive": false,
"tag": [
{
"type": "Hashtag",
"href": "https://misskey.local.live/tags/dancedance",
"name": "#dancedance"
},
{
"type": "Mention",
"href": "http://localhost:4001/users/akkoma_user",
"name": "@akkoma_user"
}
]
}

View file

@ -10,6 +10,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
import Pleroma.Factory import Pleroma.Factory
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe "Notes" do describe "Notes" do
setup do setup do
user = insert(:user) user = insert(:user)
@ -63,5 +69,47 @@ test "a note with an attachment should work", _ do
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note) %{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
end end
test "a misskey MFM status with a content field should work and be linked", _ do
local_user = insert(:user, %{nickname: "akkoma_user"})
insert(:user, %{ap_id: "https://misskey.local.live/users/92hzkskwgy"})
note =
"test/fixtures/misskey/mfm_x_format.json"
|> 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: %{
source: %{"content" => ^expected_content, "mediaType" => "text/x.misskeymarkdown"}
}
} = ArticleNotePageValidator.cast_and_validate(note)
end
test "a misskey MFM status with a _misskey_content field should work and be linked", _ do
local_user = insert(:user, %{nickname: "akkoma_user"})
insert(:user, %{ap_id: "https://misskey.local.live/users/92hzkskwgy"})
note =
"test/fixtures/misskey/mfm_underscore_format.json"
|> 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: %{
source: %{"content" => ^expected_content, "mediaType" => "text/x.misskeymarkdown"}
}
} = ArticleNotePageValidator.cast_and_validate(note)
end
end end
end end