Marker: added unread_count field
[akkoma] / lib / pleroma / marker.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.Marker do
6 use Ecto.Schema
7
8 import Ecto.Changeset
9 import Ecto.Query
10
11 alias Ecto.Multi
12 alias Pleroma.Repo
13 alias Pleroma.User
14
15 @timelines ["notifications"]
16
17 schema "markers" do
18 field(:last_read_id, :string, default: "")
19 field(:timeline, :string, default: "")
20 field(:lock_version, :integer, default: 0)
21 field(:unread_count, :integer, default: 0)
22
23 belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
24 timestamps()
25 end
26
27 def get_markers(user, timelines \\ []) do
28 Repo.all(get_query(user, timelines))
29 end
30
31 def upsert(%User{} = user, attrs) do
32 attrs
33 |> Map.take(@timelines)
34 |> Enum.reduce(Multi.new(), fn {timeline, timeline_attrs}, multi ->
35 marker =
36 user
37 |> get_marker(timeline)
38 |> changeset(timeline_attrs)
39
40 Multi.insert(multi, timeline, marker,
41 returning: true,
42 on_conflict: {:replace, [:last_read_id, :unread_count]},
43 conflict_target: [:user_id, :timeline]
44 )
45 end)
46 |> Repo.transaction()
47 end
48
49 defp get_marker(user, timeline) do
50 case Repo.find_resource(get_query(user, timeline)) do
51 {:ok, marker} -> %__MODULE__{marker | user: user}
52 _ -> %__MODULE__{timeline: timeline, user_id: user.id}
53 end
54 end
55
56 @doc false
57 defp changeset(marker, attrs) do
58 marker
59 |> cast(attrs, [:last_read_id, :unread_count])
60 |> validate_required([:user_id, :timeline, :last_read_id])
61 |> validate_inclusion(:timeline, @timelines)
62 end
63
64 defp by_timeline(query, timeline) do
65 from(m in query, where: m.timeline in ^List.wrap(timeline))
66 end
67
68 defp by_user_id(query, id), do: from(m in query, where: m.user_id == ^id)
69
70 defp get_query(user, timelines) do
71 __MODULE__
72 |> by_user_id(user.id)
73 |> by_timeline(timelines)
74 end
75 end