diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index d58274508..b54613274 100644 --- 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 @@ -1202,8 +1203,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 new file mode 100644 index 000000000..b23c49977 --- /dev/null +++ b/lib/pleroma/web/rel_me.ex @@ -0,0 +1,46 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# 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 + ] + + def parse(nil), do: {:error, "No URL provided"} + + if Mix.env() == :test do + def parse(url), do: parse_url(url) + else + def parse(url) do + Cachex.fetch!(:rel_me_cache, url, fn _ -> + {:commit, parse_url(url)} + end) + rescue + e -> {:error, "Cachex error: #{inspect(e)}"} + end + end + + defp parse_url(url) do + {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options) + + Floki.attribute(html, "link[rel=me]", "href") ++ Floki.attribute(html, "a[rel=me]", "href") + rescue + e -> {:error, "Parsing error: #{inspect(e)}"} + end + + def maybe_put_rel_me("http" <> _ = target_page, urls) when not is_nil(urls) do + if Enum.any?(parse(target_page), fn x -> x in urls end) do + "rel=\"me\" " + else + "" + end + end + + def maybe_put_rel_me(_, _) do + "" + end +end