@@ -66,6 +66,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). | |||||
- Mastodon API: Add monthly active users to `/api/v1/instance` (`pleroma.stats.mau`). | - 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: 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: `/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> | </details> | ||||
### Fixed | ### Fixed | ||||
@@ -61,9 +61,8 @@ defmodule Pleroma.Conversation do | |||||
"Create" <- activity.data["type"], | "Create" <- activity.data["type"], | ||||
%Object{} = object <- Object.normalize(activity, fetch: false), | %Object{} = object <- Object.normalize(activity, fetch: false), | ||||
true <- object.data["type"] in ["Note", "Question"], | 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) | users = User.get_users_from_set(activity.recipients, local_only: false) | ||||
participations = | participations = | ||||
@@ -220,4 +220,8 @@ defmodule Pleroma.Conversation.Participation do | |||||
select: %{count: count(p.id)} | select: %{count: count(p.id)} | ||||
) | ) | ||||
end | end | ||||
def delete(%__MODULE__{} = participation) do | |||||
Repo.delete(participation) | |||||
end | |||||
end | end |
@@ -46,16 +46,31 @@ defmodule Pleroma.Web.ApiSpec.ConversationOperation do | |||||
tags: ["Conversations"], | tags: ["Conversations"], | ||||
summary: "Mark conversation as read", | summary: "Mark conversation as read", | ||||
operationId: "ConversationController.mark_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"]}], | security: [%{"oAuth" => ["write:conversations"]}], | ||||
responses: %{ | responses: %{ | ||||
200 => Operation.response("Conversation", "application/json", Conversation) | 200 => Operation.response("Conversation", "application/json", Conversation) | ||||
} | } | ||||
} | } | ||||
end | 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 | end |
@@ -36,4 +36,13 @@ defmodule Pleroma.Web.MastodonAPI.ConversationController do | |||||
render(conn, "participation.json", participation: participation, for: user) | render(conn, "participation.json", participation: participation, for: user) | ||||
end | end | ||||
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 | end |
@@ -436,6 +436,7 @@ defmodule Pleroma.Web.Router do | |||||
get("/conversations", ConversationController, :index) | get("/conversations", ConversationController, :index) | ||||
post("/conversations/:id/read", ConversationController, :mark_as_read) | post("/conversations/:id/read", ConversationController, :mark_as_read) | ||||
delete("/conversations/:id", ConversationController, :delete) | |||||
get("/domain_blocks", DomainBlockController, :index) | get("/domain_blocks", DomainBlockController, :index) | ||||
post("/domain_blocks", DomainBlockController, :create) | post("/domain_blocks", DomainBlockController, :create) | ||||
@@ -359,4 +359,16 @@ defmodule Pleroma.Conversation.ParticipationTest do | |||||
assert Participation.unread_count(blocked) == 1 | assert Participation.unread_count(blocked) == 1 | ||||
end | end | ||||
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 | end |
@@ -217,6 +217,32 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do | |||||
assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200) | assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200) | ||||
end | 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 | defp create_direct_message(sender, recips) do | ||||
hellos = | hellos = | ||||
recips | recips | ||||