Packages

Get OEmbed URLs from a list of providers.

Current section

Files

Jump to
oembed_providers lib oembed_providers provider.ex
Raw

lib/oembed_providers/provider.ex

defmodule OEmbedProviders.Provider do
@moduledoc """
Represents an OEmbed provider.
"""
use OEmbedProviders.Parser
alias OEmbedProviders.Provider
alias OEmbedProviders.Provider.Endpoint
@type t :: %__MODULE__{
provider_name: String.t() | nil,
provider_url: String.t() | nil,
endpoints: [Endpoint.t()]
}
defstruct provider_name: nil, provider_url: nil, endpoints: []
@doc """
Convert a map into a `OEmbedProviders.Provider` struct.
"""
@spec from_map(data :: map()) :: Provider.t()
def from_map(data) when is_map(data) do
data = atomize_keys(data)
Provider
|> struct(data)
|> parse_endpoints()
end
defp parse_endpoints(%Provider{endpoints: endpoints} = provider) when is_list(endpoints) do
parsed = Enum.map(endpoints, &Endpoint.from_map/1)
Map.put(provider, :endpoints, parsed)
end
defp parse_endpoints(provider), do: provider
@doc """
Check if the given URL matches this `Provider`.
"""
@spec matches?(provider :: Provider.t(), url :: String.t()) :: boolean()
def matches?(%Provider{endpoints: endpoints}, url) when is_list(endpoints) do
Enum.any?(endpoints, &Endpoint.matches?(&1, url))
end
def matches?(_provider, _url), do: false
@doc """
Get the `OEmbedProviders.Provider.Endpoint` for a `Provider`.
"""
@spec find_endpoint(provider :: Provider.t(), url :: String.t()) :: Endpoint.t() | nil
def find_endpoint(%Provider{endpoints: endpoints}, url) when is_list(endpoints) do
Enum.find(endpoints, &Endpoint.matches?(&1, url))
end
def find_endpoint(_provider, _url), do: false
@doc """
Construct the OEmbed endpoint URL for the given `Provider` and URL.
"""
@spec oembed_url(provider :: Provider.t(), url :: String.t()) ::
{:ok, String.t()} | {:error, any()}
def oembed_url(%Provider{} = provider, url) do
format = "json"
params = %{"url" => url, "format" => format}
q = URI.encode_query(params)
with %Endpoint{url: endpoint_url} <- find_endpoint(provider, url) do
result =
endpoint_url
|> String.replace("*", URI.encode_www_form(url))
|> String.replace("{format}", URI.encode_www_form(format))
|> URI.merge("?#{q}")
|> URI.to_string()
{:ok, result}
else
nil -> {:error, :no_provider}
error -> {:error, error}
end
end
end