Twitter API refactoring.
authorRoger Braun <roger@rogerbraun.net>
Wed, 17 May 2017 16:00:20 +0000 (18:00 +0200)
committerRoger Braun <roger@rogerbraun.net>
Wed, 17 May 2017 16:00:20 +0000 (18:00 +0200)
lib/pleroma/web/twitter_api/twitter_api.ex
lib/pleroma/web/twitter_api/utils.ex [new file with mode: 0644]
test/web/twitter_api/twitter_api_test.exs

index 0b1bc473a7f1bdaa0a2e195b9c55d84e5fe3736f..202d648e115a452b4d04736facc58c6661b062ad 100644 (file)
@@ -4,28 +4,23 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
   alias Pleroma.Web.ActivityPub.Utils
   alias Pleroma.Web.TwitterAPI.Representers.{ActivityRepresenter, UserRepresenter}
   alias Pleroma.Web.OStatus
+  alias Pleroma.Formatter
 
   import Ecto.Query
+  import Pleroma.Web.TwitterAPI.Utils
 
-  def to_for_user_and_mentions(user, mentions) do
+  def to_for_user_and_mentions(user, mentions, inReplyTo) do
     default_to = [
       User.ap_followers(user),
       "https://www.w3.org/ns/activitystreams#Public"
     ]
 
-    default_to ++ Enum.map(mentions, fn ({_, %{ap_id: ap_id}}) -> ap_id end)
-  end
-
-  def format_input(text, mentions) do
-    HtmlSanitizeEx.strip_tags(text)
-    |> String.replace("\n", "<br>")
-    |> add_user_links(mentions)
-  end
-
-  def attachments_from_ids(ids) do
-    Enum.map(ids || [], fn (media_id) ->
-      Repo.get(Object, media_id).data
-    end)
+    to = default_to ++ Enum.map(mentions, fn ({_, %{ap_id: ap_id}}) -> ap_id end)
+    if inReplyTo do
+      Enum.uniq([inReplyTo.data["actor"] | to])
+    else
+      to
+    end
   end
 
   def get_replied_to_activity(id) when not is_nil(id) do
@@ -34,62 +29,16 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
 
   def get_replied_to_activity(_), do: nil
 
-  def add_attachments(text, attachments) do
-    attachment_text = Enum.map(attachments, fn
-      (%{"url" => [%{"href" => href} | _]}) ->
-        "<a href='#{href}' class='attachment'>#{href}</a>"
-      _ -> ""
-    end)
-    Enum.join([text | attachment_text], "<br>")
-    end
-
   def create_status(%User{} = user, %{"status" => status} = data) do
-    attachments = attachments_from_ids(data["media_ids"])
-    context = Utils.generate_context_id
-    mentions = parse_mentions(status)
-    content_html = status
-    |> format_input(mentions)
-    |> add_attachments(attachments)
-
-    to = to_for_user_and_mentions(user, mentions)
-    date = make_date()
-
-    inReplyTo = get_replied_to_activity(data["in_reply_to_status_id"])
-
-    # Wire up reply info.
-    [to, context, object, additional] =
-      if inReplyTo do
-      context = inReplyTo.data["context"]
-      to = to ++ [inReplyTo.data["actor"]]
-
-      object = %{
-        "type" => "Note",
-        "to" => to,
-        "content" => content_html,
-        "published" => date,
-        "context" => context,
-        "attachment" => attachments,
-        "actor" => user.ap_id,
-        "inReplyTo" => inReplyTo.data["object"]["id"],
-        "inReplyToStatusId" => inReplyTo.id,
-      }
-      additional = %{}
-
-      [to, context, object, additional]
-      else
-      object = %{
-        "type" => "Note",
-        "to" => to,
-        "content" => content_html,
-        "published" => date,
-        "context" => context,
-        "attachment" => attachments,
-        "actor" => user.ap_id
-      }
-      [to, context, object, %{}]
+    with attachments <- attachments_from_ids(data["media_ids"]),
+         mentions <- parse_mentions(status),
+         inReplyTo <- get_replied_to_activity(data["in_reply_to_status_id"]),
+         to <- to_for_user_and_mentions(user, mentions, inReplyTo),
+         content_html <- make_content_html(status, mentions, attachments),
+         context <- make_context(inReplyTo),
+         object <- make_note_data(user.ap_id, to, context, content_html, attachments, inReplyTo) do
+      ActivityPub.create(to, user, context, object)
     end
-
-    ActivityPub.create(to, user, context, object, additional, data)
   end
 
   def fetch_friend_statuses(user, opts \\ %{}) do
@@ -243,24 +192,6 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
     |> Enum.filter(fn ({_match, user}) -> user end)
   end
 
