logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma
commit: ace4231628ad1af08c8696fb7fe6983549f62631
parent: 6c6a2dbfdd7ae4043633c3201693c5c49538ef84
Author: kaniini <nenolod@gmail.com>
Date:   Sun,  3 Mar 2019 16:00:49 +0000

Merge branch 'features/bio_rel_me' into 'develop'

Add rel=me to the User bio

Closes #423

See merge request pleroma/pleroma!813

Diffstat:

Mlib/pleroma/user.ex9++++++++-
Alib/pleroma/web/rel_me.ex51+++++++++++++++++++++++++++++++++++++++++++++++++++
Atest/fixtures/rel_me_anchor.html14++++++++++++++
Atest/fixtures/rel_me_link.html14++++++++++++++
Atest/fixtures/rel_me_null.html13+++++++++++++
Mtest/user_test.exs16++++++++++++++++
Atest/web/rel_me_test.exs55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 171 insertions(+), 1 deletion(-)

diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex @@ -22,6 +22,7 @@ defmodule Pleroma.User do alias Pleroma.Web.OAuth alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.RelMe require Logger @@ -1232,8 +1233,14 @@ defmodule Pleroma.User do {String.trim(name, ":"), url} end) + # TODO: get profile URLs other than user.ap_id + profile_urls = [user.ap_id] + bio - |> CommonUtils.format_input("text/plain", mentions_format: :full) + |> CommonUtils.format_input("text/plain", + mentions_format: :full, + rel: &RelMe.maybe_put_rel_me(&1, profile_urls) + ) |> elem(0) |> Formatter.emojify(emoji) end diff --git a/lib/pleroma/web/rel_me.ex b/lib/pleroma/web/rel_me.ex @@ -0,0 +1,51 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.RelMe do + @hackney_options [ + pool: :media, + timeout: 2_000, + recv_timeout: 2_000, + max_body: 2_000_000 + ] + + if Mix.env() == :test do + def parse(url) when is_binary(url), do: parse_url(url) + else + def parse(url) when is_binary(url) do + Cachex.fetch!(:rel_me_cache, url, fn _ -> + {:commit, parse_url(url)} + end) + rescue + e -> {:error, "Cachex error: #{inspect(e)}"} + end + end + + def parse(_), do: {:error, "No URL provided"} + + defp parse_url(url) do + {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options) + + data = + Floki.attribute(html, "link[rel=me]", "href") ++ Floki.attribute(html, "a[rel=me]", "href") + + {:ok, data} + rescue + e -> {:error, "Parsing error: #{inspect(e)}"} + end + + def maybe_put_rel_me("http" <> _ = target_page, profile_urls) when is_list(profile_urls) do + {:ok, rel_me_hrefs} = parse(target_page) + + true = Enum.any?(rel_me_hrefs, fn x -> x in profile_urls end) + + "me" + rescue + _ -> nil + end + + def maybe_put_rel_me(_, _) do + nil + end +end diff --git a/test/fixtures/rel_me_anchor.html b/test/fixtures/rel_me_anchor.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <title>Blog</title> + </head> + <body> + <article> + <h1>Lorem ipsum</h1> + <p>Lorem ipsum dolor sit ameph, …</p> + <a rel="me" href="https://social.example.org/users/lain">lain’s account</a> + </article> + </body> +</html> diff --git a/test/fixtures/rel_me_link.html b/test/fixtures/rel_me_link.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <title>Blog</title> + <link rel="me" href="https://social.example.org/users/lain"/> + </head> + <body> + <article> + <h1>Lorem ipsum</h1> + <p>Lorem ipsum dolor sit ameph, …</p> + </article> + </body> +</html> diff --git a/test/fixtures/rel_me_null.html b/test/fixtures/rel_me_null.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"/> + <title>Blog</title> + </head> + <body> + <article> + <h1>Lorem ipsum</h1> + <p>Lorem ipsum dolor sit ameph, …</p> + </article> + </body> +</html> diff --git a/test/user_test.exs b/test/user_test.exs @@ -1054,6 +1054,22 @@ defmodule Pleroma.UserTest do assert expected_text == User.parse_bio(bio, user) end + + test "Adds rel=me on linkbacked urls" do + user = insert(:user, ap_id: "http://social.example.org/users/lain") + + bio = "http://example.org/rel_me/null" + expected_text = "<a href=\"#{bio}\">#{bio}</a>" + assert expected_text == User.parse_bio(bio, user) + + bio = "http://example.org/rel_me/link" + expected_text = "<a href=\"#{bio}\">#{bio}</a>" + assert expected_text == User.parse_bio(bio, user) + + bio = "http://example.org/rel_me/anchor" + expected_text = "<a href=\"#{bio}\">#{bio}</a>" + assert expected_text == User.parse_bio(bio, user) + end end test "bookmarks" do diff --git a/test/web/rel_me_test.exs b/test/web/rel_me_test.exs @@ -0,0 +1,55 @@ +defmodule Pleroma.Web.RelMeTest do + use ExUnit.Case, async: true + + setup do + Tesla.Mock.mock(fn + %{ + method: :get, + url: "http://example.com/rel_me/anchor" + } -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_anchor.html")} + + %{ + method: :get, + url: "http://example.com/rel_me/link" + } -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_link.html")} + + %{ + method: :get, + url: "http://example.com/rel_me/null" + } -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_null.html")} + end) + + :ok + end + + test "parse/1" do + hrefs = ["https://social.example.org/users/lain"] + + assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/null") == {:ok, []} + assert {:error, _} = Pleroma.Web.RelMe.parse("http://example.com/rel_me/error") + + assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/link") == {:ok, hrefs} + assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/anchor") == {:ok, hrefs} + end + + test "maybe_put_rel_me/2" do + profile_urls = ["https://social.example.org/users/lain"] + attr = "me" + fallback = nil + + assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/null", profile_urls) == + fallback + + assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/error", profile_urls) == + fallback + + assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/anchor", profile_urls) == + attr + + assert Pleroma.Web.RelMe.maybe_put_rel_me("http://example.com/rel_me/link", profile_urls) == + attr + end +end