parent
9a5de0f454
commit
f3fc8b22b1
@ -0,0 +1,106 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.PleromaConversationOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias OpenApiSpex.Schema
|
||||
alias Pleroma.Web.ApiSpec.Schemas.Conversation
|
||||
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
||||
alias Pleroma.Web.ApiSpec.StatusOperation
|
||||
|
||||
import Pleroma.Web.ApiSpec.Helpers
|
||||
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
def show_operation do
|
||||
%Operation{
|
||||
tags: ["Conversations"],
|
||||
summary: "The conversation with the given ID",
|
||||
parameters: [
|
||||
Operation.parameter(:id, :path, :string, "Conversation ID",
|
||||
example: "123",
|
||||
required: true
|
||||
)
|
||||
],
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
operationId: "PleromaAPI.ConversationController.show",
|
||||
responses: %{
|
||||
200 => Operation.response("Conversation", "application/json", Conversation)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def statuses_operation do
|
||||
%Operation{
|
||||
tags: ["Conversations"],
|
||||
summary: "Timeline for a given conversation",
|
||||
parameters: [
|
||||
Operation.parameter(:id, :path, :string, "Conversation ID",
|
||||
example: "123",
|
||||
required: true
|
||||
)
|
||||
| pagination_params()
|
||||
],
|
||||
security: [%{"oAuth" => ["read:statuses"]}],
|
||||
operationId: "PleromaAPI.ConversationController.statuses",
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response(
|
||||
"Array of Statuses",
|
||||
"application/json",
|
||||
StatusOperation.array_of_statuses()
|
||||
)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def update_operation do
|
||||
%Operation{
|
||||
tags: ["Conversations"],
|
||||
summary: "Update a conversation. Used to change the set of recipients.",
|
||||
parameters: [
|
||||
Operation.parameter(:id, :path, :string, "Conversation ID",
|
||||
example: "123",
|
||||
required: true
|
||||
),
|
||||
Operation.parameter(
|
||||
:recipients,
|
||||
:query,
|
||||
%Schema{type: :array, items: FlakeID},
|
||||
"A list of ids of users that should receive posts to this conversation. This will replace the current list of recipients, so submit the full list. The owner of owner of the conversation will always be part of the set of recipients, though.",
|
||||
required: true
|
||||
)
|
||||
],
|
||||
security: [%{"oAuth" => ["write:conversations"]}],
|
||||
operationId: "PleromaAPI.ConversationController.update",
|
||||
responses: %{
|
||||
200 => Operation.response("Conversation", "application/json", Conversation)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def mark_as_read_operation do
|
||||
%Operation{
|
||||
tags: ["Conversations"],
|
||||
summary: "Marks all user's conversations as read",
|
||||
security: [%{"oAuth" => ["write:conversations"]}],
|
||||
operationId: "PleromaAPI.ConversationController.mark_as_read",
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response(
|
||||
"Array of Conversations that were marked as read",
|
||||
"application/json",
|
||||
%Schema{
|
||||
type: :array,
|
||||
items: Conversation,
|
||||
example: [Conversation.schema().example]
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
@ -0,0 +1,95 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.PleromaAPI.ConversationController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
||||
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
plug(:put_view, Pleroma.Web.MastodonAPI.ConversationView)
|
||||
plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action in [:show, :statuses])
|
||||
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["write:conversations"]} when action in [:update, :mark_as_read]
|
||||
)
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaConversationOperation
|
||||
|
||||
def show(%{assigns: %{user: %{id: user_id} = user}} = conn, %{id: participation_id}) do
|
||||
with %Participation{user_id: ^user_id} = participation <- Participation.get(participation_id) do
|
||||
render(conn, "participation.json", participation: participation, for: user)
|
||||
else
|
||||
_error ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{"error" => "Unknown conversation id"})
|
||||
end
|
||||
end
|
||||
|
||||
def statuses(
|
||||
%{assigns: %{user: %{id: user_id} = user}} = conn,
|
||||
%{id: participation_id} = params
|
||||
) do
|
||||
with %Participation{user_id: ^user_id} = participation <-
|
||||
Participation.get(participation_id, preload: [:conversation]) do
|
||||
params =
|
||||
params
|
||||
|> Map.new(fn {key, value} -> {to_string(key), value} end)
|
||||
|> Map.put("blocking_user", user)
|
||||
|> Map.put("muting_user", user)
|
||||
|> Map.put("user", user)
|
||||
|
||||
activities =
|
||||
participation.conversation.ap_id
|
||||
|> ActivityPub.fetch_activities_for_context_query(params)
|
||||
|> Pleroma.Pagination.fetch_paginated(Map.put(params, "total", false))
|
||||
|> Enum.reverse()
|
||||
|
||||
conn
|
||||
|> add_link_headers(activities)
|
||||
|> put_view(StatusView)
|
||||
|> render("index.json", activities: activities, for: user, as: :activity)
|
||||
else
|
||||
_error ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{"error" => "Unknown conversation id"})
|
||||
end
|
||||
end
|
||||
|
||||
def update(
|
||||
%{assigns: %{user: %{id: user_id} = user}} = conn,
|
||||
%{id: participation_id, recipients: recipients}
|
||||
) do
|
||||
with %Participation{user_id: ^user_id} = participation <- Participation.get(participation_id),
|
||||
{:ok, participation} <- Participation.set_recipients(participation, recipients) do
|
||||
render(conn, "participation.json", participation: participation, for: user)
|
||||
else
|
||||
{:error, message} ->
|
||||
conn
|
||||
|> put_status(:bad_request)
|
||||
|> json(%{"error" => message})
|
||||
|
||||
_error ->
|
||||
conn
|
||||
|> put_status(:not_found)
|
||||
|> json(%{"error" => "Unknown conversation id"})
|
||||
end
|
||||
end
|
||||
|
||||
def mark_as_read(%{assigns: %{user: user}} = conn, _params) do
|
||||
with {:ok, _, participations} <- Participation.mark_all_as_read(user) do
|
||||
conn
|
||||
|> add_link_headers(participations)
|
||||
|> render("participations.json", participations: participations, for: user)
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,136 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.PleromaAPI.ConversationControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "/api/v1/pleroma/conversations/:id" do
|
||||
user = insert(:user)
|
||||
%{user: other_user, conn: conn} = oauth_access(["read:statuses"])
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}!", visibility: "direct"})
|
||||
|
||||
[participation] = Participation.for_user(other_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/conversations/#{participation.id}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert result["id"] == participation.id |> to_string()
|
||||
end
|
||||
|
||||
test "/api/v1/pleroma/conversations/:id/statuses" do
|
||||
user = insert(:user)
|
||||
%{user: other_user, conn: conn} = oauth_access(["read:statuses"])
|
||||
third_user = insert(:user)
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{status: "Hi @#{third_user.nickname}!", visibility: "direct"})
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}!", visibility: "direct"})
|
||||
|
||||
[participation] = Participation.for_user(other_user)
|
||||
|
||||
{:ok, activity_two} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Hi!",
|
||||
in_reply_to_status_id: activity.id,
|
||||
in_reply_to_conversation_id: participation.id
|
||||
})
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/conversations/#{participation.id}/statuses")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert length(result) == 2
|
||||
|
||||
id_one = activity.id
|
||||
id_two = activity_two.id
|
||||
assert [%{"id" => ^id_one}, %{"id" => ^id_two}] = result
|
||||
|
||||
{:ok, %{id: id_three}} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Bye!",
|
||||
in_reply_to_status_id: activity.id,
|
||||
in_reply_to_conversation_id: participation.id
|
||||
})
|
||||
|
||||
assert [%{"id" => ^id_two}, %{"id" => ^id_three}] =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?limit=2")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^id_three}] =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/conversations/#{participation.id}/statuses?min_id=#{id_two}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "PATCH /api/v1/pleroma/conversations/:id" do
|
||||
%{user: user, conn: conn} = oauth_access(["write:conversations"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(user, %{status: "Hi", visibility: "direct"})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
assert [user] == participation.recipients
|
||||
assert other_user not in participation.recipients
|
||||
|
||||
query = "recipients[]=#{user.id}&recipients[]=#{other_user.id}"
|
||||
|
||||
result =
|
||||
conn
|
||||
|> patch("/api/v1/pleroma/conversations/#{participation.id}?#{query}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert result["id"] == participation.id |> to_string
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
|
||||
assert user in participation.recipients
|
||||
assert other_user in participation.recipients
|
||||
end
|
||||
|
||||
test "POST /api/v1/pleroma/conversations/read" do
|
||||
user = insert(:user)
|
||||
%{user: other_user, conn: conn} = oauth_access(["write:conversations"])
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}", visibility: "direct"})
|
||||
|
||||
{:ok, _activity} =
|
||||
CommonAPI.post(user, %{status: "Hi @#{other_user.nickname}", visibility: "direct"})
|
||||
|
||||
[participation2, participation1] = Participation.for_user(other_user)
|
||||
assert Participation.get(participation2.id).read == false
|
||||
assert Participation.get(participation1.id).read == false
|
||||
assert User.get_cached_by_id(other_user.id).unread_conversation_count == 2
|
||||
|
||||
[%{"unread" => false}, %{"unread" => false}] =
|
||||
conn
|
||||
|> post("/api/v1/pleroma/conversations/read", %{})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
[participation2, participation1] = Participation.for_user(other_user)
|
||||
assert Participation.get(participation2.id).read == true
|
||||
assert Participation.get(participation1.id).read == true
|
||||
assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0
|
||||
end
|
||||
end
|
Loading…
Reference in new issue