-  def add_user_links(text, mentions) do
-    mentions = mentions
-    |> Enum.sort_by(fn ({name, _}) -> -String.length(name) end)
-    |> Enum.map(fn({name, user}) -> {name, user, Ecto.UUID.generate} end)
-
-    # This replaces the mention with a unique reference first so it doesn't
-    # contain parts of other replaced mentions. There probably is a better
-    # solution for this...
-    step_one = mentions
-    |> Enum.reduce(text, fn ({match, _user, uuid}, text) ->
-      String.replace(text, match, uuid)
-    end)
-
-    Enum.reduce(mentions, step_one, fn ({match, %User{ap_id: ap_id}, uuid}, text) ->
-      String.replace(text, uuid, "<a href='#{ap_id}'>#{match}</a>")
-    end)
-  end
-
   def register_user(params) do
     params = %{
       nickname: params["nickname"],
diff --git a/lib/pleroma/web/twitter_api/utils.ex b/lib/pleroma/web/twitter_api/utils.ex
new file mode 100644 (file)
index 0000000..6f5c9f7
--- /dev/null
@@ -0,0 +1,72 @@
+defmodule Pleroma.Web.TwitterAPI.Utils do
+  alias Pleroma.{Repo, Object, Formatter, User, Activity}
+  alias Pleroma.Web.ActivityPub.Utils
+
+  def attachments_from_ids(ids) do
+    Enum.map(ids || [], fn (media_id) ->
+      Repo.get(Object, media_id).data
+    end)
+  end
+
+  def add_attachments(text, attachments) do
+    attachment_text = Enum.map(attachments, fn
+      (%{"url" => [%{"href" => href} | _]}) ->
+        "<a href='#{href}' class='attachment'>#{href}</a>"
+      _ -> ""
+    end)
+    Enum.join([text | attachment_text], "<br>")
+  end
+
+  def format_input(text, mentions) do
+    HtmlSanitizeEx.strip_tags(text)
+    |> Formatter.linkify
+    |> String.replace("\n", "<br>")
+    |> add_user_links(mentions)
+  end
+
+  def add_user_links(text, mentions) do
+    mentions = mentions
+    |> Enum.sort_by(fn ({name, _}) -> -String.length(name) end)
+    |> Enum.map(fn({name, user}) -> {name, user, Ecto.UUID.generate} end)
+
+    # This replaces the mention with a unique reference first so it doesn't
+    # contain parts of other replaced mentions. There probably is a better
+    # solution for this...
+    step_one = mentions
+    |> Enum.reduce(text, fn ({match, _user, uuid}, text) ->
+      String.replace(text, match, uuid)
+    end)
+
+    Enum.reduce(mentions, step_one, fn ({match, %User{ap_id: ap_id}, uuid}, text) ->
+      String.replace(text, uuid, "<a href='#{ap_id}'>#{match}</a>")
+    end)
+  end
+
+  def make_content_html(status, mentions, attachments) do
+    status
+    |> format_input(mentions)
+    |> add_attachments(attachments)
+  end
+
+  def make_context(%Activity{data: %{"context" => context}}), do: context
+  def make_context(_), do: Utils.generate_context_id
+
+  def make_note_data(actor, to, context, content_html, attachments, inReplyTo) do
+      object = %{
+        "type" => "Note",
+        "to" => to,
+        "content" => content_html,
+        "context" => context,
+        "attachment" => attachments,
+        "actor" => actor
+      }
+
+    if inReplyTo do
+      object
+      |> Map.put("inReplyTo", inReplyTo.data["object"]["id"])
+      |> Map.put("inReplyToStatusId", inReplyTo.id)
+    else
+      object
+    end
+  end
+end
index d70ef88f34f2a095fc972312e86d672de322a07b..e209602287763896a1e725896109ac3603bfa886 100644 (file)
@@ -2,6 +2,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
   use Pleroma.DataCase
   alias Pleroma.Builders.{UserBuilder, ActivityBuilder}
   alias Pleroma.Web.TwitterAPI.TwitterAPI
+  alias Pleroma.Web.TwitterAPI.Utils
   alias Pleroma.{Activity, User, Object, Repo}
   alias Pleroma.Web.TwitterAPI.Representers.{ActivityRepresenter, UserRepresenter}
   alias Pleroma.Web.ActivityPub.ActivityPub
@@ -261,7 +262,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
     mentions = TwitterAPI.parse_mentions(text)
     expected_text = "<a href='#{gsimg.ap_id}'>@gsimg</a> According to <a href='#{archaeme.ap_id}'>@archaeme</a>, that is @daggsy. Also hello <a href='#{archaeme_remote.ap_id}'>@archaeme@archae.me</a>"
 
-    assert TwitterAPI.add_user_links(text, mentions) == expected_text
+    assert Utils.add_user_links(text, mentions) == expected_text
   end
 
   test "it favorites a status, returns the updated status" do