Add announcements / retweets to TwAPI.
authorRoger Braun <roger@rogerbraun.net>
Sat, 15 Apr 2017 11:54:46 +0000 (13:54 +0200)
committerRoger Braun <roger@rogerbraun.net>
Sat, 15 Apr 2017 11:54:46 +0000 (13:54 +0200)
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/twitter_api/representers/activity_representer.ex
lib/pleroma/web/twitter_api/twitter_api.ex
test/web/twitter_api/representers/activity_representer_test.exs
test/web/twitter_api/twitter_api_test.exs

index a38f63b0312db40c7c39df07ed75d85fa49972e0..b2508de68a7092b6e6a680f8ac2252d7a30094ae 100644 (file)
@@ -63,7 +63,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end)
   end
 
-  def unlike(%User{ap_id: ap_id} = user, %Object{data: %{ "id" => id}} = object) do
+  def unlike(%User{ap_id: ap_id}, %Object{data: %{ "id" => id}} = object) do
     query = from activity in Activity,
       where: fragment("? @> ?", activity.data, ^%{actor: ap_id, object: id, type: "Like"})
 
index e69a63e1de8b4d55a2f097aaa9fbe6f5f9d2e49f..f2bf93abb26c5ba84879bc653aa36144dd6a7b1d 100644 (file)
@@ -4,6 +4,32 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
   alias Pleroma.Activity
 
 
+  defp user_by_ap_id(user_list, ap_id) do
+    Enum.find(user_list, fn (%{ap_id: user_id}) -> ap_id == user_id end)
+  end
+
+  def to_map(%Activity{data: %{"type" => "Announce", "actor" => actor}} = activity, %{users: users, announced_activity: announced_activity} = opts) do
+    user = user_by_ap_id(users, actor)
+    created_at = get_in(activity.data, ["published"])
+    |> date_to_asctime
+
+    text = "#{user.nickname} retweeted a status."
+
+    announced_user = user_by_ap_id(users, announced_activity.data["actor"])
+    retweeted_status = to_map(announced_activity, Map.merge(%{user: announced_user}, opts))
+    %{
+      "id" => activity.id,
+      "user" => UserRepresenter.to_map(user, opts),
+      "statusnet_html" => text,
+      "text" => text,
+      "is_local" => true,
+      "is_post_verb" => false,
+      "uri" => "tag:#{activity.data["id"]}:objectType=note",
+      "created_at" => created_at,
+      "retweeted_status" => retweeted_status
+    }
+  end
+
   def to_map(%Activity{data: %{"type" => "Like"}} = activity, %{user: user, liked_activity: liked_activity} = opts) do
     created_at = get_in(activity.data, ["published"])
     |> date_to_asctime
@@ -45,7 +71,9 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
     created_at = get_in(activity.data, ["object", "published"])
     |> date_to_asctime
     like_count = get_in(activity.data, ["object", "like_count"]) || 0
+    announcement_count = get_in(activity.data, ["object", "announcement_count"]) || 0
     favorited = opts[:for] && opts[:for].ap_id in (activity.data["object"]["likes"] || [])
+    repeated = opts[:for] && opts[:for].ap_id in (activity.data["object"]["announcements"] || [])
 
     mentions = opts[:mentioned] || []
 
@@ -68,7 +96,9 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
       "attachments" => (activity.data["object"]["attachment"] || []) |> ObjectRepresenter.enum_to_list(opts),
       "attentions" => attentions,
       "fave_num" => like_count,
-      "favorited" => !!favorited
+      "repeat_num" => announcement_count,
+      "favorited" => !!favorited,
+      "repeated" => !!repeated,
     }
   end
 
index 76dbc77a1a4bff2b92b289a06e3c525d94a8ead5..58f8bc1d3b7a14a715c9d67fc16535f85d7f350c 100644 (file)
@@ -150,6 +150,19 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
     {:ok, status}
   end
 
