Conversations: Add recipient list to conversation participation.

This enables to address the same group of people every time.
This commit is contained in:
lain 2019-08-02 11:55:41 +02:00
parent fd4b7239cd
commit f88560accd
7 changed files with 100 additions and 1 deletions

View File

@ -4,6 +4,7 @@
defmodule Pleroma.Conversation do defmodule Pleroma.Conversation do
alias Pleroma.Conversation.Participation alias Pleroma.Conversation.Participation
alias Pleroma.Conversation.Participation.RecipientShip
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
use Ecto.Schema use Ecto.Schema
@ -39,6 +40,15 @@ def get_for_ap_id(ap_id) do
Repo.get_by(__MODULE__, ap_id: ap_id) Repo.get_by(__MODULE__, ap_id: ap_id)
end end
def maybe_set_recipients(participation, activity) do
participation = Repo.preload(participation, :recipients)
if participation.recipients |> Enum.empty?() do
recipients = User.get_all_by_ap_id(activity.recipients)
RecipientShip.create(recipients, participation)
end
end
@doc """ @doc """
This will This will
1. Create a conversation if there isn't one already 1. Create a conversation if there isn't one already
@ -60,6 +70,7 @@ def create_or_bump_for(activity, opts \\ []) do
{:ok, participation} = {:ok, participation} =
Participation.create_for_user_and_conversation(user, conversation, opts) Participation.create_for_user_and_conversation(user, conversation, opts)
maybe_set_recipients(participation, activity)
participation participation
end) end)

View File

@ -5,6 +5,7 @@
defmodule Pleroma.Conversation.Participation do defmodule Pleroma.Conversation.Participation do
use Ecto.Schema use Ecto.Schema
alias Pleroma.Conversation alias Pleroma.Conversation
alias Pleroma.Conversation.Participation.RecipientShip
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -17,6 +18,9 @@ defmodule Pleroma.Conversation.Participation do
field(:read, :boolean, default: false) field(:read, :boolean, default: false)
field(:last_activity_id, Pleroma.FlakeId, virtual: true) field(:last_activity_id, Pleroma.FlakeId, virtual: true)
has_many(:recipient_ships, RecipientShip)
has_many(:recipients, through: [:recipient_ships, :user])
timestamps() timestamps()
end end

View File

@ -0,0 +1,34 @@
# 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.RecipientShip do
use Ecto.Schema
alias Pleroma.Conversation.Participation
alias Pleroma.User
alias Pleroma.Repo
import Ecto.Changeset
schema "conversation_participation_recipient_ships" do
belongs_to(:user, User, type: Pleroma.FlakeId)
belongs_to(:participation, Participation)
end
def creation_cng(struct, params) do
struct
|> cast(params, [:user_id, :participation_id])
|> validate_required([:user_id, :participation_id])
end
def create(%User{} = user, participation), do: create([user], participation)
def create(users, participation) do
Enum.each(users, fn user ->
%__MODULE__{}
|> creation_cng(%{user_id: user.id, participation_id: participation.id})
|> Repo.insert!()
end)
end
end

View File

@ -450,6 +450,13 @@ def get_by_ap_id(ap_id) do
Repo.get_by(User, ap_id: ap_id) Repo.get_by(User, ap_id: ap_id)
end end
def get_all_by_ap_id(ap_ids) do
from(u in __MODULE__,
where: u.ap_id in ^ap_ids
)
|> Repo.all()
end
# This is mostly an SPC migration fix. This guesses the user nickname by taking the last part # This is mostly an SPC migration fix. This guesses the user nickname by taking the last part
# of the ap_id and the domain and tries to get that user # of the ap_id and the domain and tries to get that user
def get_by_guessed_nickname(ap_id) do def get_by_guessed_nickname(ap_id) do

View File

@ -0,0 +1,13 @@
defmodule Pleroma.Repo.Migrations.CreateConversationParticipationRecipientShips do
use Ecto.Migration
def change do
create_if_not_exists table(:conversation_participation_recipient_ships) do
add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
add(:participation_id, references(:conversation_participations, on_delete: :delete_all))
end
create_if_not_exists index(:conversation_participation_recipient_ships, [:user_id])
create_if_not_exists index(:conversation_participation_recipient_ships, [:participation_id])
end
end

View File

@ -8,6 +8,36 @@ defmodule Pleroma.Conversation.ParticipationTest do
alias Pleroma.Conversation.Participation alias Pleroma.Conversation.Participation
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
test "for a new conversation, it sets the recipents of the participation" do
user = insert(:user)
other_user = insert(:user)
third_user = insert(:user)
{:ok, activity} =
CommonAPI.post(user, %{"status" => "Hey @#{other_user.nickname}.", "visibility" => "direct"})
[participation] = Participation.for_user(user)
participation = Pleroma.Repo.preload(participation, :recipients)
assert length(participation.recipients) == 2
assert user in participation.recipients
assert other_user in participation.recipients
# Mentioning another user in the same conversation will not add a new recipients.
{:ok, _activity} =
CommonAPI.post(user, %{
"in_reply_to_status_id" => activity.id,
"status" => "Hey @#{third_user.nickname}.",
"visibility" => "direct"
})
[participation] = Participation.for_user(user)
participation = Pleroma.Repo.preload(participation, :recipients)
assert length(participation.recipients) == 2
end
test "it creates a participation for a conversation and a user" do test "it creates a participation for a conversation and a user" do
user = insert(:user) user = insert(:user)
conversation = insert(:conversation) conversation = insert(:conversation)