diff options
9 files changed, 207 insertions, 38 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 4a56beb73..b6ba91052 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1207,6 +1207,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      end    end +  defp exclude_chat_messages(query, %{"include_chat_messages" => true}), do: query + +  defp exclude_chat_messages(query, _) do +    if has_named_binding?(query, :object) do +      from([activity, object: o] in query, +        where: fragment("not(?->>'type' = ?)", o.data, "ChatMessage") +      ) +    else +      query +    end +  end +    defp exclude_id(query, %{"exclude_id" => id}) when is_binary(id) do      from(activity in query, where: activity.id != ^id)    end @@ -1312,6 +1324,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      |> restrict_instance(opts)      |> Activity.restrict_deactivated_users()      |> exclude_poll_votes(opts) +    |> exclude_chat_messages(opts)      |> exclude_visibility(opts)    end diff --git a/lib/pleroma/web/api_spec/operations/chat_operation.ex b/lib/pleroma/web/api_spec/operations/chat_operation.ex new file mode 100644 index 000000000..038ebb29d --- /dev/null +++ b/lib/pleroma/web/api_spec/operations/chat_operation.ex @@ -0,0 +1,81 @@ +# 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.ChatOperation do +  alias OpenApiSpex.Operation +  alias OpenApiSpex.Schema + +  @spec open_api_operation(atom) :: Operation.t() +  def open_api_operation(action) do +    operation = String.to_existing_atom("#{action}_operation") +    apply(__MODULE__, operation, []) +  end + +  def create_operation do +    %Operation{ +      tags: ["chat"], +      summary: "Create a chat", +      responses: %{ +        200 => +          Operation.response("Chat", "application/json", %Schema{ +            type: :object, +            description: "A created chat is returned", +            properties: %{ +              id: %Schema{type: :integer} +            } +          }) +      } +    } +  end + +  def index_operation do +    %Operation{ +      tags: ["chat"], +      summary: "Get a list of chats that you participated in", +      responses: %{ +        200 => +          Operation.response("Chats", "application/json", %Schema{ +            type: :array, +            description: "A list of chats", +            items: %Schema{ +              type: :object, +              description: "A chat" +            } +          }) +      } +    } +  end + +  def messages_operation do +    %Operation{ +      tags: ["chat"], +      summary: "Get the most recent messages of the chat", +      responses: %{ +        200 => +          Operation.response("Messages", "application/json", %Schema{ +            type: :array, +            description: "A list of chat messages", +            items: %Schema{ +              type: :object, +              description: "A chat message" +            } +          }) +      } +    } +  end + +  def post_chat_message_operation do +    %Operation{ +      tags: ["chat"], +      summary: "Post a message to the chat", +      responses: %{ +        200 => +          Operation.response("Message", "application/json", %Schema{ +            type: :object, +            description: "A chat message" +          }) +      } +    } +  end +end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 2f13daf0c..c306c1e96 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -24,7 +24,7 @@ defmodule Pleroma.Web.CommonAPI do    require Pleroma.Constants    require Logger -  def post_chat_message(user, recipient, content) do +  def post_chat_message(%User{} = user, %User{} = recipient, content) do      transaction =        Repo.transaction(fn ->          with {_, {:ok, chat_message_data, _meta}} <- diff --git a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex index 972330f4e..5ec546847 100644 --- a/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/chat_controller.ex @@ -9,6 +9,8 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do    alias Pleroma.Repo    alias Pleroma.User    alias Pleroma.Web.CommonAPI +  alias Pleroma.Web.PleromaAPI.ChatView +  alias Pleroma.Web.PleromaAPI.ChatMessageView    import Ecto.Query @@ -17,6 +19,8 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do    # - Views / Representers    # - Error handling +  defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ChatOperation +    def post_chat_message(%{assigns: %{user: %{id: user_id} = user}} = conn, %{          "id" => id,          "content" => content @@ -25,14 +29,9 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do           %User{} = recipient <- User.get_cached_by_ap_id(chat.recipient),           {:ok, activity} <- CommonAPI.post_chat_message(user, recipient, content),           message <- Object.normalize(activity) do -      represented_message = %{ -        actor: message.data["actor"], -        id: message.id, -        content: message.data["content"] -      } -        conn -      |> json(represented_message) +      |> put_view(ChatMessageView) +      |> render("show.json", for: user, object: message, chat: chat)      end    end @@ -60,18 +59,9 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do          )          |> Repo.all() -      represented_messages = -        messages -        |> Enum.map(fn message -> -          %{ -            actor: message.data["actor"], -            id: message.id, -            content: message.data["content"] -          } -        end) -        conn -      |> json(represented_messages) +      |> put_view(ChatMessageView) +      |> render("index.json", for: user, objects: messages, chat: chat)      end    end @@ -83,31 +73,18 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do        )        |> Repo.all() -    represented_chats = -      Enum.map(chats, fn chat -> -        %{ -          id: chat.id, -          recipient: chat.recipient, -          unread: chat.unread -        } -      end) -      conn -    |> json(represented_chats) +    |> put_view(ChatView) +    |> render("index.json", chats: chats)    end    def create(%{assigns: %{user: user}} = conn, params) do      recipient = params["ap_id"] |> URI.decode_www_form()      with {:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do -      represented_chat = %{ -        id: chat.id, -        recipient: chat.recipient, -        unread: chat.unread -      } -        conn -      |> json(represented_chat) +      |> put_view(ChatView) +      |> render("show.json", chat: chat)      end    end  end diff --git a/lib/pleroma/web/pleroma_api/views/chat_message_view.ex b/lib/pleroma/web/pleroma_api/views/chat_message_view.ex new file mode 100644 index 000000000..2df591358 --- /dev/null +++ b/lib/pleroma/web/pleroma_api/views/chat_message_view.ex @@ -0,0 +1,28 @@ +# 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.ChatMessageView do +  use Pleroma.Web, :view + +  alias Pleroma.Chat + +  def render( +        "show.json", +        %{ +          object: %{id: id, data: %{"type" => "ChatMessage"} = chat_message}, +          chat: %Chat{id: chat_id} +        } +      ) do +    %{ +      id: id, +      content: chat_message["content"], +      chat_id: chat_id, +      actor: chat_message["actor"] +    } +  end + +  def render("index.json", opts) do +    render_many(opts[:objects], __MODULE__, "show.json", Map.put(opts, :as, :object)) +  end +end diff --git a/lib/pleroma/web/pleroma_api/views/chat_view.ex b/lib/pleroma/web/pleroma_api/views/chat_view.ex new file mode 100644 index 000000000..ee48385bf --- /dev/null +++ b/lib/pleroma/web/pleroma_api/views/chat_view.ex @@ -0,0 +1,21 @@ +# 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.ChatView do +  use Pleroma.Web, :view + +  alias Pleroma.Chat + +  def render("show.json", %{chat: %Chat{} = chat}) do +    %{ +      id: chat.id, +      recipient: chat.recipient, +      unread: chat.unread +    } +  end + +  def render("index.json", %{chats: chats}) do +    render_many(chats, __MODULE__, "show.json") +  end +end diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs index 06efdc901..a5c227991 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -51,6 +51,9 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do        {:ok, activity} = CommonAPI.post(third_user, %{"status" => "repeated post"})        {:ok, _, _} = CommonAPI.repeat(activity.id, following) +      # This one should not show up in the TL +      {:ok, _activity} = CommonAPI.post_chat_message(third_user, user, ":gun:") +        ret_conn = get(conn, uri)        assert Enum.empty?(json_response(ret_conn, :ok)) diff --git a/test/web/pleroma_api/controllers/chat_controller_test.exs b/test/web/pleroma_api/controllers/chat_controller_test.exs index b4230e5ad..dad37a889 100644 --- a/test/web/pleroma_api/controllers/chat_controller_test.exs +++ b/test/web/pleroma_api/controllers/chat_controller_test.exs @@ -23,14 +23,13 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do          |> json_response(200)        assert result["content"] == "Hallo!!" +      assert result["chat_id"] == chat.id      end    end    describe "GET /api/v1/pleroma/chats/:id/messages" do      # TODO -    # - Test that statuses don't show      # - Test the case where it's not the user's chat -    # - Test the returned data      test "it returns the messages for a given chat", %{conn: conn} do        user = insert(:user)        other_user = insert(:user) @@ -49,6 +48,11 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do          |> get("/api/v1/pleroma/chats/#{chat.id}/messages")          |> json_response(200) +      result +      |> Enum.each(fn message -> +        assert message["chat_id"] == chat.id +      end) +        assert length(result) == 3      end    end diff --git a/test/web/pleroma_api/views/chat_message_view_test.exs b/test/web/pleroma_api/views/chat_message_view_test.exs new file mode 100644 index 000000000..e690da022 --- /dev/null +++ b/test/web/pleroma_api/views/chat_message_view_test.exs @@ -0,0 +1,42 @@ +# 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.ChatMessageViewTest do +  use Pleroma.DataCase + +  alias Pleroma.Chat +  alias Pleroma.Object +  alias Pleroma.Web.CommonAPI +  alias Pleroma.Web.PleromaAPI.ChatMessageView + +  import Pleroma.Factory + +  test "it displays a chat message" do +    user = insert(:user) +    recipient = insert(:user) +    {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "kippis") + +    chat = Chat.get(user.id, recipient.ap_id) + +    object = Object.normalize(activity) + +    chat_message = ChatMessageView.render("show.json", object: object, for: user, chat: chat) + +    assert chat_message[:id] == object.id +    assert chat_message[:content] == "kippis" +    assert chat_message[:actor] == user.ap_id +    assert chat_message[:chat_id] + +    {:ok, activity} = CommonAPI.post_chat_message(recipient, user, "gkgkgk") + +    object = Object.normalize(activity) + +    chat_message_two = ChatMessageView.render("show.json", object: object, for: user, chat: chat) + +    assert chat_message_two[:id] == object.id +    assert chat_message_two[:content] == "gkgkgk" +    assert chat_message_two[:actor] == recipient.ap_id +    assert chat_message_two[:chat_id] == chat_message[:chat_id] +  end +end  | 
