WIP. Implement oembed route and handle both json/xml for "Note" type activity
authorraeno <just.raeno@gmail.com>
Mon, 10 Dec 2018 19:08:02 +0000 (23:08 +0400)
committerraeno <just.raeno@gmail.com>
Thu, 13 Dec 2018 21:17:53 +0000 (22:17 +0100)
lib/pleroma/formatter.ex
lib/pleroma/web/oembed/activity_representer.ex [new file with mode: 0644]
lib/pleroma/web/oembed/oembed.ex [new file with mode: 0644]
lib/pleroma/web/oembed/oembed_controller.ex
lib/pleroma/web/oembed/views/note_view.ex [new file with mode: 0644]
lib/pleroma/web/ostatus/ostatus.ex
lib/pleroma/web/ostatus/ostatus_controller.ex
lib/pleroma/web/templates/o_embed/note.xml.eex [new file with mode: 0644]
test/web/oembed/oembed_test.exs [new file with mode: 0644]

index 1336837944af4c3c80b2e8013dab5cb6870debe0..b63f592fbc9218a84d72b3ea24dc82f0f8121a35 100644 (file)
@@ -163,4 +163,20 @@ defmodule Pleroma.Formatter 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 (file)
index 0000000..0e65090
--- /dev/null
@@ -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 (file)
index 0000000..a52aa60
--- /dev/null
@@ -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/.+\/(?<route>.+)\/(?<id>\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
index e9030049e1c7b47407398a8dd91b376eb5dcf3f4..d63d3c58c72a65ff2e8900315cf582c5c492975a 100644 (file)
@@ -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
+
+  def render_oembed(conn, "xml", result) do
+    conn
+    |> put_resp_content_type("application/xml")
+    |> NoteView.render("note.json", result)
+
   end
-end
\ No newline at end of file
+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 (file)
index 0000000..ecdabc0
--- /dev/null
@@ -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
index 8ec92d5f1699c97105fa0b698c3289c44ec312bf..0f6756d163aa8ccb01f7c0b3a4ce47ef4315cc92 100644 (file)
@@ -31,7 +31,7 @@ defmodule Pleroma.Web.OStatus do
   def oembed_links(url) do
     Enum.map(["xml", "json"], fn format ->
       href = oembed_path(url, format)
-      "<link rel=\"alternate\" type=\"application/#{format}+oembed\" href=\"#{href}\""
+      "<link rel=\"alternate\" type=\"application/#{format}+oembed\" href=\"#{href}\">"
     end)
     |> Enum.join("\r\n")
   end
index 6351896190eae3ed3346e57bca74d45c1c75a4d3..27ec24f576b939cac7ae777a469c0e4c3cacba7f 100644 (file)
@@ -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 (file)
index 0000000..e814a4c
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<oembed>
+    <version>1.0</version>
+    <type>link</type>
+    <author_name>raeno</author_name>
+    <author_url>http://iamcal.com/</author_url>
+    <cache_age>86400</cache_age>
+    <provider_name>iamcal.com</provider_name>
+    <provider_url>http://iamcal.com/</provider_url>
+</oembed>
\ 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 (file)
index 0000000..16c2c35
--- /dev/null
@@ -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