1# This file is part of the musicbrainzngs library 2# Copyright (C) Alastair Porter, Wieland Hoffmann, and others 3# This file is distributed under a BSD-2-Clause type license. 4# See the COPYING file for more information. 5 6__all__ = [ 7 'set_caa_hostname', 'get_image_list', 'get_release_group_image_list', 8 'get_release_group_image_front', 'get_image_front', 'get_image_back', 9 'get_image' 10 ] 11 12import json 13 14from musicbrainzngs import compat 15from musicbrainzngs import musicbrainz 16from musicbrainzngs.util import _unicode 17 18hostname = "coverartarchive.org" 19https = True 20 21 22def set_caa_hostname(new_hostname, use_https=False): 23 """Set the base hostname for Cover Art Archive requests. 24 Defaults to 'coverartarchive.org', accessing over https. 25 For backwards compatibility, `use_https` is False by default. 26 27 :param str new_hostname: The hostname (and port) of the CAA server to connect to 28 :param bool use_https: `True` if the host should be accessed using https. Default is `False` 29""" 30 global hostname 31 global https 32 hostname = new_hostname 33 https = use_https 34 35 36def _caa_request(mbid, imageid=None, size=None, entitytype="release"): 37 """ Make a CAA request. 38 39 :param imageid: ``front``, ``back`` or a number from the listing obtained 40 with :meth:`get_image_list`. 41 :type imageid: str 42 43 :param size: "250", "500", "1200" 44 :type size: str or None 45 46 :param entitytype: ``release`` or ``release-group`` 47 :type entitytype: str 48 """ 49 # Construct the full URL for the request, including hostname and 50 # query string. 51 path = [entitytype, mbid] 52 if imageid and size: 53 path.append("%s-%s" % (imageid, size)) 54 elif imageid: 55 path.append(imageid) 56 url = compat.urlunparse(( 57 'https' if https else 'http', 58 hostname, 59 '/%s' % '/'.join(path), 60 '', 61 '', 62 '' 63 )) 64 musicbrainz._log.debug("GET request for %s" % (url, )) 65 66 # Set up HTTP request handler and URL opener. 67 httpHandler = compat.HTTPHandler(debuglevel=0) 68 handlers = [httpHandler] 69 70 opener = compat.build_opener(*handlers) 71 72 # Make request. 73 req = musicbrainz._MusicbrainzHttpRequest("GET", url, None) 74 # Useragent isn't needed for CAA, but we'll add it if it exists 75 if musicbrainz._useragent != "": 76 req.add_header('User-Agent', musicbrainz._useragent) 77 musicbrainz._log.debug("requesting with UA %s" % musicbrainz._useragent) 78 79 resp = musicbrainz._safe_read(opener, req, None) 80 81 # TODO: The content type declared by the CAA for JSON files is 82 # 'applicaiton/octet-stream'. This is not useful to detect whether the 83 # content is JSON, so default to decoding JSON if no imageid was supplied. 84 # http://tickets.musicbrainz.org/browse/CAA-75 85 if imageid: 86 # If we asked for an image, return the image 87 return resp 88 else: 89 # Otherwise it's json 90 data = _unicode(resp) 91 return json.loads(data) 92 93 94def get_image_list(releaseid): 95 """Get the list of cover art associated with a release. 96 97 The return value is the deserialized response of the `JSON listing 98 <http://musicbrainz.org/doc/Cover_Art_Archive/API#.2Frelease.2F.7Bmbid.7D.2F>`_ 99 returned by the Cover Art Archive API. 100 101 If an error occurs then a :class:`~musicbrainzngs.ResponseError` will 102 be raised with one of the following HTTP codes: 103 104 * 400: `Releaseid` is not a valid UUID 105 * 404: No release exists with an MBID of `releaseid` 106 * 503: Ratelimit exceeded 107 """ 108 return _caa_request(releaseid) 109 110 111def get_release_group_image_list(releasegroupid): 112 """Get the list of cover art associated with a release group. 113 114 The return value is the deserialized response of the `JSON listing 115 <http://musicbrainz.org/doc/Cover_Art_Archive/API#.2Frelease-group.2F.7Bmbid.7D.2F>`_ 116 returned by the Cover Art Archive API. 117 118 If an error occurs then a :class:`~musicbrainzngs.ResponseError` will 119 be raised with one of the following HTTP codes: 120 121 * 400: `Releaseid` is not a valid UUID 122 * 404: No release exists with an MBID of `releaseid` 123 * 503: Ratelimit exceeded 124 """ 125 return _caa_request(releasegroupid, entitytype="release-group") 126 127 128def get_release_group_image_front(releasegroupid, size=None): 129 """Download the front cover art for a release group. 130 The `size` argument and the possible error conditions are the same as for 131 :meth:`get_image`. 132 """ 133 return get_image(releasegroupid, "front", size=size, 134 entitytype="release-group") 135 136 137def get_image_front(releaseid, size=None): 138 """Download the front cover art for a release. 139 The `size` argument and the possible error conditions are the same as for 140 :meth:`get_image`. 141 """ 142 return get_image(releaseid, "front", size=size) 143 144 145def get_image_back(releaseid, size=None): 146 """Download the back cover art for a release. 147 The `size` argument and the possible error conditions are the same as for 148 :meth:`get_image`. 149 """ 150 return get_image(releaseid, "back", size=size) 151 152 153def get_image(mbid, coverid, size=None, entitytype="release"): 154 """Download cover art for a release. The coverart file to download 155 is specified by the `coverid` argument. 156 157 If `size` is not specified, download the largest copy present, which can be 158 very large. 159 160 If an error occurs then a :class:`~musicbrainzngs.ResponseError` 161 will be raised with one of the following HTTP codes: 162 163 * 400: `Releaseid` is not a valid UUID or `coverid` is invalid 164 * 404: No release exists with an MBID of `releaseid` 165 * 503: Ratelimit exceeded 166 167 :param coverid: ``front``, ``back`` or a number from the listing obtained with 168 :meth:`get_image_list` 169 :type coverid: int or str 170 171 :param size: "250", "500", "1200" or None. If it is None, the largest 172 available picture will be downloaded. If the image originally 173 uploaded to the Cover Art Archive was smaller than the 174 requested size, only the original image will be returned. 175 :type size: str or None 176 177 :param entitytype: The type of entity for which to download the cover art. 178 This is either ``release`` or ``release-group``. 179 :type entitytype: str 180 :return: The binary image data 181 :type: str 182 """ 183 if isinstance(coverid, int): 184 coverid = "%d" % (coverid, ) 185 if isinstance(size, int): 186 size = "%d" % (size, ) 187 return _caa_request(mbid, coverid, size=size, entitytype=entitytype) 188