79 lines
2.3 KiB
Elixir
79 lines
2.3 KiB
Elixir
defmodule Mobilizon.Federation.ActivityStream.Converter.Media do
|
|
@moduledoc """
|
|
Media converter.
|
|
|
|
This module allows to convert events from ActivityStream format to our own
|
|
internal one, and back.
|
|
"""
|
|
|
|
alias Mobilizon.Federation.ActivityStream
|
|
alias Mobilizon.Medias
|
|
alias Mobilizon.Medias.Media, as: MediaModel
|
|
alias Mobilizon.Service.HTTP.RemoteMediaDownloaderClient
|
|
alias Mobilizon.Web.Upload
|
|
|
|
@doc """
|
|
Convert a media struct to an ActivityStream representation.
|
|
"""
|
|
@spec model_to_as(MediaModel.t()) :: ActivityStream.t()
|
|
def model_to_as(%MediaModel{file: file}) do
|
|
%{
|
|
"type" => "Document",
|
|
"mediaType" => file.content_type,
|
|
"url" => file.url,
|
|
"name" => file.name
|
|
}
|
|
end
|
|
|
|
@doc """
|
|
Save media data from raw data and return AS Link data.
|
|
"""
|
|
@spec find_or_create_media(map(), String.t() | integer()) ::
|
|
{:ok, MediaModel.t()} | {:error, atom() | String.t() | Ecto.Changeset.t()}
|
|
def find_or_create_media(%{"type" => "Link", "href" => url}, actor_id),
|
|
do:
|
|
find_or_create_media(
|
|
%{"type" => "Document", "url" => url, "name" => "External media"},
|
|
actor_id
|
|
)
|
|
|
|
def find_or_create_media(
|
|
%{"type" => "Document", "url" => media_url, "name" => name},
|
|
actor_id
|
|
)
|
|
when is_binary(media_url) do
|
|
with {:ok, %{url: url} = uploaded} <- upload_media(media_url, name) do
|
|
case Medias.get_media_by_url(url) do
|
|
%MediaModel{file: _file} = media ->
|
|
{:ok, media}
|
|
|
|
nil ->
|
|
Medias.create_media(%{
|
|
file: Map.take(uploaded, [:url, :name, :content_type, :size]),
|
|
metadata: Map.take(uploaded, [:width, :height, :blurhash]),
|
|
actor_id: actor_id
|
|
})
|
|
end
|
|
end
|
|
end
|
|
|
|
@spec upload_media(String.t(), String.t()) :: {:ok, map()} | {:error, atom() | String.t()}
|
|
defp upload_media(media_url, ""), do: upload_media(media_url, "unknown")
|
|
|
|
defp upload_media(media_url, name) do
|
|
case RemoteMediaDownloaderClient.get(media_url) do
|
|
{:ok, %{body: body}} ->
|
|
case Upload.store(%{body: body, name: name}) do
|
|
{:ok, %{url: _url} = uploaded} ->
|
|
{:ok, uploaded}
|
|
|
|
{:error, err} ->
|
|
{:error, err}
|
|
end
|
|
|
|
{:error, err} ->
|
|
{:error, err}
|
|
end
|
|
end
|
|
end
|