Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85829213
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/conversation.ex b/lib/conversation.ex
index 3d53e91b7..6eedc72b6 100644
--- a/lib/conversation.ex
+++ b/lib/conversation.ex
@@ -1,70 +1,70 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Conversation do
alias Pleroma.Repo
alias Pleroma.Conversation.Participation
alias Pleroma.User
use Ecto.Schema
import Ecto.Changeset
schema "conversations" do
# This is the context ap id.
field(:ap_id, :string)
has_many(:participations, Participation)
timestamps()
end
def creation_cng(struct, params) do
struct
|> cast(params, [:ap_id])
|> validate_required([:ap_id])
|> unique_constraint(:ap_id)
end
def create_for_ap_id(ap_id) do
%__MODULE__{}
|> creation_cng(%{ap_id: ap_id})
|> Repo.insert(
on_conflict: [set: [updated_at: NaiveDateTime.utc_now()]],
returning: true,
conflict_target: :ap_id
)
end
def get_for_ap_id(ap_id) do
Repo.get_by(__MODULE__, ap_id: ap_id)
end
@doc """
This will
1. Create a conversation if there isn't one already
2. Create a participation for all the people involved who don't have one already
3. Bump all relevant participations to 'unread'
"""
def create_or_bump_for(activity) do
with true <- Pleroma.Web.ActivityPub.Visibility.is_direct?(activity),
"Create" <- activity.data["type"],
"Note" <- activity.data["object"]["type"],
ap_id when is_binary(ap_id) <- activity.data["object"]["context"] do
{:ok, conversation} = create_for_ap_id(ap_id)
- local_users = User.get_users_from_set(activity.recipients, true)
+ users = User.get_users_from_set(activity.recipients)
participations =
- Enum.map(local_users, fn user ->
+ Enum.map(users, fn user ->
{:ok, participation} =
Participation.create_for_user_and_conversation(user, conversation)
participation
end)
%{
conversation
| participations: participations
}
end
end
end
diff --git a/lib/conversation/participation.ex b/lib/conversation/participation.ex
index a58d0ca0d..23e6409f1 100644
--- a/lib/conversation/participation.ex
+++ b/lib/conversation/participation.ex
@@ -1,53 +1,62 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Conversation.Participation do
use Ecto.Schema
alias Pleroma.User
alias Pleroma.Conversation
alias Pleroma.Repo
import Ecto.Changeset
+ import Ecto.Query
schema "conversation_participations" do
belongs_to(:user, User, type: Pleroma.FlakeId)
belongs_to(:conversation, Conversation)
field(:read, :boolean, default: false)
timestamps()
end
def creation_cng(struct, params) do
struct
|> cast(params, [:user_id, :conversation_id])
|> validate_required([:user_id, :conversation_id])
end
def create_for_user_and_conversation(user, conversation) do
%__MODULE__{}
|> creation_cng(%{user_id: user.id, conversation_id: conversation.id})
|> Repo.insert(
on_conflict: [set: [read: false, updated_at: NaiveDateTime.utc_now()]],
returning: true,
conflict_target: [:user_id, :conversation_id]
)
end
def read_cng(struct, params) do
struct
|> cast(params, [:read])
|> validate_required([:read])
end
def mark_as_read(participation) do
participation
|> read_cng(%{read: true})
|> Repo.update()
end
def mark_as_unread(participation) do
participation
|> read_cng(%{read: false})
|> Repo.update()
end
+
+ def for_user(user, params \\ %{}) do
+ from(p in __MODULE__,
+ where: p.user_id == ^user.id,
+ order_by: [desc: p.updated_at]
+ )
+ |> Pleroma.Pagination.fetch_paginated(params)
+ end
end
diff --git a/test/conversation/participation_test.exs b/test/conversation/participation_test.exs
index 4e7d9dc92..c52b4ed88 100644
--- a/test/conversation/participation_test.exs
+++ b/test/conversation/participation_test.exs
@@ -1,54 +1,84 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Conversation.ParticipationTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Conversation.Participation
+ alias Pleroma.Web.CommonAPI
test "it creates a participation for a conversation and a user" do
user = insert(:user)
conversation = insert(:conversation)
{:ok, %Participation{} = participation} =
Participation.create_for_user_and_conversation(user, conversation)
assert participation.user_id == user.id
assert participation.conversation_id == conversation.id
:timer.sleep(1000)
# Creating again returns the same participation
{:ok, %Participation{} = participation_two} =
Participation.create_for_user_and_conversation(user, conversation)
assert participation.id == participation_two.id
refute participation.updated_at == participation_two.updated_at
end
test "recreating an existing participations sets it to unread" do
participation = insert(:participation, %{read: true})
{:ok, participation} =
Participation.create_for_user_and_conversation(
participation.user,
participation.conversation
)
refute participation.read
end
test "it marks a participation as read" do
participation = insert(:participation, %{read: false})
{:ok, participation} = Participation.mark_as_read(participation)
assert participation.read
end
test "it marks a participation as unread" do
participation = insert(:participation, %{read: true})
{:ok, participation} = Participation.mark_as_unread(participation)
refute participation.read
end
+
+ test "gets all the participations for a user, ordered by updated at descending" do
+ user = insert(:user)
+ {:ok, activity_one} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
+ :timer.sleep(1000)
+ {:ok, activity_two} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
+ :timer.sleep(1000)
+
+ {:ok, activity_three} =
+ CommonAPI.post(user, %{
+ "status" => "x",
+ "visibility" => "direct",
+ "in_reply_to_status_id" => activity_one.id
+ })
+
+ assert [participation_one, participation_two] =
+ Participation.for_user(user)
+ |> Repo.preload(:conversation)
+
+ assert participation_one.conversation.ap_id == activity_three.data["object"]["context"]
+ assert participation_two.conversation.ap_id == activity_two.data["object"]["context"]
+
+ # Pagination
+ assert [participation_one] =
+ Participation.for_user(user, %{limit: 1})
+ |> Repo.preload(:conversation)
+
+ assert participation_one.conversation.ap_id == activity_three.data["object"]["context"]
+ end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Oct 31, 4:47 PM (20 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1801601
Default Alt Text
(7 KB)
Attached To
Mode
rPUBE pleroma-upstream
Attached
Detach File
Event Timeline