From d1da6b155ab758ae4eb8fa154997a0a2a179897c Mon Sep 17 00:00:00 2001
From: lain <lain@soykaf.club>
Date: Wed, 10 Apr 2019 09:34:53 +0200
Subject: [PATCH] Conversation: Add Conversations and Participations.

---
 lib/conversation.ex                           | 30 ++++++++++++++++++
 lib/conversation/participation.ex             | 31 +++++++++++++++++++
 .../20190408123347_create_conversations.exs   | 26 ++++++++++++++++
 test/conversation/participation_test.exs      | 22 +++++++++++++
 test/conversation_test.exs                    | 12 +++++++
 test/support/factory.ex                       |  6 ++++
 6 files changed, 127 insertions(+)
 create mode 100644 lib/conversation.ex
 create mode 100644 lib/conversation/participation.ex
 create mode 100644 priv/repo/migrations/20190408123347_create_conversations.exs
 create mode 100644 test/conversation/participation_test.exs
 create mode 100644 test/conversation_test.exs

diff --git a/lib/conversation.ex b/lib/conversation.ex
new file mode 100644
index 000000000..cfb78d925
--- /dev/null
+++ b/lib/conversation.ex
@@ -0,0 +1,30 @@
+# 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
+  use Ecto.Schema
+  import Ecto.Changeset
+
+  schema "conversations" do
+    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()
+  end
+end
diff --git a/lib/conversation/participation.ex b/lib/conversation/participation.ex
new file mode 100644
index 000000000..244d37c46
--- /dev/null
+++ b/lib/conversation/participation.ex
@@ -0,0 +1,31 @@
+# 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
+
+  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()
+  end
+end
diff --git a/priv/repo/migrations/20190408123347_create_conversations.exs b/priv/repo/migrations/20190408123347_create_conversations.exs
new file mode 100644
index 000000000..68bf766bc
--- /dev/null
+++ b/priv/repo/migrations/20190408123347_create_conversations.exs
@@ -0,0 +1,26 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Repo.Migrations.CreateConversations do
+  use Ecto.Migration
+
+  def change do
+    create table(:conversations) do
+      add(:ap_id, :string, null: false)
+      timestamps()
+    end
+
+    create table(:conversation_participations) do
+      add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
+      add(:conversation_id, references(:conversations, on_delete: :delete_all))
+      add(:read, :boolean, default: false)
+
+      timestamps()
+    end
+
+    create index(:conversation_participations, [:user_id])
+    create index(:conversation_participations, [:conversation_id])
+    create unique_index(:conversations, [:ap_id])
+  end
+end
diff --git a/test/conversation/participation_test.exs b/test/conversation/participation_test.exs
new file mode 100644
index 000000000..8dc15a802
--- /dev/null
+++ b/test/conversation/participation_test.exs
@@ -0,0 +1,22 @@
+# 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
+
+  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
+  end
+end
diff --git a/test/conversation_test.exs b/test/conversation_test.exs
new file mode 100644
index 000000000..8fb55d51c
--- /dev/null
+++ b/test/conversation_test.exs
@@ -0,0 +1,12 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.ConversationTest do
+  use Pleroma.DataCase
+  alias Pleroma.Conversation
+
+  test "it creates a conversation for given ap_id" do
+    assert {:ok, %Conversation{}} = Conversation.create_for_ap_id("https://some_ap_id")
+  end
+end
diff --git a/test/support/factory.ex b/test/support/factory.ex
index ea59912cf..af38be46c 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -5,6 +5,12 @@
 defmodule Pleroma.Factory do
   use ExMachina.Ecto, repo: Pleroma.Repo
 
+  def conversation_factory do
+    %Pleroma.Conversation{
+      ap_id: sequence(:ap_id, &"https://some_conversation/#{&1}")
+    }
+  end
+
   def user_factory do
     user = %Pleroma.User{
       name: sequence(:name, &"Test テスト User #{&1}"),