logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

conversation.ex (3172B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Conversation do
  5. alias Pleroma.Conversation.Participation
  6. alias Pleroma.Conversation.Participation.RecipientShip
  7. alias Pleroma.Object
  8. alias Pleroma.Repo
  9. alias Pleroma.User
  10. use Ecto.Schema
  11. import Ecto.Changeset
  12. schema "conversations" do
  13. # This is the context ap id.
  14. field(:ap_id, :string)
  15. has_many(:participations, Participation)
  16. has_many(:users, through: [:participations, :user])
  17. timestamps()
  18. end
  19. def creation_cng(struct, params) do
  20. struct
  21. |> cast(params, [:ap_id])
  22. |> validate_required([:ap_id])
  23. |> unique_constraint(:ap_id)
  24. end
  25. def create_for_ap_id(ap_id) do
  26. %__MODULE__{}
  27. |> creation_cng(%{ap_id: ap_id})
  28. |> Repo.insert(
  29. on_conflict: [set: [updated_at: NaiveDateTime.utc_now()]],
  30. returning: true,
  31. conflict_target: :ap_id
  32. )
  33. end
  34. def get_for_ap_id(ap_id) do
  35. Repo.get_by(__MODULE__, ap_id: ap_id)
  36. end
  37. def maybe_create_recipientships(participation, activity) do
  38. participation = Repo.preload(participation, :recipients)
  39. if Enum.empty?(participation.recipients) do
  40. recipients = User.get_all_by_ap_id(activity.recipients)
  41. RecipientShip.create(recipients, participation)
  42. end
  43. end
  44. @doc """
  45. This will
  46. 1. Create a conversation if there isn't one already
  47. 2. Create a participation for all the people involved who don't have one already
  48. 3. Bump all relevant participations to 'unread'
  49. """
  50. def create_or_bump_for(activity, opts \\ []) do
  51. with true <- Pleroma.Web.ActivityPub.Visibility.direct?(activity),
  52. "Create" <- activity.data["type"],
  53. %Object{} = object <- Object.normalize(activity, fetch: false),
  54. true <- object.data["type"] in ["Note", "Question"],
  55. ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"],
  56. {:ok, conversation} <- create_for_ap_id(ap_id) do
  57. users = User.get_users_from_set(activity.recipients, local_only: false)
  58. participations =
  59. Enum.map(users, fn user ->
  60. invisible_conversation = Enum.any?(users, &User.blocks?(user, &1))
  61. opts = Keyword.put(opts, :invisible_conversation, invisible_conversation)
  62. {:ok, participation} =
  63. Participation.create_for_user_and_conversation(user, conversation, opts)
  64. maybe_create_recipientships(participation, activity)
  65. participation
  66. end)
  67. {:ok,
  68. %{
  69. conversation
  70. | participations: participations
  71. }}
  72. else
  73. e -> {:error, e}
  74. end
  75. end
  76. @doc """
  77. This is only meant to be run by a mix task. It creates conversations/participations for all direct messages in the database.
  78. """
  79. def bump_for_all_activities do
  80. stream =
  81. Pleroma.Web.ActivityPub.ActivityPub.fetch_direct_messages_query()
  82. |> Repo.stream()
  83. Repo.transaction(
  84. fn ->
  85. stream
  86. |> Enum.each(fn a -> create_or_bump_for(a, read: true) end)
  87. end,
  88. timeout: :infinity
  89. )
  90. end
  91. end