1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Marker do
16 @timelines ["notifications"]
19 field(:last_read_id, :string, default: "")
20 field(:timeline, :string, default: "")
21 field(:lock_version, :integer, default: 0)
22 field(:unread_count, :integer, default: 0)
24 belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
28 def get_markers(user, timelines \\ []) do
29 Repo.all(get_query(user, timelines))
32 def upsert(%User{} = user, attrs) do
34 |> Map.take(@timelines)
35 |> Enum.reduce(Multi.new(), fn {timeline, timeline_attrs}, multi ->
38 |> get_marker(timeline)
39 |> changeset(timeline_attrs)
41 Multi.insert(multi, timeline, marker,
43 on_conflict: {:replace, [:last_read_id, :unread_count]},
44 conflict_target: [:user_id, :timeline]
50 @spec multi_set_unread_count(Multi.t(), User.t(), String.t()) :: Multi.t()
51 def multi_set_unread_count(multi, %User{} = user, "notifications") do
53 |> Multi.run(:counters, fn _repo, _changes ->
54 {:ok, Repo.one(Pleroma.Notification.notifications_info_query(user))}
58 fn %{counters: attrs} ->
59 %Marker{timeline: "notifications", user_id: user.id}
61 |> Ecto.Changeset.change()
64 on_conflict: {:replace, [:last_read_id, :unread_count]},
65 conflict_target: [:user_id, :timeline]
69 def multi_set_unread_count(multi, _, _), do: multi
71 defp get_marker(user, timeline) do
72 case Repo.find_resource(get_query(user, timeline)) do
73 {:ok, marker} -> %__MODULE__{marker | user: user}
74 _ -> %__MODULE__{timeline: timeline, user_id: user.id}
79 defp changeset(marker, attrs) do
81 |> cast(attrs, [:last_read_id, :unread_count])
82 |> validate_required([:user_id, :timeline, :last_read_id])
83 |> validate_inclusion(:timeline, @timelines)
86 defp by_timeline(query, timeline) do
87 from(m in query, where: m.timeline in ^List.wrap(timeline))
90 defp by_user_id(query, id), do: from(m in query, where: m.user_id == ^id)
92 defp get_query(user, timelines) do
94 |> by_user_id(user.id)
95 |> by_timeline(timelines)