Merge branch 'feature/twitterapi-unrepeat' into 'develop'

Add TwitterAPI unretweet endpoint and cleanup AP.unannounce

See merge request pleroma/pleroma!218
This commit is contained in:
lambda 2018-06-14 07:19:36 +00:00
commit 8c7fdcb31b
9 changed files with 63 additions and 16 deletions

View file

@ -199,7 +199,7 @@ def unannounce(
:ok <- maybe_federate(unannounce_activity), :ok <- maybe_federate(unannounce_activity),
{:ok, _activity} <- Repo.delete(announce_activity), {:ok, _activity} <- Repo.delete(announce_activity),
{:ok, object} <- remove_announce_from_object(announce_activity, object) do {:ok, object} <- remove_announce_from_object(announce_activity, object) do
{:ok, unannounce_activity, announce_activity, object} {:ok, unannounce_activity, object}
else else
_e -> {:ok, object} _e -> {:ok, object}
end end

View file

@ -312,7 +312,7 @@ def handle_incoming(
with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <- {:ok, object} <-
get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
{:ok, activity, _, _} <- ActivityPub.unannounce(actor, object, id, false) do {:ok, activity, _} <- ActivityPub.unannounce(actor, object, id, false) do
{:ok, activity} {:ok, activity}
else else
_e -> :error _e -> :error

View file

@ -360,7 +360,7 @@ def reblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
end end
def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
with {:ok, _, _, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user), with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user),
%Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do
render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity})
end end

View file

@ -244,6 +244,7 @@ def user_fetcher(username) do
post("/statuses/update", TwitterAPI.Controller, :status_update) post("/statuses/update", TwitterAPI.Controller, :status_update)
post("/statuses/retweet/:id", TwitterAPI.Controller, :retweet) post("/statuses/retweet/:id", TwitterAPI.Controller, :retweet)
post("/statuses/unretweet/:id", TwitterAPI.Controller, :unretweet)
post("/statuses/destroy/:id", TwitterAPI.Controller, :delete_post) post("/statuses/destroy/:id", TwitterAPI.Controller, :delete_post)
get("/pleroma/friend_requests", TwitterAPI.Controller, :friend_requests) get("/pleroma/friend_requests", TwitterAPI.Controller, :friend_requests)

View file

@ -12,14 +12,9 @@ def create_status(%User{} = user, %{"status" => _} = data) do
end end
def delete(%User{} = user, id) do def delete(%User{} = user, id) do
# TwitterAPI does not have an "unretweet" endpoint; instead this is done with %Activity{data: %{"type" => type}} <- Repo.get(Activity, id),
# via the "destroy" endpoint. Therefore, we need to handle {:ok, activity} <- CommonAPI.delete(id, user) do
# when the status to "delete" is actually an Announce (repeat) object. {:ok, activity}
with %Activity{data: %{"type" => type}} <- Repo.get(Activity, id) do
case type do
"Announce" -> unrepeat(user, id)
_ -> CommonAPI.delete(id, user)
end
end end
end end
@ -70,8 +65,9 @@ def repeat(%User{} = user, ap_id_or_id) do
end end
end end
defp unrepeat(%User{} = user, ap_id_or_id) do def unrepeat(%User{} = user, ap_id_or_id) do
with {:ok, _unannounce, activity, _object} <- CommonAPI.unrepeat(ap_id_or_id, user) do with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user),
%Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do
{:ok, activity} {:ok, activity}
end end
end end

View file

@ -241,6 +241,13 @@ def retweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do
end end
end end
def unretweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do
with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)},
{:ok, activity} <- TwitterAPI.unrepeat(user, id) do
render(conn, ActivityView, "activity.json", %{activity: activity, for: user})
end
end
def register(conn, params) do def register(conn, params) do
with {:ok, user} <- TwitterAPI.register_user(params) do with {:ok, user} <- TwitterAPI.register_user(params) do
render(conn, UserView, "show.json", %{user: user}) render(conn, UserView, "show.json", %{user: user})

View file

@ -318,11 +318,9 @@ test "unannouncing a previously announced object" do
{:ok, announce_activity, object} = ActivityPub.announce(user, object) {:ok, announce_activity, object} = ActivityPub.announce(user, object)
assert object.data["announcement_count"] == 1 assert object.data["announcement_count"] == 1
{:ok, unannounce_activity, activity, object} = ActivityPub.unannounce(user, object) {:ok, unannounce_activity, object} = ActivityPub.unannounce(user, object)
assert object.data["announcement_count"] == 0 assert object.data["announcement_count"] == 0
assert activity == announce_activity
assert unannounce_activity.data["to"] == [ assert unannounce_activity.data["to"] == [
User.ap_followers(user), User.ap_followers(user),
announce_activity.data["actor"] announce_activity.data["actor"]

View file

@ -580,6 +580,40 @@ test "with credentials", %{conn: conn, user: current_user} do
end end
end end
describe "POST /api/statuses/unretweet/:id" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
note_activity = insert(:note_activity)
conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
note_activity = insert(:note_activity)
request_path = "/api/statuses/retweet/#{note_activity.id}.json"
_response =
conn
|> with_credentials(current_user.nickname, "test")
|> post(request_path)
request_path = String.replace(request_path, "retweet", "unretweet")
response =
conn
|> with_credentials(current_user.nickname, "test")
|> post(request_path)
activity = Repo.get(Activity, note_activity.id)
activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
assert json_response(response, 200) ==
ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
end
end
describe "POST /api/account/register" do describe "POST /api/account/register" do
test "it creates a new user", %{conn: conn} do test "it creates a new user", %{conn: conn} do
data = %{ data = %{

View file

@ -228,6 +228,17 @@ test "it retweets a status and returns the retweet" do
assert status == updated_activity assert status == updated_activity
end end
test "it unretweets an already retweeted status" do
user = insert(:user)
note_activity = insert(:note_activity)
{:ok, _status} = TwitterAPI.repeat(user, note_activity.id)
{:ok, status} = TwitterAPI.unrepeat(user, note_activity.id)
updated_activity = Activity.get_by_ap_id(note_activity.data["id"])
assert status == updated_activity
end
test "it registers a new user and returns the user." do test "it registers a new user and returns the user." do
data = %{ data = %{
"nickname" => "lain", "nickname" => "lain",