89537d155723d1435056d7e9393f38860046af17
[akkoma] / lib / pleroma / chat / message_reference.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Chat.MessageReference do
6 @moduledoc """
7 A reference that builds a relation between an AP chat message that a user can see and whether it has been seen
8 by them, or should be displayed to them. Used to build the chat view that is presented to the user.
9 """
10
11 use Ecto.Schema
12
13 alias Pleroma.Chat
14 alias Pleroma.Object
15 alias Pleroma.Repo
16
17 import Ecto.Changeset
18 import Ecto.Query
19
20 @primary_key {:id, FlakeId.Ecto.Type, autogenerate: true}
21
22 schema "chat_message_references" do
23 belongs_to(:object, Object)
24 belongs_to(:chat, Chat, type: FlakeId.Ecto.CompatType)
25
26 field(:unread, :boolean, default: true)
27
28 timestamps()
29 end
30
31 def changeset(struct, params) do
32 struct
33 |> cast(params, [:object_id, :chat_id, :unread])
34 |> validate_required([:object_id, :chat_id, :unread])
35 end
36
37 def get_by_id(id) do
38 __MODULE__
39 |> Repo.get(id)
40 |> Repo.preload(:object)
41 end
42
43 def delete(cm_ref) do
44 cm_ref
45 |> Repo.delete()
46 end
47
48 def delete_for_object(%{id: object_id}) do
49 from(cr in __MODULE__,
50 where: cr.object_id == ^object_id
51 )
52 |> Repo.delete_all()
53 end
54
55 def for_chat_and_object(%{id: chat_id}, %{id: object_id}) do
56 __MODULE__
57 |> Repo.get_by(chat_id: chat_id, object_id: object_id)
58 |> Repo.preload(:object)
59 end
60
61 def for_chat_query(chat) do
62 from(cr in __MODULE__,
63 where: cr.chat_id == ^chat.id,
64 order_by: [desc: :id],
65 preload: [:object]
66 )
67 end
68
69 def last_message_for_chat(chat) do
70 chat
71 |> for_chat_query()
72 |> limit(1)
73 |> Repo.one()
74 end
75
76 def create(chat, object, unread) do
77 params = %{
78 chat_id: chat.id,
79 object_id: object.id,
80 unread: unread
81 }
82
83 %__MODULE__{}
84 |> changeset(params)
85 |> Repo.insert()
86 end
87
88 def unread_count_for_chat(chat) do
89 chat
90 |> for_chat_query()
91 |> where([cmr], cmr.unread == true)
92 |> Repo.aggregate(:count)
93 end
94
95 def mark_as_read(cm_ref) do
96 cm_ref
97 |> changeset(%{unread: false})
98 |> Repo.update()
99 end
100
101 def set_all_seen_for_chat(chat, last_read_id \\ nil) do
102 query =
103 chat
104 |> for_chat_query()
105 |> exclude(:order_by)
106 |> exclude(:preload)
107 |> where([cmr], cmr.unread == true)
108
109 if last_read_id do
110 query
111 |> where([cmr], cmr.id <= ^last_read_id)
112 else
113 query
114 end
115 |> Repo.update_all(set: [unread: false])
116 end
117 end