From 73df2f8e5e2d0e2b125df8848c2dd7f2a73f1c03 Mon Sep 17 00:00:00 2001 From: Roger Braun Date: Thu, 30 Mar 2017 17:07:03 +0200 Subject: [PATCH] Add attachments to the TwAPI. --- .../representers/activity_representer.ex | 5 ++-- .../representers/object_representer.ex | 7 ++++- lib/pleroma/web/twitter_api/twitter_api.ex | 9 +++++-- .../web/twitter_api/twitter_api_controller.ex | 13 +++++++++- .../activity_representer_test.exs | 26 ++++++++++++++++--- .../representers/object_representer_test.exs | 5 ++-- test/web/twitter_api/twitter_api_test.exs | 21 +++++++++++++-- 7 files changed, 73 insertions(+), 13 deletions(-) diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex index 05d130639..bcb819200 100644 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex @@ -1,6 +1,6 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter - alias Pleroma.Web.TwitterAPI.Representers.UserRepresenter + alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ObjectRepresenter} alias Pleroma.Activity def to_map(%Activity{} = activity, %{user: user} = opts) do @@ -16,7 +16,8 @@ def to_map(%Activity{} = activity, %{user: user} = opts) do "is_post_verb" => true, "created_at" => published, "in_reply_to_status_id" => activity.data["object"]["inReplyToStatusId"], - "statusnet_conversation_id" => activity.data["object"]["statusnetConversationId"] + "statusnet_conversation_id" => activity.data["object"]["statusnetConversationId"], + "attachments" => (activity.data["attachment"] || []) |> ObjectRepresenter.enum_to_list(opts) } end end diff --git a/lib/pleroma/web/twitter_api/representers/object_representer.ex b/lib/pleroma/web/twitter_api/representers/object_representer.ex index 57ab24caa..c39b60760 100644 --- a/lib/pleroma/web/twitter_api/representers/object_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/object_representer.ex @@ -8,8 +8,13 @@ def to_map(%Object{} = object, _opts) do %{ url: url["href"], mimetype: url["mediaType"], - id: object.id, + id: data["uuid"], oembed: false } end + + # If we only get the naked data, wrap in an object + def to_map(%{} = data, opts) do + to_map(%Object{data: data}, opts) + end end diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index 0624e73aa..ab2b1aab7 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -1,5 +1,5 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do - alias Pleroma.{User, Activity, Repo} + alias Pleroma.{User, Activity, Repo, Object} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter @@ -8,6 +8,10 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do def create_status(user = %User{}, data = %{}) do date = DateTime.utc_now() |> DateTime.to_iso8601 + attachments = Enum.map(data["media_ids"] || [], fn (media_id) -> + Repo.get(Object, media_id).data + end) + context = ActivityPub.generate_context_id activity = %{ "type" => "Create", @@ -23,7 +27,8 @@ def create_status(user = %User{}, data = %{}) do "context" => context }, "published" => date, - "context" => context + "context" => context, + "attachment" => attachments } # Wire up reply info. diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index a26885bf1..2154f34f7 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -11,11 +11,22 @@ def verify_credentials(%{assigns: %{user: user}} = conn, _params) do end def status_update(%{assigns: %{user: user}} = conn, status_data) do - {:ok, activity} = TwitterAPI.create_status(user, status_data) + media_ids = extract_media_ids(status_data) + {:ok, activity} = TwitterAPI.create_status(user, %{ "status" => status_data["status"], "media_ids" => media_ids }) conn |> json_reply(200, ActivityRepresenter.to_json(activity, %{user: user})) end + defp extract_media_ids(status_data) do + with media_ids when not is_nil(media_ids) <- status_data["media_ids"], + split_ids <- String.split(media_ids, ","), + clean_ids <- Enum.reject(split_ids, fn (id) -> String.length(id) == 0 end) + do + clean_ids + else _e -> [] + end + end + def public_timeline(%{assigns: %{user: user}} = conn, params) do statuses = TwitterAPI.fetch_public_statuses(user, params) {:ok, json} = Poison.encode(statuses) diff --git a/test/web/twitter_api/representers/activity_representer_test.exs b/test/web/twitter_api/representers/activity_representer_test.exs index 376d31575..96e6dc98e 100644 --- a/test/web/twitter_api/representers/activity_representer_test.exs +++ b/test/web/twitter_api/representers/activity_representer_test.exs @@ -1,13 +1,27 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do use Pleroma.DataCase - alias Pleroma.{User, Activity} - alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ActivityRepresenter} + alias Pleroma.{User, Activity, Object} + alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ActivityRepresenter, ObjectRepresenter} alias Pleroma.Builders.UserBuilder test "an activity" do {:ok, user} = UserBuilder.insert {:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]}) + object = %Object{ + data: %{ + "type" => "Image", + "url" => [ + %{ + "type" => "Link", + "mediaType" => "image/jpg", + "href" => "http://example.org/image.jpg" + } + ], + "uuid" => 1 + } + } + content = "Some content" date = DateTime.utc_now() |> DateTime.to_iso8601 @@ -19,6 +33,9 @@ test "an activity" do User.ap_followers(user), "https://www.w3.org/ns/activitystreams#Public" ], + "attachment" => [ + object + ], "actor" => User.ap_id(user), "object" => %{ "published" => date, @@ -42,7 +59,10 @@ test "an activity" do "is_post_verb" => true, "created_at" => date, "in_reply_to_status_id" => 213123, - "statusnet_conversation_id" => 4711 + "statusnet_conversation_id" => 4711, + "attachments" => [ + ObjectRepresenter.to_map(object) + ] } assert ActivityRepresenter.to_map(activity, %{user: user, for: follower}) == expected_status diff --git a/test/web/twitter_api/representers/object_representer_test.exs b/test/web/twitter_api/representers/object_representer_test.exs index fc6e0aff9..791b30237 100644 --- a/test/web/twitter_api/representers/object_representer_test.exs +++ b/test/web/twitter_api/representers/object_representer_test.exs @@ -14,12 +14,13 @@ test "represent an image attachment" do "mediaType" => "sometype", "href" => "someurl" } - ] + ], + "uuid" => 6 } } expected_object = %{ - id: 5, + id: 6, url: "someurl", mimetype: "sometype", oembed: false diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs index dcffab2b8..97657eae0 100644 --- a/test/web/twitter_api/twitter_api_test.exs +++ b/test/web/twitter_api/twitter_api_test.exs @@ -2,13 +2,28 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do use Pleroma.DataCase alias Pleroma.Builders.{UserBuilder, ActivityBuilder} alias Pleroma.Web.TwitterAPI.TwitterAPI - alias Pleroma.{Activity, User} + alias Pleroma.{Activity, User, Object, Repo} alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter test "create a status" do user = UserBuilder.build + object_data = %{ + "type" => "Image", + "url" => [ + %{ + "type" => "Link", + "mediaType" => "image/jpg", + "href" => "http://example.org/image.jpg" + } + ], + "uuid" => 1 + } + + object = Repo.insert!(%Object{data: object_data}) + input = %{ - "status" => "Hello again." + "status" => "Hello again.", + "media_ids" => [object.id] } { :ok, activity = %Activity{} } = TwitterAPI.create_status(user, input) @@ -24,6 +39,8 @@ test "create a status" do assert is_binary(get_in(activity.data, ["object", "context"])) assert get_in(activity.data, ["object", "statusnetConversationId"]) == activity.id assert get_in(activity.data, ["statusnetConversationId"]) == activity.id + + assert is_list(activity.data["attachment"]) end test "create a status that is a reply" do