Browse Source

avatar_url_as improvements

static_format will only apply to static (not animated) avatars. Makes
it easier to grab gif-or-'format' of an avatar. Defaults to 'webp'

This is for a similar usecase to avatar_url_as(format=None), except
one can specify the non-animated format, instead of always using
webp.

add User.avatar_is_animated property.

add validation for avatar_url_as, since invalid arguments result in
a url which will return 415, which can be confusing for a user. (They
just see a blank page)

Discord accepts size=16-2048, but images cap at 1024px, so accept 16-1024
Discord accepts "jpg", "jpeg", "png", "gif", and "webp", *unless* the
avatar is not animated, in which case "gif" is not supported. :\
pull/670/merge
khazhyk 8 years ago
committed by Rapptz
parent
commit
12ca0d9b16
  1. 42
      discord/user.py
  2. 4
      discord/utils.py

42
discord/user.py

@ -24,15 +24,18 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
""" """
from .utils import snowflake_time, _bytes_to_base64_data, parse_time from .utils import snowflake_time, _bytes_to_base64_data, parse_time, valid_icon_size
from .enums import DefaultAvatar, RelationshipType, UserFlags from .enums import DefaultAvatar, RelationshipType, UserFlags
from .errors import ClientException from .errors import ClientException, InvalidArgument
from collections import namedtuple from collections import namedtuple
import discord.abc import discord.abc
import asyncio import asyncio
VALID_STATIC_FORMATS = {"jpeg", "jpg", "webp", "png"}
VALID_AVATAR_FORMATS = VALID_STATIC_FORMATS | {"gif"}
class Profile(namedtuple('Profile', 'flags user mutual_guilds connected_accounts premium_since')): class Profile(namedtuple('Profile', 'flags user mutual_guilds connected_accounts premium_since')):
__slots__ = () __slots__ = ()
@ -96,22 +99,31 @@ class BaseUser(_BaseUser):
""" """
return self.avatar_url_as(format=None, size=1024) return self.avatar_url_as(format=None, size=1024)
def avatar_url_as(self, *, format, size=1024): @property
def avatar_is_animated(self):
"""Returns if the user has an animated avatar."""
return self.avatar and self.avatar.startswith('a_')
def avatar_url_as(self, *, format=None, static_format='webp', size=1024):
"""Returns a friendly URL version of the avatar the user has. """Returns a friendly URL version of the avatar the user has.
If the user does not have a traditional avatar, their default If the user does not have a traditional avatar, their default
avatar URL is returned instead. avatar URL is returned instead.
The format must be one of 'webp', 'jpeg', 'png' or 'gif'. The The format must be one of 'webp', 'jpeg', 'jpg', 'png' or 'gif', and
size must be a power of 2 (128, 256, 512, 1024). 'gif' is only valid for animated avatars. The size must be a power of 2
between 16 and 1024.
Parameters Parameters
----------- -----------
format: Optional[str] format: Optional[str]
The format to attempt to convert the avatar to. The format to attempt to convert the avatar to.
If the format is ``None``, then it is automatically If the format is ``None``, then it is automatically
detected into either 'gif' or 'webp' depending on the detected into either 'gif' or static_format depending on the
avatar being animated or not. avatar being animated or not.
static_format: 'str'
Format to attempt to convert only non-animated avatars to.
Defaults to 'webp'
size: int size: int
The size of the image to display. The size of the image to display.
@ -119,16 +131,30 @@ class BaseUser(_BaseUser):
-------- --------
str str
The resulting CDN URL. The resulting CDN URL.
Raises
------
InvalidArgument
Bad image format passed to ``format`` or ``static_format``, or
invalid ``size``.
""" """
if not valid_icon_size(size):
raise InvalidArgument("size must be a power of 2 between 16 and 1024")
if format is not None and format not in VALID_AVATAR_FORMATS:
raise InvalidArgument("format must be None or one of {}".format(VALID_AVATAR_FORMATS))
if format == "gif" and not self.avatar_is_animated:
raise InvalidArgument("non animated avatars do not support gif format")
if static_format not in VALID_STATIC_FORMATS:
raise InvalidArgument("static_format must be one of {}".format(VALID_STATIC_FORMATS))
if self.avatar is None: if self.avatar is None:
return self.default_avatar_url return self.default_avatar_url
if format is None: if format is None:
if self.avatar.startswith('a_'): if self.avatar_is_animated:
format = 'gif' format = 'gif'
else: else:
format = 'webp' format = static_format
return 'https://cdn.discordapp.com/avatars/{0.id}/{0.avatar}.{1}?size={2}'.format(self, format, size) return 'https://cdn.discordapp.com/avatars/{0.id}/{0.avatar}.{1}?size={2}'.format(self, format, size)

4
discord/utils.py

@ -281,3 +281,7 @@ def sane_wait_for(futures, *, timeout, loop):
if len(pending) != 0: if len(pending) != 0:
raise asyncio.TimeoutError() raise asyncio.TimeoutError()
def valid_icon_size(size):
"""Icons must be power of 2 within [16, 1024]."""
return ((size != 0) and not (size & (size - 1))) and size in range(16, 1025)

Loading…
Cancel
Save