wip
This commit is contained in:
parent
b3ee618e0d
commit
193c17cea5
88
lib/pleroma/media.ex
Normal file
88
lib/pleroma/media.ex
Normal file
@ -0,0 +1,88 @@
|
||||
defmodule Pleroma.Media do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.Media
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
@derive {Jason.Encoder,
|
||||
only: [:href, :type, :media_type, :name, :blurhash, :meta, :object_id, :user_id]}
|
||||
|
||||
@type t() :: %__MODULE__{}
|
||||
|
||||
schema "media" do
|
||||
field(:href, :string)
|
||||
field(:type, :string)
|
||||
field(:media_type, :string)
|
||||
field(:name, :string)
|
||||
field(:blurhash, :string)
|
||||
field(:meta, :map)
|
||||
|
||||
belongs_to(:object, Pleroma.Object)
|
||||
belongs_to(:user, Pleroma.User, type: FlakeId.Ecto.CompatType)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
def create_from_object_data(%{"url" => [url]} = data, %{user: user} = _opts) do
|
||||
%Media{}
|
||||
|> changeset(%{
|
||||
href: url["href"],
|
||||
type: url["type"],
|
||||
media_type: url["mediaType"],
|
||||
name: data["name"],
|
||||
blurhash: nil,
|
||||
meta: %{},
|
||||
user_id: user.id
|
||||
})
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
def get_by_id(nil), do: nil
|
||||
def get_by_id(id), do: Repo.get(Media, id)
|
||||
|
||||
@spec authorize_access(Media.t(), User.t()) :: :ok | {:error, :forbidden}
|
||||
def authorize_access(%Media{user_id: user_id}, %User{id: user_id}), do: :ok
|
||||
def authorize_access(%Media{user_id: user_id}, %User{id: user_id}), do: {:error, :forbidden}
|
||||
|
||||
def update(%Media{} = media, attrs \\ %{}) do
|
||||
media
|
||||
|> changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
def from_object(%Pleroma.Object{data: data}, %{user: user}) do
|
||||
%Media{href: data["href"], user_id: user.id}
|
||||
end
|
||||
|
||||
def insert(%Media{} = media) do
|
||||
media
|
||||
|> changeset()
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
def changeset(struct, params \\ %{}) do
|
||||
struct
|
||||
|> cast(params, [:href, :type, :media_type, :name, :blurhash, :meta, :user_id, :object_id])
|
||||
|> validate_required([:href, :type, :media_type])
|
||||
end
|
||||
|
||||
def to_object_form(%Media{} = media) do
|
||||
%{
|
||||
"id" => media.id,
|
||||
"url" => [
|
||||
%{
|
||||
"href" => media.href,
|
||||
"type" => media.type,
|
||||
"mediaType" => media.media_type
|
||||
}
|
||||
],
|
||||
"name" => media.name,
|
||||
"type" => "Document",
|
||||
"blurhash" => media.blurhash,
|
||||
"mediaType" => media.media_type
|
||||
}
|
||||
end
|
||||
end
|
@ -119,6 +119,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
{:fake, false, map, recipients} <- {:fake, fake, map, recipients},
|
||||
{:containment, :ok} <- {:containment, Containment.contain_child(map)},
|
||||
{:ok, map, object} <- insert_full_object(map),
|
||||
:ok <- maybe_update_media(object),
|
||||
{:ok, activity} <- insert_activity_with_expiration(map, local, recipients) do
|
||||
# Splice in the child object if we have one.
|
||||
activity = Maps.put_if_present(activity, :object, object)
|
||||
@ -161,6 +162,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_update_media(%Object{data: %{"attachment" => []}}), do: :ok
|
||||
|
||||
defp maybe_update_media(%Object{id: id, data: %{"attachment" => attachments}}) do
|
||||
Enum.each(attachments, fn %{"id" => media_id} ->
|
||||
media_id
|
||||
|> Pleroma.Media.get_by_id()
|
||||
|> Pleroma.Media.update(%{object_id: id})
|
||||
end)
|
||||
end
|
||||
|
||||
defp insert_activity_with_expiration(data, local, recipients) do
|
||||
struct = %Activity{
|
||||
data: data,
|
||||
@ -1190,10 +1201,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
|
||||
@spec upload(Upload.source(), keyword()) :: {:ok, Object.t()} | {:error, any()}
|
||||
def upload(file, opts \\ []) do
|
||||
with {:ok, data} <- Upload.store(file, opts) do
|
||||
obj_data = Maps.put_if_present(data, "actor", opts[:actor])
|
||||
|
||||
Repo.insert(%Object{data: obj_data})
|
||||
with {:ok, data} <- Upload.store(file, opts),
|
||||
%User{} <- opts[:user] do
|
||||
Pleroma.Media.create_from_object_data(data, %{user: opts[:user]})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Media
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
@ -37,8 +38,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
||||
|
||||
def attachments_from_ids_no_descs(ids) do
|
||||
Enum.map(ids, fn media_id ->
|
||||
case Repo.get(Object, media_id) do
|
||||
%Object{data: data} -> data
|
||||
case Repo.get(Media, media_id) do
|
||||
%Media{} = media -> Media.to_object_form(media)
|
||||
_ -> nil
|
||||
end
|
||||
end)
|
||||
@ -51,8 +52,9 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
||||
{_, descs} = Jason.decode(descs_str)
|
||||
|
||||
Enum.map(ids, fn media_id ->
|
||||
with %Object{data: data} <- Repo.get(Object, media_id) do
|
||||
Map.put(data, "name", descs[media_id])
|
||||
with %Media{} = media <- Repo.get(Media, media_id) do
|
||||
%Media{media | name: descs[media_id]}
|
||||
|> Media.to_object_form()
|
||||
end
|
||||
end)
|
||||
|> Enum.reject(&is_nil/1)
|
||||
|
@ -5,6 +5,7 @@
|
||||
defmodule Pleroma.Web.MastodonAPI.MediaController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.Media
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
@ -22,6 +23,20 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
|
||||
|
||||
@doc "POST /api/v1/media"
|
||||
def create(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do
|
||||
with {:ok, media} <-
|
||||
ActivityPub.upload(
|
||||
file,
|
||||
user: user,
|
||||
actor: User.ap_id(user),
|
||||
description: Map.get(data, :description)
|
||||
) do
|
||||
render(conn, "media.json", %{media: media})
|
||||
end
|
||||
end
|
||||
|
||||
def create(_conn, _data), do: {:error, :bad_request}
|
||||
|
||||
def _create(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do
|
||||
with {:ok, object} <-
|
||||
ActivityPub.upload(
|
||||
file,
|
||||
@ -34,7 +49,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
|
||||
end
|
||||
end
|
||||
|
||||
def create(_conn, _data), do: {:error, :bad_request}
|
||||
def _create(_conn, _data), do: {:error, :bad_request}
|
||||
|
||||
@doc "POST /api/v2/media"
|
||||
def create2(%{assigns: %{user: user}, body_params: %{file: file} = data} = conn, _) do
|
||||
@ -56,6 +71,18 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
|
||||
|
||||
@doc "PUT /api/v1/media/:id"
|
||||
def update(%{assigns: %{user: user}, body_params: %{description: description}} = conn, %{id: id}) do
|
||||
with %Media{} = media <- Media.get_by_id(id),
|
||||
:ok <- Media.authorize_access(media, user),
|
||||
{:ok, %Media{} = media} <- Media.update(media, %{"name" => description}) do
|
||||
render(conn, "media.json", %{media: media})
|
||||
end
|
||||
end
|
||||
|
||||
def update(conn, data), do: show(conn, data)
|
||||
|
||||
def _update(%{assigns: %{user: user}, body_params: %{description: description}} = conn, %{
|
||||
id: id
|
||||
}) do
|
||||
with %Object{} = object <- Object.get_by_id(id),
|
||||
:ok <- Object.authorize_access(object, user),
|
||||
{:ok, %Object{data: data}} <- Object.update_data(object, %{"name" => description}) do
|
||||
@ -65,10 +92,19 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
|
||||
end
|
||||
end
|
||||
|
||||
def update(conn, data), do: show(conn, data)
|
||||
def _update(conn, data), do: show(conn, data)
|
||||
|
||||
@doc "GET /api/v1/media/:id"
|
||||
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Pleroma.Media{} = media <- Pleroma.Media.get_by_id(id),
|
||||
:ok <- Pleroma.Media.authorize_access(media, user) do
|
||||
render(conn, "media.json", %{media: media})
|
||||
end
|
||||
end
|
||||
|
||||
def show(_conn, _data), do: {:error, :bad_request}
|
||||
|
||||
def _show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Object{data: data, id: object_id} = object <- Object.get_by_id(id),
|
||||
:ok <- Object.authorize_access(object, user) do
|
||||
attachment_data = Map.put(data, "id", object_id)
|
||||
@ -77,5 +113,5 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
|
||||
end
|
||||
end
|
||||
|
||||
def show(_conn, _data), do: {:error, :bad_request}
|
||||
def _show(_conn, _data), do: {:error, :bad_request}
|
||||
end
|
||||
|
@ -242,8 +242,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||
true -> CommonAPI.thread_muted?(opts[:for], activity)
|
||||
end
|
||||
|
||||
attachment_data = object.data["attachment"] || []
|
||||
attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment)
|
||||
attachment_data = object.data["attachments"] || []
|
||||
# attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment)
|
||||
attachments = render_many(attachment_data, StatusView, "media.json", as: :media)
|
||||
|
||||
created_at = Utils.to_masto_date(object.data["published"])
|
||||
|
||||
@ -436,6 +437,32 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||
}
|
||||
end
|
||||
|
||||
def render("media.json", %{media: media}) do
|
||||
media_type = media.media_type || media.mime_type || "image"
|
||||
href = MediaProxy.url(media.href)
|
||||
href_preview = MediaProxy.preview_url(media.href)
|
||||
|
||||
type =
|
||||
cond do
|
||||
String.contains?(media_type, "image") -> "image"
|
||||
String.contains?(media_type, "video") -> "video"
|
||||
String.contains?(media_type, "audio") -> "audio"
|
||||
true -> "unknown"
|
||||
end
|
||||
|
||||
%{
|
||||
id: to_string(media.id),
|
||||
url: href,
|
||||
remote_url: href,
|
||||
preview_url: href_preview,
|
||||
text_url: href,
|
||||
type: type,
|
||||
description: media.name,
|
||||
pleroma: %{mime_type: media_type},
|
||||
blurhash: media.blurhash
|
||||
}
|
||||
end
|
||||
|
||||
def render("context.json", %{activity: activity, activities: activities, user: user}) do
|
||||
%{ancestors: ancestors, descendants: descendants} =
|
||||
activities
|
||||
|
@ -46,6 +46,8 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do
|
||||
|
||||
config = Pleroma.Config.get(Pleroma.Upload)
|
||||
|
||||
# https://pleroma.local/media/cf61935ec407b4df8fd3dcf58352948eb6231bdfe12fcbf5270e653c20da9860.jpeg
|
||||
|
||||
with uploader <- Keyword.fetch!(config, :uploader),
|
||||
proxy_remote = Keyword.get(config, :proxy_remote, false),
|
||||
{:ok, get_method} <- uploader.get_file(file),
|
||||
|
19
priv/repo/migrations/20201125170429_create_media.exs
Normal file
19
priv/repo/migrations/20201125170429_create_media.exs
Normal file
@ -0,0 +1,19 @@
|
||||
defmodule Pleroma.Repo.Migrations.CreateMedia do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create_if_not_exists table(:media) do
|
||||
add(:href, :string, null: false)
|
||||
add(:type, :string, null: false)
|
||||
add(:media_type, :string, null: false)
|
||||
add(:name, :string)
|
||||
add(:blurhash, :string)
|
||||
add(:meta, :map)
|
||||
# TODO discuss delete_all option
|
||||
add(:object_id, references(:objects, on_delete: :nothing), null: true)
|
||||
add(:user_id, references(:users, type: :uuid, on_delete: :nothing), null: false)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user