- Mastodon API: Add monthly active users to `/api/v1/instance` (`pleroma.stats.mau`).
- Mastodon API: Home, public, hashtag & list timelines accept `only_media`, `remote` & `local` parameters for filtration.
- Mastodon API: `/api/v1/accounts/:id` & `/api/v1/mutes` endpoints accept `with_relationships` parameter and return filled `pleroma.relationship` field.
+- Mastodon API: Endpoint to remove a conversation (`DELETE /api/v1/conversations/:id`).
</details>
### Fixed
"Create" <- activity.data["type"],
%Object{} = object <- Object.normalize(activity, fetch: false),
true <- object.data["type"] in ["Note", "Question"],
- ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"] do
- {:ok, conversation} = create_for_ap_id(ap_id)
-
+ ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"],
+ {:ok, conversation} <- create_for_ap_id(ap_id) do
users = User.get_users_from_set(activity.recipients, local_only: false)
participations =
select: %{count: count(p.id)}
)
end
+
+ def delete(%__MODULE__{} = participation) do
+ Repo.delete(participation)
+ end
end
tags: ["Conversations"],
summary: "Mark conversation as read",
operationId: "ConversationController.mark_as_read",
- parameters: [
- Operation.parameter(:id, :path, :string, "Conversation ID",
- example: "123",
- required: true
- )
- ],
+ parameters: [id_param()],
security: [%{"oAuth" => ["write:conversations"]}],
responses: %{
200 => Operation.response("Conversation", "application/json", Conversation)
}
}
end
+
+ def delete_operation do
+ %Operation{
+ tags: ["Conversations"],
+ summary: "Remove conversation",
+ operationId: "ConversationController.delete",
+ parameters: [id_param()],
+ security: [%{"oAuth" => ["write:conversations"]}],
+ responses: %{
+ 200 => empty_object_response()
+ }
+ }
+ end
+
+ def id_param do
+ Operation.parameter(:id, :path, :string, "Conversation ID",
+ example: "123",
+ required: true
+ )
+ end
end
render(conn, "participation.json", participation: participation, for: user)
end
end
+
+ @doc "DELETE /api/v1/conversations/:id"
+ def delete(%{assigns: %{user: user}} = conn, %{id: participation_id}) do
+ with %Participation{} = participation <-
+ Repo.get_by(Participation, id: participation_id, user_id: user.id),
+ {:ok, _} <- Participation.delete(participation) do
+ json(conn, %{})
+ end
+ end
end
get("/conversations", ConversationController, :index)
post("/conversations/:id/read", ConversationController, :mark_as_read)
+ delete("/conversations/:id", ConversationController, :delete)
get("/domain_blocks", DomainBlockController, :index)
post("/domain_blocks", DomainBlockController, :create)
assert Participation.unread_count(blocked) == 1
end
end
+
+ test "deletes a conversation" do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, _activity} =
+ CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
+
+ assert [participation] = Participation.for_user(other_user)
+ assert {:ok, _} = Participation.delete(participation)
+ assert [] == Participation.for_user(other_user)
+ end
end
assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
end
+ test "Removes a conversation", %{user: user_one, conn: conn} do
+ user_two = insert(:user)
+ token = insert(:oauth_token, user: user_one, scopes: ["read:statuses", "write:conversations"])
+
+ {:ok, _direct} = create_direct_message(user_one, [user_two])
+ {:ok, _direct} = create_direct_message(user_one, [user_two])
+
+ assert [%{"id" => conv1_id}, %{"id" => conv2_id}] =
+ conn
+ |> assign(:token, token)
+ |> get("/api/v1/conversations")
+ |> json_response_and_validate_schema(200)
+
+ assert %{} =
+ conn
+ |> assign(:token, token)
+ |> delete("/api/v1/conversations/#{conv1_id}")
+ |> json_response_and_validate_schema(200)
+
+ assert [%{"id" => ^conv2_id}] =
+ conn
+ |> assign(:token, token)
+ |> get("/api/v1/conversations")
+ |> json_response_and_validate_schema(200)
+ end
+
defp create_direct_message(sender, recips) do
hellos =
recips