Commit 2e786866 authored by lain's avatar lain
Browse files

SideEffects: Handle ChatMessage creation.

parent 3775683a
...@@ -18,23 +18,28 @@ defmodule Pleroma.Chat do ...@@ -18,23 +18,28 @@ defmodule Pleroma.Chat do
schema "chats" do schema "chats" do
belongs_to(:user, User, type: FlakeId.Ecto.CompatType) belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
field(:recipient, :string) field(:recipient, :string)
field(:unread, :integer, default: 0) field(:unread, :integer, default: 0, read_after_writes: true)
timestamps() timestamps()
end end
def creation_cng(struct, params) do def creation_cng(struct, params) do
struct struct
|> cast(params, [:user_id, :recipient]) |> cast(params, [:user_id, :recipient, :unread])
|> validate_required([:user_id, :recipient]) |> validate_required([:user_id, :recipient])
|> unique_constraint(:user_id, name: :chats_user_id_recipient_index) |> unique_constraint(:user_id, name: :chats_user_id_recipient_index)
end end
def get_or_create(user_id, recipient) do def get(user_id, recipient) do
__MODULE__
|> Repo.get_by(user_id: user_id, recipient: recipient)
end
def bump_or_create(user_id, recipient) do
%__MODULE__{} %__MODULE__{}
|> creation_cng(%{user_id: user_id, recipient: recipient}) |> creation_cng(%{user_id: user_id, recipient: recipient, unread: 1})
|> Repo.insert( |> Repo.insert(
on_conflict: [set: [updated_at: NaiveDateTime.utc_now()]], on_conflict: [set: [updated_at: NaiveDateTime.utc_now()], inc: [unread: 1]],
conflict_target: [:user_id, :recipient] conflict_target: [:user_id, :recipient]
) )
end end
......
...@@ -10,6 +10,28 @@ defmodule Pleroma.Web.ActivityPub.Builder do ...@@ -10,6 +10,28 @@ defmodule Pleroma.Web.ActivityPub.Builder do
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
def create(actor, object_id, recipients) do
{:ok,
%{
"id" => Utils.generate_activity_id(),
"actor" => actor.ap_id,
"to" => recipients,
"object" => object_id,
"type" => "Create"
}, []}
end
def chat_message(actor, recipient, content) do
{:ok,
%{
"id" => Utils.generate_object_id(),
"actor" => actor.ap_id,
"type" => "ChatMessage",
"to" => [recipient],
"content" => content
}, []}
end
@spec like(User.t(), Object.t()) :: {:ok, map(), keyword()} @spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}
def like(actor, object) do def like(actor, object) do
object_actor = User.get_cached_by_ap_id(object.data["actor"]) object_actor = User.get_cached_by_ap_id(object.data["actor"])
......
...@@ -5,8 +5,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do ...@@ -5,8 +5,10 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
liked object, a `Follow` activity will add the user to the follower liked object, a `Follow` activity will add the user to the follower
collection, and so on. collection, and so on.
""" """
alias Pleroma.Chat
alias Pleroma.Notification alias Pleroma.Notification
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
def handle(object, meta \\ []) def handle(object, meta \\ [])
...@@ -21,8 +23,35 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do ...@@ -21,8 +23,35 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do
{:ok, object, meta} {:ok, object, meta}
end end
def handle(%{data: %{"type" => "Create", "object" => object_id}} = activity, meta) do
object = Object.get_by_ap_id(object_id)
{:ok, _object} = handle_object_creation(object)
{:ok, activity, meta}
end
# Nothing to do # Nothing to do
def handle(object, meta) do def handle(object, meta) do
{:ok, object, meta} {:ok, object, meta}
end end
def handle_object_creation(%{data: %{"type" => "ChatMessage"}} = object) do
actor = User.get_cached_by_ap_id(object.data["actor"])
recipient = User.get_cached_by_ap_id(hd(object.data["to"]))
[[actor, recipient], [recipient, actor]]
|> Enum.each(fn [user, other_user] ->
if user.local do
Chat.bump_or_create(user.id, other_user.ap_id)
end
end)
{:ok, object}
end
# Nothing to do
def handle_object_creation(object) do
{:ok, object}
end
end end
...@@ -14,7 +14,7 @@ test "it creates a chat for a user and recipient" do ...@@ -14,7 +14,7 @@ test "it creates a chat for a user and recipient" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
{:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
assert chat.id assert chat.id
end end
...@@ -23,19 +23,21 @@ test "it returns a chat for a user and recipient if it already exists" do ...@@ -23,19 +23,21 @@ test "it returns a chat for a user and recipient if it already exists" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
{:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
{:ok, chat_two} = Chat.get_or_create(user.id, other_user.ap_id) {:ok, chat_two} = Chat.bump_or_create(user.id, other_user.ap_id)
assert chat.id == chat_two.id assert chat.id == chat_two.id
end end
test "a returning chat will have an updated `update_at` field" do test "a returning chat will have an updated `update_at` field and an incremented unread count" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
{:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id) {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
assert chat.unread == 1
:timer.sleep(1500) :timer.sleep(1500)
{:ok, chat_two} = Chat.get_or_create(user.id, other_user.ap_id) {:ok, chat_two} = Chat.bump_or_create(user.id, other_user.ap_id)
assert chat_two.unread == 2
assert chat.id == chat_two.id assert chat.id == chat_two.id
assert chat.updated_at != chat_two.updated_at assert chat.updated_at != chat_two.updated_at
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
defmodule Pleroma.Web.ActivityPub.SideEffectsTest do defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
use Pleroma.DataCase use Pleroma.DataCase
alias Pleroma.Chat
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Builder
...@@ -31,4 +32,29 @@ test "add the like to the original object", %{like: like, user: user} do ...@@ -31,4 +32,29 @@ test "add the like to the original object", %{like: like, user: user} do
assert user.ap_id in object.data["likes"] assert user.ap_id in object.data["likes"]
end end
end end
describe "creation of ChatMessages" do
test "it creates a Chat for the local users and bumps the unread count" do
author = insert(:user, local: false)
recipient = insert(:user, local: true)
{:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
{:ok, chat_message_object} = Object.create(chat_message_data)
{:ok, create_activity_data, _meta} =
Builder.create(author, chat_message_object.data["id"], [recipient.ap_id])
{:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
{:ok, _create_activity, _meta} = SideEffects.handle(create_activity)
# The remote user won't get a chat
chat = Chat.get(author.id, recipient.ap_id)
refute chat
# The local user will get a chat
chat = Chat.get(recipient.id, author.ap_id)
assert chat
end
end
end end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment