Merge branch 'develop' into feature/polls-2-electric-boogalo
[akkoma] / lib / pleroma / conversation.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Conversation do
6 alias Pleroma.Conversation.Participation
7 alias Pleroma.Repo
8 alias Pleroma.User
9 use Ecto.Schema
10 import Ecto.Changeset
11
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
18 timestamps()
19 end
20
21 def creation_cng(struct, params) do
22 struct
23 |> cast(params, [:ap_id])
24 |> validate_required([:ap_id])
25 |> unique_constraint(:ap_id)
26 end
27
28 def create_for_ap_id(ap_id) do
29 %__MODULE__{}
30 |> creation_cng(%{ap_id: ap_id})
31 |> Repo.insert(
32 on_conflict: [set: [updated_at: NaiveDateTime.utc_now()]],
33 returning: true,
34 conflict_target: :ap_id
35 )
36 end
37
38 def get_for_ap_id(ap_id) do
39 Repo.get_by(__MODULE__, ap_id: ap_id)
40 end
41
42 @doc """
43 This will
44 1. Create a conversation if there isn't one already
45 2. Create a participation for all the people involved who don't have one already
46 3. Bump all relevant participations to 'unread'
47 """
48 def create_or_bump_for(activity, opts \\ []) do
49 with true <- Pleroma.Web.ActivityPub.Visibility.is_direct?(activity),
50 "Create" <- activity.data["type"],
51 object <- Pleroma.Object.normalize(activity),
52 true <- object.data["type"] in ["Note", "Question"],
53 ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"] do
54 {:ok, conversation} = create_for_ap_id(ap_id)
55
56 users = User.get_users_from_set(activity.recipients, false)
57
58 participations =
59 Enum.map(users, fn user ->
60 {:ok, participation} =
61 Participation.create_for_user_and_conversation(user, conversation, opts)
62
63 participation
64 end)
65
66 {:ok,
67 %{
68 conversation
69 | participations: participations
70 }}
71 else
72 e -> {:error, e}
73 end
74 end
75
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
84 Repo.transaction(
85 fn ->
86 stream
87 |> Enum.each(fn a -> create_or_bump_for(a, read: true) end)
88 end,
89 timeout: :infinity
90 )
91 end
92 end