[#58] pre-link MFM content (#59)

Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/59
This commit is contained in:
floatingghost 2022-07-10 17:06:25 +00:00
parent 82fa766ed7
commit 5ad256f170
9 changed files with 175 additions and 18 deletions

View file

@ -36,6 +36,33 @@ config :logger, :console,
level: :info
```
## Testing with HTTPS
If you end up developing alongside other software like misskey,
you will not be able to federate without an SSL certificate. You should
be able to use the snakeoil certificate that comes standard with most
distributions or generate one from scratch, then force elixir to accept it.
HTTP clients are none too keen to accept self-signed certs, but we can do
this:
```elixir
config :pleroma, :http,
adapter: [
pools: %{
default: [
conn_opts: [
transport_opts: [
verify: :verify_none
]
]
]
}
]
```
Now your SSL requests will work. Hooray.
## Testing
1. Create a `test.secret.exs` file with the content as shown below

View file

@ -58,9 +58,6 @@ defmodule Pleroma.Application do
Pleroma.Docs.JSON.compile()
limiters_setup()
Logger.info("Starting Finch")
Finch.start_link(name: MyFinch)
# Define workers and child supervisors to be supervised
children =
[
@ -70,6 +67,7 @@ defmodule Pleroma.Application do
Pleroma.Web.Plugs.RateLimiter.Supervisor
] ++
cachex_children() ++
http_children() ++
[
Pleroma.Stats,
Pleroma.JobQueueMonitor,
@ -276,4 +274,13 @@ defmodule Pleroma.Application do
ConcurrentLimiter.new(module, max_running, max_waiting)
end)
end
defp http_children do
config =
[:http, :adapter]
|> Config.get([])
|> Keyword.put(:name, MyFinch)
[{Finch, config}]
end
end

View file

@ -133,7 +133,7 @@ defmodule Pleroma.Formatter do
HTML.filter_tags(text)
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)
|> Enum.map_every(2, fn chunk ->
{:safe, part} = Phoenix.HTML.html_escape(chunk)

View file

@ -65,7 +65,6 @@ defmodule Pleroma.HTTP do
options = put_in(options[:adapter], adapter_opts)
params = options[:params] || []
request = build_request(method, headers, options, url, body, params)
client = Tesla.client([Tesla.Middleware.FollowRedirects])
request(client, request)

View file

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

View file

@ -259,7 +259,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do
@doc """
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
|> Formatter.html_escape("text/plain")
|> Formatter.linkify(options)
@ -291,15 +292,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|> Formatter.html_escape("text/html")
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
date |> DateTime.from_naive!("Etc/UTC") |> format_asctime
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
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
describe "Notes" do
setup do
user = insert(:user)
@ -63,5 +69,55 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
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: %{
content: ^expected_content,
source: %{
"content" => "@akkoma_user linkifylink #dancedance $[jelly mfm goes here] \n\n## aaa",
"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: %{
content: ^expected_content,
source: %{
"content" => "@akkoma_user linkifylink #dancedance $[jelly mfm goes here] \n\n## aaa",
"mediaType" => "text/x.misskeymarkdown"
}
}
} = ArticleNotePageValidator.cast_and_validate(note)
end
end
end