From 8902942128e3aee814c215d700e2eaee21b491e9 Mon Sep 17 00:00:00 2001 From: raeno Date: Mon, 10 Dec 2018 23:08:02 +0400 Subject: [PATCH] WIP. Implement oembed route and handle both json/xml for "Note" type activity --- lib/pleroma/formatter.ex | 16 ++++++++++++ .../web/oembed/activity_representer.ex | 25 ++++++++++++++++++ lib/pleroma/web/oembed/oembed.ex | 23 ++++++++++++++++ lib/pleroma/web/oembed/oembed_controller.ex | 26 ++++++++++++++++--- lib/pleroma/web/oembed/views/note_view.ex | 21 +++++++++++++++ lib/pleroma/web/ostatus/ostatus.ex | 2 +- lib/pleroma/web/ostatus/ostatus_controller.ex | 1 - .../web/templates/o_embed/note.xml.eex | 10 +++++++ test/web/oembed/oembed_test.exs | 23 ++++++++++++++++ 9 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 lib/pleroma/web/oembed/activity_representer.ex create mode 100644 lib/pleroma/web/oembed/oembed.ex create mode 100644 lib/pleroma/web/oembed/views/note_view.ex create mode 100644 lib/pleroma/web/templates/o_embed/note.xml.eex create mode 100644 test/web/oembed/oembed_test.exs diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index 133683794..b63f592fb 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -163,4 +163,20 @@ def finalize({subs, text}) do String.replace(result_text, uuid, replacement) end) end + + def truncate(text, opts \\ []) do + max_length = opts[:max_length] || 200 + omission = opts[:omission] || "..." + + cond do + not String.valid?(text) -> + text + String.length(text) < max_length -> + text + true -> + length_with_omission = max_length - String.length(omission) + + "#{String.slice(text, 0, length_with_omission)}#{omission}" + end + end end diff --git a/lib/pleroma/web/oembed/activity_representer.ex b/lib/pleroma/web/oembed/activity_representer.ex new file mode 100644 index 000000000..0e65090ee --- /dev/null +++ b/lib/pleroma/web/oembed/activity_representer.ex @@ -0,0 +1,25 @@ +defmodule Pleroma.Web.OEmbed.ActivityRepresenter do + alias Pleroma.{Activity, User, Object} + alias Pleroma.Web.OStatus.UserRepresenter + + def to_simple_form(%{data: %{"object" => %{"type" => "Note"}}} = activity, user, with_author) do + h = fn str -> [to_charlist(str)] end + + content = if activity.data["object"]["content"] do + [{:content, [], h.(activity.data["object"]["content"])}] + else + [] + end + + [ + {:version, ["1.0"]}, + {:type, ["link"]}, + ] ++ content + + end + + def wrap_with_entry(simple_form) do + [ { :oembed, [], simple_form } ] + end + +end diff --git a/lib/pleroma/web/oembed/oembed.ex b/lib/pleroma/web/oembed/oembed.ex new file mode 100644 index 000000000..a52aa6004 --- /dev/null +++ b/lib/pleroma/web/oembed/oembed.ex @@ -0,0 +1,23 @@ +defmodule Pleroma.Web.OEmbed do + alias Pleroma.{Repo, Object, Activity, User} + alias Pleroma.Formatter + + def recognize_path(url) do + details = Regex.named_captures(~r/.+\/(?.+)\/(?\w+).*$/, url) + + case details do + %{ "route" => "notice", "id" => id } -> + %{type: :activity, entity: Repo.get(Activity, id) } + %{ "route" => "users", "id" => nickname } -> + %{type: :user, entity: User.get_by_nickname(nickname) } + _ -> + { :error, "no matching route"} + end + end + + def truncated_content(activity) do + content = activity.data['object']['content'] + IO.puts(content) + Formatter.truncate(content) + end +end diff --git a/lib/pleroma/web/oembed/oembed_controller.ex b/lib/pleroma/web/oembed/oembed_controller.ex index e9030049e..d63d3c58c 100644 --- a/lib/pleroma/web/oembed/oembed_controller.ex +++ b/lib/pleroma/web/oembed/oembed_controller.ex @@ -1,11 +1,31 @@ defmodule Pleroma.Web.OEmbed.OEmbedController do use Pleroma.Web, :controller + alias Pleroma.Web.OEmbed + alias Pleroma.Web.OEmbed.{NoteView, ActivityRepresenter} + alias Pleroma.Web.MediaProxy alias Pleroma.Repo + alias Pleroma.User - def url(conn, %{ "url" => uri} ) do + def url(conn, %{ "url" => url} ) do + case format = get_format(conn) do + _ -> + result = OEmbed.recognize_path(url) + render_oembed(conn, format, result) + end + end + + def render_oembed(conn, format \\ "json", result) + def render_oembed(conn, "json", result) do conn |> put_resp_content_type("application/json") - |> json(%{ status: "success"} ) + |> json(NoteView.render("note.json", result)) end -end \ No newline at end of file + + def render_oembed(conn, "xml", result) do + conn + |> put_resp_content_type("application/xml") + |> NoteView.render("note.json", result) + + end +end diff --git a/lib/pleroma/web/oembed/views/note_view.ex b/lib/pleroma/web/oembed/views/note_view.ex new file mode 100644 index 000000000..ecdabc04b --- /dev/null +++ b/lib/pleroma/web/oembed/views/note_view.ex @@ -0,0 +1,21 @@ +defmodule Pleroma.Web.OEmbed.NoteView do + use Pleroma.Web, :view + alias Pleroma.{User, Activity} + alias Pleroma.Web.OEmbed + + def render("note.json", %{type: type, entity: activity }) do + oembed_data(activity) + end + + def oembed_data(activity) do + with %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]), + image = User.avatar_url(user) |> MediaProxy.url() do + %{ + version: "1.0", + type: "link", + title: OEmbed.truncated_content(activity), + provider_url: "https://pleroma.site", + thumbnail_url: image, + } + end +end diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index 8ec92d5f1..0f6756d16 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -31,7 +31,7 @@ def metadata(url), do: oembed_links(url) def oembed_links(url) do Enum.map(["xml", "json"], fn format -> href = oembed_path(url, format) - "" end) |> Enum.join("\r\n") end diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 635189619..27ec24f57 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -9,7 +9,6 @@ defmodule Pleroma.Web.OStatus.OStatusController do alias Pleroma.Web.ActivityPub.ObjectView alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Router.Helpers, as: Routes plug(Pleroma.Web.FederatingPlug when action in [:salmon_incoming]) action_fallback(:errors) diff --git a/lib/pleroma/web/templates/o_embed/note.xml.eex b/lib/pleroma/web/templates/o_embed/note.xml.eex new file mode 100644 index 000000000..e814a4cb3 --- /dev/null +++ b/lib/pleroma/web/templates/o_embed/note.xml.eex @@ -0,0 +1,10 @@ + + + 1.0 + link + raeno + http://iamcal.com/ + 86400 + iamcal.com + http://iamcal.com/ + \ No newline at end of file diff --git a/test/web/oembed/oembed_test.exs b/test/web/oembed/oembed_test.exs new file mode 100644 index 000000000..16c2c3598 --- /dev/null +++ b/test/web/oembed/oembed_test.exs @@ -0,0 +1,23 @@ +defmodule Pleroma.Web.OEmbedTest do + use Pleroma.DataCase + alias Pleroma.Web.OEmbed + alias Pleroma.Web.XML + alias Pleroma.{Object, Repo, User, Activity} + import Pleroma.Factory + import ExUnit.CaptureLog + + setup_all do + :ok + end + + test 'recognizes notices in given url' do + url = "https://pleroma.site/notice/5" + assert { :activity, _ } = OEmbed.recognize_path(url) + end + + test 'recognizes user card in given url' do + url = "https://pleroma.site/users/raeno" + assert { :user, _ } = OEmbed.recognize_path(url) + end + +end