Source code for groupy.api.attachments

from . import base
from groupy import utils


# use a class registry to enable factory creation of attachment objects
class AttachmentMeta(type):
    _types = {}

    def __init__(cls, name, bases, attrs):
        cls._types[name.lower()] = cls


[docs]class Attachment(base.Resource, metaclass=AttachmentMeta): """Base attachment class. Every attachment has a type and additional data. :param str type: attachment type :param kwargs data: additional attachment data """ def __init__(self, type, **data): data['type'] = type self.data = data
[docs] def to_json(self): """Return the attachment as JSON serializable dict. :return: serializable attachment data :rtype: dict """ return self.data
[docs] @classmethod def from_data(cls, type, **data): """Create an attachment from data. :param str type: attachment type :param kwargs data: additional attachment data :return: an attachment subclass object :rtype: `~groupy.api.attachments.Attachment` """ try: return cls._types[type](**data) except KeyError: return cls(type=type, **data)
[docs] @classmethod def from_bulk_data(cls, attachments): """Create multiple attachments from a list of attachment data. :return: attachment sublcass objects :rtype: :class:`list` """ return [cls.from_data(**a) for a in attachments]
[docs]class Location(Attachment): """A location attachment. :param float lat: latitude :param float lng: longitude :param str name: the name :param str foursqure_venue_id: an optional Foursquare venue ID """ def __init__(self, lat, lng, name, foursqure_venue_id=None): super().__init__(type='location', lat=lat, lng=lng, name=name, foursqure_venue_id=foursqure_venue_id)
[docs]class Split(Attachment): """A split attachment (deprecated in the API). :param str token: the split token """ def __init__(self, token): super().__init__(type='split', token=token)
[docs]class Emoji(Attachment): """An emoji attachment. :param str placeholder: the "stand-in" character for the emoji :param charmap: a list of 2-tuples specifying which emojis :type charmap: :class:`list` """ def __init__(self, placeholder, charmap): super().__init__(type='emoji', placeholder=placeholder, charmap=charmap)
[docs]class Mentions(Attachment): """A mentions attachment. :param loci: the start and end indices of one or more mentions :type loci: :class:`list` :param user_ids: the user_ids of one or more users mentioned :type user_ids: :class:`list` """ def __init__(self, loci=None, user_ids=None): loci = loci or [] user_ids = user_ids or [] super().__init__(type='mentions', loci=loci, user_ids=user_ids)
[docs]class Image(Attachment): """An image attachment. :param str url: the absolute URL for the image :param str source_url: an optional, absolute URL for the image source """ def __init__(self, url, source_url=None): super().__init__(type='image', url=url, source_url=source_url)
# this is documented nowhere :(
[docs]class LinkedImage(Image): pass
[docs]class Images(base.Manager): """A manager for handling image uploads/downloads.""" #: the base url for the pictures API base_url = 'https://image.groupme.com/'
[docs] def from_file(self, fp): """Create a new image attachment from an image file. :param file fp: a file object containing binary image data :return: an image attachment :rtype: :class:`~groupy.api.attachments.Image` """ image_urls = self.upload(fp) return Image(image_urls['url'], source_url=image_urls['picture_url'])
[docs] def upload(self, fp): """Upload image data to the image service. Call this, rather than :func:`from_file`, you don't want to create an attachment of the image. :param file fp: a file object containing binary image data :return: the URLs for the image uploaded :rtype: dict """ url = utils.urljoin(self.url, 'pictures') response = self.session.post(url, data=fp.read()) image_urls = response.data return image_urls
[docs] def download(self, image, url_field='url', suffix=None): """Download the binary data of an image attachment. :param image: an image attachment :type image: :class:`~groupy.api.attachments.Image` :param str url_field: the field of the image with the right URL :param str suffix: an optional URL suffix :return: binary image data :rtype: bytes """ url = getattr(image, url_field) if suffix is not None: url = '.'.join(url, suffix) response = self.session.get(url) return response.content
[docs] def download_preview(self, image, url_field='url'): """Downlaod the binary data of an image attachment at preview size. :param str url_field: the field of the image with the right URL :return: binary image data :rtype: bytes """ return self.download(image, url_field=url_field, suffix='preview')
[docs] def download_large(self, image, url_field='url'): """Downlaod the binary data of an image attachment at large size. :param str url_field: the field of the image with the right URL :return: binary image data :rtype: bytes """ return self.download(image, url_field=url_field, suffix='large')
[docs] def download_avatar(self, image, url_field='url'): """Downlaod the binary data of an image attachment at avatar size. :param str url_field: the field of the image with the right URL :return: binary image data :rtype: bytes """ return self.download(image, url_field=url_field, suffix='avatar')