defmodule Remedy.CDN do
alias Sunbake.Snowflake
@cdn "https://cdn.discordapp.com"
@type uri :: String.t()
@moduledoc """
Discord CDN interface.
Storing images and other assets can be painful, use this module to retreive assets from the discord cdn rather than storing them.
Each function takes the required parameters to directly access a resource.
## Format
All images are returned as either a `.png` or a `.gif` if the asset is animated. This is done automatically.
## Size
Images can be requested of a size in `[16, 32, 64, 128, 256, 512, 1024, 2048, 4096]`. This is given as an optional final argument to any of the functions in this module. Arguments given will be rounded to the next largest, or the largest size if you try to go over.
Unless specified, discord will deliver the smallest size available. ( Potato )
"""
@typedoc """
The images size.
"""
@type size :: integer() | nil
@typedoc """
The snowflake id of the resource.
"""
@type snowflake :: Snowflake.t()
@typedoc """
The images hash.
"""
@type hash :: binary()
@typedoc """
A four digit integer assigned by discord to avoid duplicate usernames
"""
@type discriminator :: integer()
@doc """
Returns the url for a custom emoji.
"""
@spec custom_emoji(snowflake, size) :: binary
def custom_emoji(id, size \\ nil) do
"/emojis/#{id}" |> encode(id, size)
end
@doc """
Returns the url for a guilds icon.
## Examples
iex> Remedy.CDN.guild_icon(872417560094732328, "f817c5adaf96672c94a17de8e944f427")
"https://cdn.discordapp.com/icons/872417560094732328/f817c5adaf96672c94a17de8e944f427.png"
"""
@spec guild_icon(snowflake, hash, size) :: uri
def guild_icon(id, guild_icon, size \\ nil) do
"/icons/#{id}/#{guild_icon}" |> encode(guild_icon, size)
end
@doc """
Returns the url for a guilds splash.
## Examples
iex> Remedy.CDN.guild_splash(848619361782726696, "7ed6ea26b7a5e64f78ca5df202cf4d13")
"https://cdn.discordapp.com/splashes/848619361782726696/7ed6ea26b7a5e64f78ca5df202cf4d13.png"
"""
@spec guild_splash(snowflake, hash, size) :: uri
def guild_splash(id, splash, size \\ nil) do
"/splashes/#{id}/#{splash}"
|> encode(splash, size)
end
@doc """
Returns the url for a guilds discovery splash.
"""
@spec guild_discovery_splash(snowflake, hash, size) :: uri
def guild_discovery_splash(guild_id, guild_discovery_splash, size \\ nil) do
"/discovery-splashes/#{guild_id}/#{guild_discovery_splash}"
|> encode(guild_discovery_splash, size)
end
@doc """
Returns the url for a guilds banner.
"""
@spec guild_banner(snowflake, hash, size) :: uri
def guild_banner(guild_id, guild_banner, size) do
"/banners/#{guild_id}/#{guild_banner}"
|> encode(guild_banner, size)
end
@doc """
Returns the url for a users banner.
## Examples
iex> Remedy.CDN.user_banner(179255727561375744, "e625e858e48602248a69bcfdfa886ab4")
"https://cdn.discordapp.com/banners/179255727561375744/e625e858e48602248a69bcfdfa886ab4.png"
"""
@spec user_banner(snowflake, hash, size) :: uri
def user_banner(user_id, user_banner, size \\ nil) do
"/banners/#{user_id}/#{user_banner}"
|> encode(user_banner, size)
end
@doc """
Returns the url for the default avatar of a user.
That is, their avatar if they do not have one set, based on their discriminator. It can also take just the discriminator if you wish to do so.
## Examples
iex> Remedy.CDN.default_user_avatar(3)
"https://cdn.discordapp.com/embed/avatars/3.png"
"""
@spec default_user_avatar(discriminator, size) :: uri
def default_user_avatar(discriminator, size \\ nil) do
"/embed/avatars/#{rem(discriminator, 5)}"
|> encode(discriminator, size)
end
@doc """
Returns the url for the users avatar.
## Examples
iex> Remedy.CDN.user_avatar(707047919332884520, "1df05ae0f21a24c377e9a1051c2b6035", 128)
"https://cdn.discordapp.com/avatars/707047919332884520/1df05ae0f21a24c377e9a1051c2b6035.png?size=128"
"""
@spec user_avatar(snowflake, hash, size) :: uri
def user_avatar(id, user_avatar, size \\ nil) do
"/avatars/#{id}/#{user_avatar}"
|> encode(user_avatar, size)
end
@doc """
Returns the url for the applications icon.
"""
@spec application_icon(snowflake, hash, size) :: uri
def application_icon(application_id, icon, size \\ nil) do
"/app-icons/#{application_id}/#{icon}"
|> encode(icon, size)
end
@doc """
Returns an application cover url.
"""
@spec application_cover(snowflake, hash, size) :: uri
def application_cover(application_id, cover_image, size \\ nil) do
"/app-icons/#{application_id}/#{cover_image}"
|> encode(cover_image, size)
end
@doc """
Returns an application asset url.
"""
@spec application_asset(snowflake, hash, size) :: uri
def application_asset(application_id, asset_id, size \\ nil) do
"/app-assets/#{application_id}/#{asset_id}"
|> encode(asset_id, size)
end
@doc """
Returns an achievement icon url.
"""
@spec achievement_icon(snowflake, snowflake, hash, size) :: uri
def achievement_icon(application_id, achievement_id, icon_hash, size \\ nil) do
"/app-assets/#{application_id}/achievements/#{achievement_id}/icons/#{icon_hash}"
|> encode(icon_hash, size)
end
@doc """
Returns a sticker banner url.
"""
@spec sticker_pack_banner(snowflake, size) :: uri
def sticker_pack_banner(banner_asset_id, size) do
"/app-assets/710982414301790216/store/#{banner_asset_id}"
|> encode(banner_asset_id, size)
end
############
#### Private
############
defp encode(term, hash, size) do
(@cdn <> term)
|> put_extension(hash)
|> put_size(size)
|> URI.encode()
end
defp put_size(term, nil), do: term
defp put_size(term, size) when not is_integer(size), do: put_size(term, nil)
defp put_size(term, size) when size in [16, 32, 64, 128, 256, 512, 1024, 2048, 4096] do
term <> "?size=#{to_string(size)}"
end
defp put_size(term, size) when is_integer(size) and size < 16, do: put_size(term, 16)
defp put_size(term, size) when is_integer(size) and size < 32, do: put_size(term, 32)
defp put_size(term, size) when is_integer(size) and size < 64, do: put_size(term, 64)
defp put_size(term, size) when is_integer(size) and size < 128, do: put_size(term, 128)
defp put_size(term, size) when is_integer(size) and size < 256, do: put_size(term, 256)
defp put_size(term, size) when is_integer(size) and size < 512, do: put_size(term, 512)
defp put_size(term, size) when is_integer(size) and size < 1024, do: put_size(term, 1024)
defp put_size(term, size) when is_integer(size) and size < 2048, do: put_size(term, 2048)
defp put_size(term, size) when is_integer(size) and size > 4096, do: put_size(term, 4096)
defp put_extension(term, hash)
defp put_extension(term, "a_" <> _hash), do: term <> ".gif"
defp put_extension(term, _), do: term <> ".png"
end