ChatMessages: Add attachments.

This commit is contained in:
lain 2020-05-06 16:12:36 +02:00
commit 20baa2eaf0
14 changed files with 237 additions and 24 deletions

View file

@ -23,17 +23,28 @@ defmodule Pleroma.Web.ActivityPub.Builder do
}, []}
end
def chat_message(actor, recipient, content) do
{:ok,
%{
"id" => Utils.generate_object_id(),
"actor" => actor.ap_id,
"type" => "ChatMessage",
"to" => [recipient],
"content" => content,
"published" => DateTime.utc_now() |> DateTime.to_iso8601(),
"emoji" => Emoji.Formatter.get_emoji_map(content)
}, []}
def chat_message(actor, recipient, content, opts \\ []) do
basic = %{
"id" => Utils.generate_object_id(),
"actor" => actor.ap_id,
"type" => "ChatMessage",
"to" => [recipient],
"content" => content,
"published" => DateTime.utc_now() |> DateTime.to_iso8601(),
"emoji" => Emoji.Formatter.get_emoji_map(content)
}
case opts[:attachment] do
%Object{data: attachment_data} ->
{
:ok,
Map.put(basic, "attachment", attachment_data),
[]
}
_ ->
{:ok, basic, []}
end
end
@spec like(User.t(), Object.t()) :: {:ok, map(), keyword()}

View file

@ -63,11 +63,18 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|> stringify_keys
end
def stringify_keys(object) do
def stringify_keys(object) when is_map(object) do
object
|> Map.new(fn {key, val} -> {to_string(key), val} end)
|> Map.new(fn {key, val} -> {to_string(key), stringify_keys(val)} end)
end
def stringify_keys(object) when is_list(object) do
object
|> Enum.map(&stringify_keys/1)
end
def stringify_keys(object), do: object
def fetch_actor(object) do
with {:ok, actor} <- Types.ObjectID.cast(object["actor"]) do
User.get_or_fetch_by_ap_id(actor)

View file

@ -0,0 +1,72 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
use Ecto.Schema
alias Pleroma.Web.ActivityPub.ObjectValidators.UrlObjectValidator
import Ecto.Changeset
@primary_key false
embedded_schema do
field(:type, :string)
field(:mediaType, :string)
field(:name, :string)
embeds_many(:url, UrlObjectValidator)
end
def cast_and_validate(data) do
data
|> cast_data()
|> validate_data()
end
def cast_data(data) do
%__MODULE__{}
|> changeset(data)
end
def changeset(struct, data) do
data =
data
|> fix_media_type()
|> fix_url()
struct
|> cast(data, [:type, :mediaType, :name])
|> cast_embed(:url, required: true)
end
def fix_media_type(data) do
data
|> Map.put_new("mediaType", data["mimeType"])
end
def fix_url(data) do
case data["url"] do
url when is_binary(url) ->
data
|> Map.put(
"url",
[
%{
"href" => url,
"type" => "Link",
"mediaType" => data["mediaType"]
}
]
)
_ ->
data
end
end
def validate_data(cng) do
cng
|> validate_required([:mediaType, :url, :type])
end
end

View file

@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator
import Ecto.Changeset
import Pleroma.Web.ActivityPub.Transmogrifier, only: [fix_emoji: 1]
@ -22,6 +23,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do
field(:actor, Types.ObjectID)
field(:published, Types.DateTime)
field(:emoji, :map, default: %{})
embeds_one(:attachment, AttachmentValidator)
end
def cast_and_apply(data) do
@ -51,7 +54,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do
data = fix(data)
struct
|> cast(data, __schema__(:fields))
|> cast(data, List.delete(__schema__(:fields), :attachment))
|> cast_embed(:attachment)
end
def validate_data(data_cng) do

View file

@ -0,0 +1,20 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.UrlObjectValidator do
use Ecto.Schema
alias Pleroma.Web.ActivityPub.ObjectValidators.Types
import Ecto.Changeset
@primary_key false
embedded_schema do
field(:type, :string)
field(:href, Types.Uri)
field(:mediaType, :string)
end
def changeset(struct, data) do
struct
|> cast(data, __schema__(:fields))
|> validate_required([:type, :href, :mediaType])
end
end

View file

@ -236,7 +236,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
description: "POST body for creating an chat message",
type: :object,
properties: %{
content: %Schema{type: :string, description: "The content of your message"}
content: %Schema{type: :string, description: "The content of your message"},
media_id: %Schema{type: :string, description: "The id of an upload"}
},
required: [:content],
example: %{

View file

@ -17,7 +17,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do
chat_id: %Schema{type: :string},
content: %Schema{type: :string},
created_at: %Schema{type: :string, format: :"date-time"},
emojis: %Schema{type: :array}
emojis: %Schema{type: :array},
attachment: %Schema{type: :object, nullable: true}
},
example: %{
"account_id" => "someflakeid",
@ -32,7 +33,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ChatMessage do
"url" => "https://dontbulling.me/emoji/Firefox.gif"
}
],
"id" => "14"
"id" => "14",
"attachment" => nil
}
})
end

View file

@ -25,14 +25,16 @@ defmodule Pleroma.Web.CommonAPI do
require Pleroma.Constants
require Logger
def post_chat_message(%User{} = user, %User{} = recipient, content) do
def post_chat_message(%User{} = user, %User{} = recipient, content, opts \\ []) do
with :ok <- validate_chat_content_length(content),
maybe_attachment <- opts[:media_id] && Object.get_by_id(opts[:media_id]),
{_, {:ok, chat_message_data, _meta}} <-
{:build_object,
Builder.chat_message(
user,
recipient.ap_id,
content |> Formatter.html_escape("text/plain")
content |> Formatter.html_escape("text/plain"),
attachment: maybe_attachment
)},
{_, {:ok, create_activity_data, _meta}} <-
{:build_create_activity, Builder.create(user, chat_message_data, [recipient.ap_id])},

View file

@ -36,14 +36,16 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.ChatOperation
def post_chat_message(
%{body_params: %{content: content}, assigns: %{user: %{id: user_id} = user}} = conn,
%{body_params: %{content: content} = params, assigns: %{user: %{id: user_id} = user}} =
conn,
%{
id: id
}
) do
with %Chat{} = chat <- Repo.get_by(Chat, id: id, user_id: user_id),
%User{} = recipient <- User.get_cached_by_ap_id(chat.recipient),
{:ok, activity} <- CommonAPI.post_chat_message(user, recipient, content),
{:ok, activity} <-
CommonAPI.post_chat_message(user, recipient, content, media_id: params[:media_id]),
message <- Object.normalize(activity) do
conn
|> put_view(ChatMessageView)

View file

@ -23,7 +23,10 @@ defmodule Pleroma.Web.PleromaAPI.ChatMessageView do
chat_id: chat_id |> to_string(),
account_id: User.get_cached_by_ap_id(chat_message["actor"]).id,
created_at: Utils.to_masto_date(chat_message["published"]),
emojis: StatusView.build_emojis(chat_message["emoji"])
emojis: StatusView.build_emojis(chat_message["emoji"]),
attachment:
chat_message["attachment"] &&
StatusView.render("attachment.json", attachment: chat_message["attachment"])
}
end