+  def retweet(%User{} = user, %Activity{data: %{"object" => object}} = activity) do
+    object = Object.get_by_ap_id(object["id"])
+
+    {:ok, _announce_activity, object} = ActivityPub.announce(user, object)
+    new_data = activity.data
+    |> Map.put("object", object.data)
+
+    status = %{activity | data: new_data}
+    |> activity_to_status(%{for: user})
+
+    {:ok, status}
+  end
+
   def upload(%Plug.Upload{} = file, format \\ "xml") do
     {:ok, object} = ActivityPub.upload(file)
 
@@ -229,6 +242,16 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
     ActivityRepresenter.to_map(activity, Map.merge(opts, %{user: user, liked_activity: liked_activity}))
   end
 
+  # For announces, fetch the announced activity and the user.
+  defp activity_to_status(%Activity{data: %{"type" => "Announce"}} = activity, opts) do
+    actor = get_in(activity.data, ["actor"])
+    user = User.get_cached_by_ap_id(actor)
+    [announced_activity] = Activity.all_by_object_ap_id(activity.data["object"])
+    announced_actor = User.get_cached_by_ap_id(announced_activity.data["actor"])
+
+    ActivityRepresenter.to_map(activity, Map.merge(opts, %{users: [user, announced_actor], announced_activity: announced_activity}))
+  end
+
   defp activity_to_status(activity, opts) do
     actor = get_in(activity.data, ["actor"])
     user = User.get_cached_by_ap_id(actor)
index d1f9e00c8c7b2cf8d1ed8497c6d34728b5764e2e..a9129bcccd1bb1ae30fd3290e7d20639109ce91a 100644 (file)
@@ -6,6 +6,26 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do
   alias Pleroma.Builders.UserBuilder
   import Pleroma.Factory
 
+  test "an announce activity" do
+    user = insert(:user)
+    note_activity = insert(:note_activity)
+    activity_actor = Repo.get_by(User, ap_id: note_activity.data["actor"])
+    object = Object.get_by_ap_id(note_activity.data["object"]["id"])
+
+    {:ok, announce_activity, _object} = ActivityPub.announce(user, object)
+    note_activity = Activity.get_by_ap_id(note_activity.data["id"])
+
+    status = ActivityRepresenter.to_map(announce_activity, %{users: [user, activity_actor], announced_activity: note_activity, for: user})
+
+    assert status["id"] == announce_activity.id
+    assert status["user"] == UserRepresenter.to_map(user, %{for: user})
+
+    retweeted_status = ActivityRepresenter.to_map(note_activity, %{user: activity_actor, for: user})
+    assert retweeted_status["repeated"] == true
+
+    assert status["retweeted_status"] == retweeted_status
+  end
+
   test "a like activity" do
     user = insert(:user)
     note_activity = insert(:note_activity)
@@ -65,7 +85,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do
           "attachment" => [
             object
           ],
-          "like_count" => 5
+          "like_count" => 5,
+          "announcement_count" => 3
         },
         "published" => date
       }
@@ -90,7 +111,9 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do
         UserRepresenter.to_map(mentioned_user, %{for: follower})
       ],
       "fave_num" => 5,
-      "favorited" => false
+      "repeat_num" => 3,
+      "favorited" => false,
+      "repeated" => false
     }
 
     assert ActivityRepresenter.to_map(activity, %{user: user, for: follower, mentioned: [mentioned_user]}) == expected_status
index fd9908b9fd984fb7b4fd1cf09bba36678a8b0061..71b0d8b129a8f0c4c815f7f2e186dc1742420125 100644 (file)
@@ -209,6 +209,17 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
     assert status["fave_num"] == 0
   end
 
+  test "it retweets a status and returns the retweet" do
+    user = insert(:user)
+    note_activity = insert(:note_activity)
+    activity_user = Repo.get_by!(User, ap_id: note_activity.data["actor"])
+
+    {:ok, status} = TwitterAPI.retweet(user, note_activity)
+    updated_activity = Activity.get_by_ap_id(note_activity.data["id"])
+
+    assert status == ActivityRepresenter.to_map(updated_activity, %{user: activity_user, for: user})
+  end
+
   setup do
     Supervisor.terminate_child(Pleroma.Supervisor, ConCache)
     Supervisor.restart_child(Pleroma.Supervisor, ConCache)