Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

173 řádky
5.1KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.PleromaAPI.ChatController do
  5. use Pleroma.Web, :controller
  6. import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
  7. alias Pleroma.Activity
  8. alias Pleroma.Chat
  9. alias Pleroma.Chat.MessageReference
  10. alias Pleroma.Object
  11. alias Pleroma.Pagination
  12. alias Pleroma.Repo
  13. alias Pleroma.User
  14. alias Pleroma.Web.CommonAPI
  15. alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
  16. alias Pleroma.Web.PleromaAPI.ChatView
  17. alias Pleroma.Web.Plugs.OAuthScopesPlug
  18. import Ecto.Query
  19. action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
  20. plug(
  21. OAuthScopesPlug,
  22. %{scopes: ["write:chats"]}
  23. when action in [
  24. :post_chat_message,
  25. :create,
  26. :mark_as_read,
  27. :mark_message_as_read,
  28. :delete_message
  29. ]
  30. )
  31. plug(
  32. OAuthScopesPlug,
  33. %{scopes: ["read:chats"]} when action in [:messages, :index, :show]
  34. )
  35. plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
  36. defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ChatOperation
  37. def delete_message(%{assigns: %{user: %{id: user_id} = user}} = conn, %{
  38. message_id: message_id,
  39. id: chat_id
  40. }) do
  41. with %MessageReference{} = cm_ref <-
  42. MessageReference.get_by_id(message_id),
  43. ^chat_id <- to_string(cm_ref.chat_id),
  44. %Chat{user_id: ^user_id} <- Chat.get_by_id(chat_id),
  45. {:ok, _} <- remove_or_delete(cm_ref, user) do
  46. conn
  47. |> put_view(MessageReferenceView)
  48. |> render("show.json", chat_message_reference: cm_ref)
  49. else
  50. _e ->
  51. {:error, :could_not_delete}
  52. end
  53. end
  54. defp remove_or_delete(
  55. %{object: %{data: %{"actor" => actor, "id" => id}}},
  56. %{ap_id: actor} = user
  57. ) do
  58. with %Activity{} = activity <- Activity.get_create_by_object_ap_id(id) do
  59. CommonAPI.delete(activity.id, user)
  60. end
  61. end
  62. defp remove_or_delete(cm_ref, _), do: MessageReference.delete(cm_ref)
  63. def post_chat_message(
  64. %{body_params: params, assigns: %{user: user}} = conn,
  65. %{id: id}
  66. ) do
  67. with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
  68. %User{} = recipient <- User.get_cached_by_ap_id(chat.recipient),
  69. {:ok, activity} <-
  70. CommonAPI.post_chat_message(user, recipient, params[:content],
  71. media_id: params[:media_id]
  72. ),
  73. message <- Object.normalize(activity, false),
  74. cm_ref <- MessageReference.for_chat_and_object(chat, message) do
  75. conn
  76. |> put_view(MessageReferenceView)
  77. |> render("show.json", chat_message_reference: cm_ref)
  78. else
  79. {:reject, message} ->
  80. conn
  81. |> put_status(:unprocessable_entity)
  82. |> json(%{error: message})
  83. {:error, message} ->
  84. conn
  85. |> put_status(:bad_request)
  86. |> json(%{error: message})
  87. end
  88. end
  89. def mark_message_as_read(
  90. %{assigns: %{user: %{id: user_id}}} = conn,
  91. %{id: chat_id, message_id: message_id}
  92. ) do
  93. with %MessageReference{} = cm_ref <- MessageReference.get_by_id(message_id),
  94. ^chat_id <- to_string(cm_ref.chat_id),
  95. %Chat{user_id: ^user_id} <- Chat.get_by_id(chat_id),
  96. {:ok, cm_ref} <- MessageReference.mark_as_read(cm_ref) do
  97. conn
  98. |> put_view(MessageReferenceView)
  99. |> render("show.json", chat_message_reference: cm_ref)
  100. end
  101. end
  102. def mark_as_read(
  103. %{body_params: %{last_read_id: last_read_id}, assigns: %{user: user}} = conn,
  104. %{id: id}
  105. ) do
  106. with {:ok, chat} <- Chat.get_by_user_and_id(user, id),
  107. {_n, _} <- MessageReference.set_all_seen_for_chat(chat, last_read_id) do
  108. conn
  109. |> put_view(ChatView)
  110. |> render("show.json", chat: chat)
  111. end
  112. end
  113. def messages(%{assigns: %{user: user}} = conn, %{id: id} = params) do
  114. with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do
  115. chat_message_refs =
  116. chat
  117. |> MessageReference.for_chat_query()
  118. |> Pagination.fetch_paginated(params)
  119. conn
  120. |> add_link_headers(chat_message_refs)
  121. |> put_view(MessageReferenceView)
  122. |> render("index.json", chat_message_references: chat_message_refs)
  123. end
  124. end
  125. def index(%{assigns: %{user: %{id: user_id} = user}} = conn, _params) do
  126. blocked_ap_ids = User.blocked_users_ap_ids(user)
  127. chats =
  128. Chat.for_user_query(user_id)
  129. |> where([c], c.recipient not in ^blocked_ap_ids)
  130. |> Repo.all()
  131. conn
  132. |> put_view(ChatView)
  133. |> render("index.json", chats: chats)
  134. end
  135. def create(%{assigns: %{user: user}} = conn, %{id: id}) do
  136. with %User{ap_id: recipient} <- User.get_cached_by_id(id),
  137. {:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
  138. conn
  139. |> put_view(ChatView)
  140. |> render("show.json", chat: chat)
  141. end
  142. end
  143. def show(%{assigns: %{user: user}} = conn, %{id: id}) do
  144. with {:ok, chat} <- Chat.get_by_user_and_id(user, id) do
  145. conn
  146. |> put_view(ChatView)
  147. |> render("show.json", chat: chat)
  148. end
  149. end
  150. end