end
end
- defp do_unfollow(follower, followed, activity_id, local) do
+ defp do_unfollow(follower, followed, activity_id, local)
+
+ defp do_unfollow(follower, followed, activity_id, local) when local == true do
with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed),
{:ok, follow_activity} <- update_follow_state(follow_activity, "cancelled"),
unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
end
end
+ defp do_unfollow(follower, followed, activity_id, false) do
+ # On a remote unfollow, _remove_ their activity from the database, since some software (MISSKEEEEY)
+ # uses deterministic ids for follows.
+ with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed),
+ {:ok, _activity} <- Repo.delete(follow_activity),
+ unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
+ unfollow_activity <- remote_unfollow_data(unfollow_data),
+ _ <- notify_and_stream(unfollow_activity) do
+ {:ok, unfollow_activity}
+ else
+ nil -> nil
+ {:error, error} -> Repo.rollback(error)
+ end
+ end
+
+ defp remote_unfollow_data(data) do
+ {recipients, _, _} = get_recipients(data)
+
+ %Activity{
+ data: data,
+ local: false,
+ actor: data["actor"],
+ recipients: recipients
+ }
+ end
+
@spec flag(map()) :: {:ok, Activity.t()} | {:error, any()}
def flag(params) do
with {:ok, result} <- Repo.transaction(fn -> do_flag(params) end) do
assert embedded_object["object"] == followed.ap_id
assert embedded_object["id"] == follow_activity.data["id"]
end
+
+ test "it removes the follow activity if it was remote" do
+ follower = insert(:user, local: false)
+ followed = insert(:user)
+
+ {:ok, _, _, follow_activity} = CommonAPI.follow(follower, followed)
+ {:ok, activity} = ActivityPub.unfollow(follower, followed, nil, false)
+
+ assert activity.data["type"] == "Undo"
+ assert activity.data["actor"] == follower.ap_id
+
+ activity = Activity.get_by_id(follow_activity.id)
+ assert is_nil(activity)
+ assert is_nil(Utils.fetch_latest_follow(follower, followed))
+ end
end
describe "timeline post-processing" do