Current section

Files

Jump to
wax lib models message_outbound_media.ex
Raw

lib/models/message_outbound_media.ex

defmodule Whatsapp.Models.MessageOutboundMedia do
@moduledoc """
Estructura del mensaje de Whatsapp
"""
require Logger
alias __MODULE__
@enforce_keys [:to, :type, :data, :file_name]
@default_values %{
caption: nil
}
defstruct(
to: nil,
type: nil,
file_name: nil,
caption: nil,
mime_type: nil,
data: nil,
extension: nil,
media_id: nil
)
@type t :: %__MODULE__{}
@doc """
Crea un mensaje nuevo
"""
@spec new(Keyword.t()) :: __MODULE__.t()
def new(options) do
attrs =
options
|> Enum.into(Map.new())
|> Map.merge(@default_values)
|> _add_extension_from_mime()
|> _add_caption()
|> _add_binary_data()
Kernel.struct(__MODULE__, attrs)
end
def set_media_id(media, media_id) do
%{media | media_id: media_id}
end
def validate(%MessageOutboundMedia{media_id: nil}) do
{:error, "Invalid media_id"}
end
def validate(message) do
{:ok, message}
end
def to_json(%__MODULE__{} = message) do
%{
recipient_type: "individual",
to: message.to,
type: message.type,
"#{message.type}": media_to_json(message)
}
end
# Genera la estructura del archivo media.
# No se envía caption si el tipo de archivo es audio o si es nulo
@spec media_to_json(__MODULE__.t()) :: map
defp media_to_json(%__MODULE__{type: "audio", media_id: media_id}) do
%{id: media_id}
end
defp media_to_json(%__MODULE__{caption: nil, media_id: media_id}) do
%{id: media_id}
end
defp media_to_json(%__MODULE__{caption: caption, media_id: media_id}) do
%{
id: media_id,
caption: caption
}
end
@doc """
Agrega el binario del archivo media al campo de data
"""
@spec _add_binary_data(map()) :: map()
def _add_binary_data(%{data: binary_data} = msg) when is_bitstring(binary_data) do
binary_data =
if String.starts_with?(binary_data, "data:") do
[_, binary_data] = String.split(binary_data, ",", parts: 2)
Base.decode64!(binary_data)
else
binary_data
end
%{msg | data: binary_data}
end
def _add_binary_data(_), do: {:error, "Invalid data"}
# Obtiene la extension del archivo a partir del mime_type
# El null (o vacío) a PDF es por un bug de Whatsapp
@spec _add_extension_from_mime(map()) :: map()
defp _add_extension_from_mime(%{mime_type: nil} = msg) do
Map.put(msg, :extension, "pdf")
end
defp _add_extension_from_mime(%{mime_type: mime_type} = msg) do
[_, extension] = Regex.run(~r/\/([a-z0-9]+)/, mime_type)
Map.put(msg, :extension, extension)
end
defp _add_extension_from_mime(msg) do
Map.put(msg, :extension, "pdf")
end
# Asigna el nombre del archivo como content para los mensajes media de tipo document
@spec _add_caption(map()) :: map()
def _add_caption(%{caption: caption, type: "document", file_name: file_name} = msg)
when caption in [nil, ""] do
Map.put(msg, :caption, file_name)
end
def _add_caption(%{caption: caption, type: "document", extension: extension} = msg) do
Map.put(msg, :caption, caption <> "." <> extension)
end
def _add_caption(%{caption: caption} = msg) do
Map.put(msg, :caption, caption)
end
def _add_caption(_) do
{:error, "Invalid caption"}
end
end