Exemple #1
0
def findArtist(name, limit=1):

	with mb_lock:
	
		artistlist = []
		attempt = 0
		artistResults = None
		
		chars = set('!?*')
		if any((c in chars) for c in name):
			name = '"'+name+'"'
			
		q, sleepytime = startmb()
		
		while attempt < 5:
		
			try:
				artistResults = q.getArtists(ws.ArtistFilter(query=name, limit=limit))
				break
			except WebServiceError, e:
				logger.warn('Attempt to query MusicBrainz for %s failed: %s [%s:%i]' % (name, e, mbhost, mbport))
				attempt += 1
				time.sleep(5)
		
		time.sleep(sleepytime)
		
		if not artistResults:
			return False		
		
		for result in artistResults:
		
			if result.artist.name != result.artist.getUniqueName() and limit == 1:
				
				logger.debug('Found an artist with a disambiguation: %s - doing an album based search' % name)
				artistdict = findArtistbyAlbum(name)
				
				if not artistdict:
					logger.debug('Cannot determine the best match from an artist/album search. Using top match instead')
					artistlist.append({
						'name': 			result.artist.name,
						'uniquename':		result.artist.getUniqueName(),
						'id':				u.extractUuid(result.artist.id),
						'url': 				result.artist.id,
						'score':			result.score
						})
					
				else:
					artistlist.append(artistdict)
			
			else:
				artistlist.append({
						'name': 			result.artist.name,
						'uniquename':		result.artist.getUniqueName(),
						'id':				u.extractUuid(result.artist.id),
						'url': 				result.artist.id,
						'score':			result.score
						})
			
		return artistlist
Exemple #2
0
def getRelease(releaseid):
	"""
	Deep release search to get track info
	"""
	with mb_lock:
	
		release = {}
	
		inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True)
		results = None
		attempt = 0
			
		while attempt < 5:
		
			try:
				results = q.getReleaseById(releaseid, inc)
				break
			except WebServiceError, e:
				logger.warn('Attempt to retrieve information from MusicBrainz for release "%s" failed: %s. SLeeping 5 seconds' % (releaseid, e))
				attempt += 1
				time.sleep(5)	
		
		if not results:
			return False
		
		time.sleep(1)
		
		release['title'] = results.title
		release['id'] = u.extractUuid(results.id)
		release['asin'] = results.asin
		release['date'] = results.getEarliestReleaseDate()
		
		tracks = []
		
		i = 1
		for track in results.tracks:
			tracks.append({
					'number':		i,
					'title':		track.title,
					'id':			u.extractUuid(track.id),
					'url':			track.id,
					'duration':		track.duration
					})
			i += 1
			
		release['tracks'] = tracks
		
		return release
def addReleases(artist_id, update_artist = True):
  artist_record = Artist.get(id=artist_id)
  musicbrainz_artist = musicbrainz.getBestArtistMatch(artist_record.name)
  release_ids = []

  for release in musicbrainz_artist.getReleases():
    release_ids.append(utils.extractUuid(release.id))

  # These release results do not contain all the information, we must re-query for that info...
  for rid in release_ids:
    release = musicbrainz.getRelease(rid)

    if not release: continue

    release_group_id = utils.extractUuid(release.getReleaseGroup().id)

    try:
      release_group_tracked = Album.get(release_group_id=release_group_id)
    except peewee.DoesNotExist:
      release_group_tracked = None

    if release_group_tracked: continue

    release_record = Album.create(
        musicbrainz_id = rid,
        asin = release.getAsin(),
        release_group_id = release_group_id,
        artist_id = artist_id,
        name = release.getTitle(),
        type = release.getType(),
        released_on = release.getEarliestReleaseDate(),
        state = 'wanted')

    track_number = 1

    for track in release.getTracks():
      Track.create(
          album_id = release_record.id,
          number = track_number,
          title = track.getTitle(),
          length = track.getDuration(),
          state = 'wanted')

      track_number += 1

  # Rescan the Music Library after adding new releases to see if the user has 
  # them or not. Will not run if explicitly told not to by the caller.
  if(update_artist): ThreadPool.put(updateArtist, {'artist_id': artist_id})
	def submitPuids(self, tracks2puids):
		"""Submit track to PUID mappings.

		The C{tracks2puids} parameter has to be a dictionary, with the
		keys being MusicBrainz track IDs (either as absolute URIs or
		in their 36 character ASCII representation) and the values
		being PUIDs (ASCII, 36 characters).

		Note that this method only works if a valid user name and
		password have been set. See the example in L{Query} on how
		to supply authentication data.

		@param tracks2puids: a dictionary mapping track IDs to PUIDs

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid track or PUIDs
		@raise AuthenticationError: invalid user name and/or password
		"""
		assert self._clientId is not None, 'Please supply a client ID'
		params = [ ]
		params.append( ('client', self._clientId.encode('utf-8')) )

		for (trackId, puid) in tracks2puids.iteritems():
			trackId = mbutils.extractUuid(trackId, 'track')
			params.append( ('puid', trackId + ' ' + puid) )

		encodedStr = urllib.urlencode(params, True)

		self._ws.post('track', '', encodedStr)
	def submitUserTags(self, entityUri, tags):
		"""Submit folksonomy tags for an entity.

		Note that all previously existing tags from the authenticated
		user are replaced with the ones given to this method. Other
		users' tags are not affected.
		
		@param entityUri: a string containing an absolute MB ID
		@param tags: A list of either L{Tag <musicbrainz2.model.Tag>} objects
		             or strings

		@raise ValueError: invalid entityUri
		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID, entity or tags
		@raise AuthenticationError: invalid user name and/or password
		"""
		entity = mbutils.extractEntityType(entityUri)
		uuid = mbutils.extractUuid(entityUri, entity)
		params = (
			('type', 'xml'),
			('entity', entity),
			('id', uuid),
			('tags', ','.join([unicode(tag).encode('utf-8') for tag in tags]))
		)

		encodedStr = urllib.urlencode(params)

		self._ws.post('tag', '', encodedStr)
def getBestArtistMatch(artist_name):
  with mb_lock:
    attempt = 0

    if any((c in set('!?*')) for c in artist_name):
      artist_name = '"' + artist_name + '"'

    while attempt < 10:
      try:
        artist_results = query.getArtists(webservice.ArtistFilter(query=artist_name, limit=1))

        if artist_results:
          includes = webservice.ArtistIncludes(releases=(model.Release.TYPE_ALBUM, model.Release.TYPE_OFFICIAL))
          artist = artist_results[0].artist

          # Unfortunately, the search results do not contain release information, we have to query again for it...
          return query.getArtistById(utils.extractUuid(artist.id), includes)
        else:
          return None

        break
      except WebServiceError, e:
        logger.error('Attempt to query MusicBrainz for Artist %s failed: %s. Retrying in 10 seconds...' % (artist_name, e))
        attempt += 1
        time.sleep(10)
	def getUserRating(self, entityUri):
		"""Return the rating a user has applied to an entity.

		The given parameter has to be a fully qualified MusicBrainz
		ID, as returned by other library functions.
		
		Note that this method only works if a valid user name and
		password have been set. Only the rating the authenticated user
		applied to the entity will be returned. If username and/or
		password are incorrect, an AuthenticationError is raised.
		
		This method will return a L{Rating <musicbrainz2.model.Rating>}
		object.
		
		@param entityUri: a string containing an absolute MB ID
		
		@raise ValueError: invalid entityUri
  		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or entity
		@raise AuthenticationError: invalid user name and/or password
		"""
		entity = mbutils.extractEntityType(entityUri)
		uuid = mbutils.extractUuid(entityUri, entity)
		params = { 'entity': entity, 'id': uuid }
		
		stream = self._ws.get('rating', '', filter=params)
		try:
			parser = MbXmlParser()
			result = parser.parse(stream)
		except ParseError, e:
			raise ResponseError(str(e), e)
Exemple #8
0
def findArtist(name, limit=1):

	with mb_lock:

		artistlist = []
		attempt = 0
		
		while attempt < 5:
		
			try:
				artistResults = q.getArtists(ws.ArtistFilter(query=name, limit=limit))
				break
			except WebServiceError, e:
				logger.warn('Attempt to retrieve information from MusicBrainz failed: %s' % e)
				attempt += 1
				time.sleep(1)
		
		time.sleep(1)
		
		for result in artistResults:
			
			artistlist.append({
					'name': 			result.artist.name,
					'uniquename':		result.artist.getUniqueName(),
					'id':				u.extractUuid(result.artist.id),
					'url': 				result.artist.id,
					'score':			result.score
					})
			
		return artistlist
	def submitUserRating(self, entityUri, rating):
		"""Submit rating for an entity.

		Note that all previously existing rating from the authenticated
		user are replaced with the one given to this method. Other
		users' ratings are not affected.
		
		@param entityUri: a string containing an absolute MB ID
		@param rating: A L{Rating <musicbrainz2.model.Rating>} object
		             or integer

		@raise ValueError: invalid entityUri
		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID, entity or tags
		@raise AuthenticationError: invalid user name and/or password
		"""
		entity = mbutils.extractEntityType(entityUri)
		uuid = mbutils.extractUuid(entityUri, entity)
		params = (
			('type', 'xml'),
			('entity', entity),
			('id', uuid),
			('rating', unicode(rating).encode('utf-8'))
		)

		encodedStr = urllib.urlencode(params)

		self._ws.post('rating', '', encodedStr)
	def submitISRCs(self, tracks2isrcs):
		"""Submit track to ISRC mappings.

		The C{tracks2isrcs} parameter has to be a dictionary, with the
		keys being MusicBrainz track IDs (either as absolute URIs or
		in their 36 character ASCII representation) and the values
		being ISRCs (ASCII, 12 characters).

		Note that this method only works if a valid user name and
		password have been set. See the example in L{Query} on how
		to supply authentication data.

		@param tracks2isrcs: a dictionary mapping track IDs to ISRCs

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid track or ISRCs
		@raise AuthenticationError: invalid user name and/or password
		"""
		params = [ ]

		for (trackId, isrc) in tracks2isrcs.iteritems():
			trackId = mbutils.extractUuid(trackId, 'track')
			params.append( ('isrc', trackId + ' ' + isrc) )

		encodedStr = urllib.urlencode(params, True)

		self._ws.post('track', '', encodedStr)
	def __init__(self, title=None, discId=None, releaseTypes=None,
			artistName=None, artistId=None, limit=None,
			offset=None, query=None, trackCount=None):
		"""Constructor.

		If C{discId} or C{artistId} are set, only releases matching
		those IDs are returned. The C{releaseTypes} parameter allows
		to limit the types of the releases returned. You can set it to
		C{(Release.TYPE_ALBUM, Release.TYPE_OFFICIAL)}, for example,
		to only get officially released albums. Note that those values
		are connected using the I{AND} operator. MusicBrainz' support
		is currently very limited, so C{Release.TYPE_LIVE} and
		C{Release.TYPE_COMPILATION} exclude each other (see U{the
		documentation on release attributes
		<http://wiki.musicbrainz.org/AlbumAttribute>} for more
		information and all valid values).

		If both the C{artistName} and the C{artistId} parameter are
		given, the server will ignore C{artistName}.

		The C{query} parameter may contain a query in U{Lucene syntax
		<http://lucene.apache.org/java/docs/queryparsersyntax.html>}.
		Note that C{query} may not be used together with the other
		parameters except for C{limit} and C{offset}.

		@param title: a unicode string containing the release's title
		@param discId: a unicode string containing the DiscID
		@param releaseTypes: a sequence of release type URIs
		@param artistName: a unicode string containing the artist's name
		@param artistId: a unicode string containing the artist's ID
		@param limit: the maximum number of releases to return
		@param offset: start results at this zero-based offset
		@param query: a string containing a query in Lucene syntax
		@param trackCount: the number of tracks in the release

		@see: the constants in L{musicbrainz2.model.Release}
		"""
		if releaseTypes is None or len(releaseTypes) == 0:
			releaseTypesStr = None
		else:
			tmp = [ mbutils.extractFragment(x) for x in releaseTypes ]
			releaseTypesStr = ' '.join(tmp)

		self._params = [
			('title', title),
			('discid', discId),
			('releasetypes', releaseTypesStr),
			('artist', artistName),
			('artistid', mbutils.extractUuid(artistId)),
			('limit', limit),
			('offset', offset),
			('query', query),
			('count', trackCount),
		]

		if not _paramsValid(self._params):
			raise ValueError('invalid combination of parameters')
	def __init__(self, title=None, artistName=None, artistId=None,
			releaseTitle=None, releaseId=None,
			duration=None, puid=None, limit=None, offset=None,
			query=None):
		"""Constructor.

		If C{artistId}, C{releaseId} or C{puid} are set, only tracks
		matching those IDs are returned.

		The server will ignore C{artistName} and C{releaseTitle} if
		C{artistId} or ${releaseId} are set respectively.

		The C{query} parameter may contain a query in U{Lucene syntax
		<http://lucene.apache.org/java/docs/queryparsersyntax.html>}.
		Note that C{query} may not be used together with the other
		parameters except for C{limit} and C{offset}.

		@param title: a unicode string containing the track's title
		@param artistName: a unicode string containing the artist's name
		@param artistId: a string containing the artist's ID
		@param releaseTitle: a unicode string containing the release's title
		@param releaseId: a string containing the release's title
		@param duration: the track's length in milliseconds
		@param puid: a string containing a PUID
		@param limit: the maximum number of releases to return
		@param offset: start results at this zero-based offset
		@param query: a string containing a query in Lucene syntax
		"""
		self._params = [
			('title', title),
			('artist', artistName),
			('artistid', mbutils.extractUuid(artistId)),
			('release', releaseTitle),
			('releaseid', mbutils.extractUuid(releaseId)),
			('duration', duration),
			('puid', puid),
			('limit', limit),
			('offset', offset),
			('query', query),
		]

		if not _paramsValid(self._params):
			raise ValueError('invalid combination of parameters')
Exemple #13
0
def findRelease(name, limit=1):

    with mb_lock:

        releaselist = []
        attempt = 0
        releaseResults = None

        chars = set('!?')
        if any((c in chars) for c in name):
            name = '"' + name + '"'

        while attempt < 5:

            try:
                releaseResults = q.getReleases(
                    ws.ReleaseFilter(query=name, limit=limit))
                break
            except WebServiceError, e:
                logger.warn('Attempt to query MusicBrainz for %s failed: %s' %
                            (name, e))
                attempt += 1
                time.sleep(5)

        time.sleep(1)

        if not releaseResults:
            return False

        for result in releaseResults:

            releaselist.append({
                'uniquename': result.release.artist.name,
                'title': result.release.title,
                'id': u.extractUuid(result.release.artist.id),
                'albumid': u.extractUuid(result.release.id),
                'url': result.release.artist.id,
                'albumurl': result.release.id,
                'score': result.score
            })

        return releaselist
Exemple #14
0
def findRelease(name, limit=1):

	with mb_lock:
	
		releaselist = []
		attempt = 0
		releaseResults = None
		
		chars = set('!?')
		if any((c in chars) for c in name):
			name = '"'+name+'"'
			
		q, sleepytime = startmb()
		
		while attempt < 5:
		
			try:
				releaseResults = q.getReleases(ws.ReleaseFilter(query=name, limit=limit))
				break
			except WebServiceError, e:
				logger.warn('Attempt to query MusicBrainz for %s failed: %s' % (name, e))
				attempt += 1
				time.sleep(5)
		
		time.sleep(sleepytime)
		
		if not releaseResults:
			return False		
		
		for result in releaseResults:
			
			releaselist.append({
						'uniquename':		result.release.artist.name,
						'title': 			result.release.title,
						'id':				u.extractUuid(result.release.artist.id),
						'albumid':			u.extractUuid(result.release.id),
						'url': 				result.release.artist.id,
						'albumurl':			result.release.id,
						'score':			result.score
						})
			
		return releaselist
Exemple #15
0
def findRelease(name, limit=1):

    with mb_lock:

        releaselist = []
        attempt = 0
        releaseResults = None

        chars = set("!?")
        if any((c in chars) for c in name):
            name = '"' + name + '"'

        while attempt < 5:

            try:
                releaseResults = q.getReleases(ws.ReleaseFilter(query=name, limit=limit))
                break
            except WebServiceError, e:
                logger.warn("Attempt to query MusicBrainz for %s failed: %s" % (name, e))
                attempt += 1
                time.sleep(5)

        time.sleep(1)

        if not releaseResults:
            return False

        for result in releaseResults:

            releaselist.append(
                {
                    "uniquename": result.release.artist.name,
                    "title": result.release.title,
                    "id": u.extractUuid(result.release.artist.id),
                    "albumid": u.extractUuid(result.release.id),
                    "url": result.release.artist.id,
                    "albumurl": result.release.id,
                    "score": result.score,
                }
            )

        return releaselist
Exemple #16
0
def getReleaseGroup(rgid):
	"""
	Returns the best release out of any given release group
	"""
	with mb_lock:
	
		releaselist = []
		
		inc = ws.ReleaseGroupIncludes(releases=True)
		
		attempt = 0
		
		while attempt < 5:
		
			try:
				releaseGroup = q.getReleaseGroupById(rgid, inc)
				break
			except WebServiceError, e:
				logger.warn('Attempt to retrieve information from MusicBrainz failed: %s' % e)
				attempt += 1
				time.sleep(1)
	
		time.sleep(1)
		# I think for now we have to make separate queries for each release, in order
		# to get more detailed release info (ASIN, track count, etc.)
		for release in releaseGroup.releases:
	
			inc = ws.ReleaseIncludes(tracks=True)		
	
			attempt = 0
			
			while attempt < 5:
			
				try:
					releaseResult = q.getReleaseById(release.id, inc)
					break
				except WebServiceError, e:
					logger.warn('Attempt to retrieve information for %s from MusicBrainz failed: %s' % (releaseResult.title, e))
					attempt += 1
					time.sleep(1)		
			
			if not releaseResult:
				continue
				
			time.sleep(1)
			
			release_dict = {
				'asin':			bool(releaseResult.asin),
				'tracks':		len(releaseResult.getTracks()),
				'releaseid':	u.extractUuid(releaseResult.id)
				}
			
			releaselist.append(release_dict)
	def removeFromUserCollection(self, releases):
		"""Remove releases from a user's collection.

		The releases parameter must be a list. It can contain either L{Release}
		objects or a string representing a MusicBrainz release ID (either as
		absolute URIs or in their 36 character ASCII representation).

		Removing a release that is not in the collection has no effect.

		@param releases: a list of releases to remove from the user collection

		@raise ConnectionError: couldn't connect to server
		@raise AuthenticationError: invalid user name and/or password
		"""
		rels = []
		for release in releases:
			if isinstance(release, Release):
				rels.append(mbutils.extractUuid(release.id))
			else:
				rels.append(mbutils.extractUuid(release))
		encodedStr = urllib.urlencode({'remove': ",".join(rels)}, True)
		self._ws.post('collection', '', encodedStr)
Exemple #18
0
def findArtist(name, limit=1):

	with mb_lock:
	
		artistlist = []
		attempt = 0
		artistResults = None
		
		chars = set('!?')
		if any((c in chars) for c in name):
			name = '"'+name+'"'
		
		while attempt < 5:
		
			try:
				artistResults = q.getArtists(ws.ArtistFilter(query=name, limit=limit))
				break
			except WebServiceError, e:
				logger.warn('Attempt to query MusicBrainz for %s failed: %s' % (name, e))
				attempt += 1
				time.sleep(5)
		
		time.sleep(1)
		
		if not artistResults:
			return False		
		
		for result in artistResults:
		
			if result.artist.name != result.artist.getUniqueName() and limit == 1:
				
				logger.info('Found an artist with a disambiguation: %s - doing an album based search' % name)
				artistdict = findArtistbyAlbum(name)
				
				if not artistdict:
					return False
					
				else:
					artistlist.append(artistdict)
			
			else:
				artistlist.append({
						'name': 			result.artist.name,
						'uniquename':		result.artist.getUniqueName(),
						'id':				u.extractUuid(result.artist.id),
						'url': 				result.artist.id,
						'score':			result.score
						})
			
		return artistlist
Exemple #19
0
def getArtist(artistid):

	with mb_lock:
	
		artist_dict = {}
	
		#Get all official release groups
		inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
		
		attempt = 0
		
		while attempt < 5:
		
			try:
				artist = q.getArtistById(artistid, inc)
				break
			except WebServiceError, e:
				logger.warn('Attempt to retrieve information from MusicBrainz failed: %s' % e)
				attempt += 1
				time.sleep(1)
				
		time.sleep(1)
				
		artist_dict['artist_name'] = artist.name
		artist_dict['artist_sortname'] = artist.sortName
		artist_dict['artist_uniquename'] = artist.getUniqueName()
		artist_dict['artist_type'] = u.extractFragment(artist.type)
		artist_dict['artist_begindate'] = artist.beginDate
		artist_dict['artist_endDate'] = artist.endDate
		
		releasegroups = []
		
		for rg in artist.getReleaseGroups():
			
			releasegroups.append({
						'title':		rg.title,
						'id':			u.extractUuid(rg.id),
						'url':			rg.id,
						'type':			u.getReleaseTypeName(rg.type)
				})
				
		artist_dict['releasegroups'] = releasegroups
		
		return artist_dict
	def getLabelById(self, id_, include=None):
		"""Returns a L{model.Label}
		
		If no label with that ID can be found, or there is a server problem,
		an exception is raised.
		
		@param id_: a string containing the label's ID.

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or include tags
		@raise ResourceNotFoundError: release doesn't exist
		@raise ResponseError: server returned invalid data
		"""
		uuid = mbutils.extractUuid(id_, 'label')
		result = self._getFromWebService('label', uuid, include)
		label = result.getLabel()
		if label is not None:
			return label
		else:
			raise ResponseError("server didn't return a label")
Exemple #21
0
def getExtras(artistid):

	types = [m.Release.TYPE_EP, m.Release.TYPE_SINGLE, m.Release.TYPE_LIVE, m.Release.TYPE_REMIX,
			m.Release.TYPE_COMPILATION]
			
	for type in types:
	
		inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, type), releaseGroups=True)
		artist = q.getArtistById(artistid, inc)
		
		for rg in artist.getReleaseGroups():
		
			rgid = u.extractUuid(rg.id)
			releaseid = getReleaseGroup(rgid)
			
			inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True)
			results = ws.Query().getReleaseById(releaseid, inc)
			
			print results.title
			print u.getReleaseTypeName(results.releaseGroup.type)
def addArtist(id3_artist_name, path):
  musicbrainz_artist = musicbrainz.getBestArtistMatch(id3_artist_name)

  if musicbrainz_artist is None:
    unique_name = id3_artist_name
    artist_mb_id = None
  else:
    unique_name = musicbrainz_artist.getUniqueName()
    artist_mb_id = utils.extractUuid(musicbrainz_artist.id)

  try:
    artist = Artist.get(peewee.Q(musicbrainz_id=artist_mb_id) | peewee.Q(unique_name=unique_name))
  except peewee.DoesNotExist:
    artist = Artist.create(
        name = id3_artist_name,
        unique_name = unique_name,
        location = path,
        state = 'wanted',
        musicbrainz_id = artist_mb_id)

  return artist
	def getReleaseGroupById(self, id_, include=None):
		"""Returns a release group.

		If no release group with that ID can be found, C{include}
		contains invalid tags, or there's a server problem, an
		exception is raised.

		@param id_: a string containing the release group's ID
		@param include: a L{ReleaseGroupIncludes} object, or None

		@return: a L{ReleaseGroup <musicbrainz2.model.ReleaseGroup>} object, or None

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or include tags
		@raise ResourceNotFoundError: release doesn't exist
		@raise ResponseError: server returned invalid data
		"""
		uuid = mbutils.extractUuid(id_, 'release-group')
		result = self._getFromWebService('release-group', uuid, include)
		releaseGroup = result.getReleaseGroup()
		if releaseGroup is not None:
			return releaseGroup
		else:
			raise ResponseError("server didn't return releaseGroup")
	def getArtistById(self, id_, include=None):
		"""Returns an artist.

		If no artist with that ID can be found, C{include} contains
		invalid tags or there's a server problem, an exception is
		raised.

		@param id_: a string containing the artist's ID
		@param include: an L{ArtistIncludes} object, or None

		@return: an L{Artist <musicbrainz2.model.Artist>} object, or None

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or include tags
		@raise ResourceNotFoundError: artist doesn't exist
		@raise ResponseError: server returned invalid data
		"""
		uuid = mbutils.extractUuid(id_, 'artist')
		result = self._getFromWebService('artist', uuid, include)
		artist = result.getArtist()
		if artist is not None:
			return artist
		else:
			raise ResponseError("server didn't return artist")
	def getTrackById(self, id_, include=None):
		"""Returns a track.

		If no track with that ID can be found, C{include} contains
		invalid tags or there's a server problem, an exception is
		raised.

		@param id_: a string containing the track's ID
		@param include: a L{TrackIncludes} object, or None

		@return: a L{Track <musicbrainz2.model.Track>} object, or None

		@raise ConnectionError: couldn't connect to server
		@raise RequestError: invalid ID or include tags
		@raise ResourceNotFoundError: track doesn't exist
		@raise ResponseError: server returned invalid data
		"""
		uuid = mbutils.extractUuid(id_, 'track')
		result = self._getFromWebService('track', uuid, include)
		track = result.getTrack()
		if track is not None:
			return track
		else:
			raise ResponseError("server didn't return track")
Exemple #26
0
def findArtist(name, limit=1):

    with mb_lock:

        artistlist = []
        attempt = 0
        artistResults = None

        chars = set("!?*")
        if any((c in chars) for c in name):
            name = '"' + name + '"'

        while attempt < 5:

            try:
                artistResults = q.getArtists(ws.ArtistFilter(query=name, limit=limit))
                break
            except WebServiceError, e:
                logger.warn("Attempt to query MusicBrainz for %s failed: %s" % (name, e))
                attempt += 1
                time.sleep(5)

        time.sleep(1)

        if not artistResults:
            return False

        for result in artistResults:

            if result.artist.name != result.artist.getUniqueName() and limit == 1:

                logger.debug("Found an artist with a disambiguation: %s - doing an album based search" % name)
                artistdict = findArtistbyAlbum(name)

                if not artistdict:
                    logger.debug("Cannot determine the best match from an artist/album search. Using top match instead")
                    artistlist.append(
                        {
                            "name": result.artist.name,
                            "uniquename": result.artist.getUniqueName(),
                            "id": u.extractUuid(result.artist.id),
                            "url": result.artist.id,
                            "score": result.score,
                        }
                    )

                else:
                    artistlist.append(artistdict)

            else:
                artistlist.append(
                    {
                        "name": result.artist.name,
                        "uniquename": result.artist.getUniqueName(),
                        "id": u.extractUuid(result.artist.id),
                        "url": result.artist.id,
                        "score": result.score,
                    }
                )

        return artistlist
Exemple #27
0
def getArtist(artistid, extrasonly=False):

	with mb_lock:
	
		artist_dict = {}
	
		#Get all official release groups
		inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
		artist = None
		attempt = 0
		
		while attempt < 5:
		
			try:
				artist = q.getArtistById(artistid, inc)
				break
			except WebServiceError, e:
				logger.warn('Attempt to retrieve artist information from MusicBrainz failed for artistid: %s. Sleeping 5 seconds' % artistid)
				attempt += 1
				time.sleep(5)
				
		if not artist:
			return False
		
		time.sleep(1)
				
		artist_dict['artist_name'] = artist.name
		artist_dict['artist_sortname'] = artist.sortName
		artist_dict['artist_uniquename'] = artist.getUniqueName()
		artist_dict['artist_type'] = u.extractFragment(artist.type)
		artist_dict['artist_begindate'] = artist.beginDate
		artist_dict['artist_enddate'] = artist.endDate
		
		releasegroups = []
		
		if not extrasonly:
		
			for rg in artist.getReleaseGroups():
				
				releasegroups.append({
							'title':		rg.title,
							'id':			u.extractUuid(rg.id),
							'url':			rg.id,
							'type':			u.getReleaseTypeName(rg.type)
					})
				
		# See if we need to grab extras
		myDB = db.DBConnection()

		try:
			includeExtras = myDB.select('SELECT IncludeExtras from artists WHERE ArtistID=?', [artistid])[0][0]
		except IndexError:
			includeExtras = False
		
		if includeExtras or headphones.INCLUDE_EXTRAS:
			includes = [m.Release.TYPE_COMPILATION, m.Release.TYPE_REMIX, m.Release.TYPE_SINGLE, m.Release.TYPE_LIVE, m.Release.TYPE_EP]
			for include in includes:
				inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, include), releaseGroups=True)
		
				artist = None
				attempt = 0
			
				while attempt < 5:
		
					try:
						artist = q.getArtistById(artistid, inc)
						break
					except WebServiceError, e:
						logger.warn('Attempt to retrieve artist information from MusicBrainz failed for artistid: %s. Sleeping 5 seconds' % artistid)
						attempt += 1
						time.sleep(5)
						
				if not artist:
					continue
					
				for rg in artist.getReleaseGroups():
			
					releasegroups.append({
							'title':		rg.title,
							'id':			u.extractUuid(rg.id),
							'url':			rg.id,
							'type':			u.getReleaseTypeName(rg.type)
						})
Exemple #28
0
def getReleaseGroup(rgid):
	"""
	Returns the best release out of any given release group
	"""
	with mb_lock:
	
		releaselist = []
		
		inc = ws.ReleaseGroupIncludes(releases=True)
		releaseGroup = None
		attempt = 0
		
		while attempt < 5:
		
			try:
				releaseGroup = q.getReleaseGroupById(rgid, inc)
				break
			except WebServiceError, e:
				logger.warn('Attempt to retrieve information from MusicBrainz for release group "%s" failed. Sleeping 5 seconds' % rgid)
				attempt += 1
				time.sleep(5)
	
		if not releaseGroup:
			return False
			
		time.sleep(1)
		# I think for now we have to make separate queries for each release, in order
		# to get more detailed release info (ASIN, track count, etc.)
		for release in releaseGroup.releases:
	
			inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True)		
			releaseResult = None
			attempt = 0
			
			while attempt < 5:
			
				try:
					releaseResult = q.getReleaseById(release.id, inc)
					break
				except WebServiceError, e:
					logger.warn('Attempt to retrieve release information for %s from MusicBrainz failed: %s. Sleeping 5 seconds' % (releaseResult.title, e))
					attempt += 1
					time.sleep(5)		
			
			if not releaseResult:
				continue
				
			if releaseResult.title.lower() != releaseGroup.title.lower():
				continue
				
			time.sleep(1)
			
			formats = {
				'2xVinyl':			'2',
				'Vinyl':			'2',
				'CD':				'0',
				'Cassette':			'3',			
				'2xCD':				'1',
				'Digital Media':	'0'
				}
				
			country = {
				'US':	'0',
				'GB':	'1',
				'JP':	'1',
				}

			
			try:
				format = int(replace_all(u.extractFragment(releaseResult.releaseEvents[0].format), formats))
			except:
				format = 3
				
			try:
				country = int(replace_all(releaseResult.releaseEvents[0].country, country))
			except:
				country = 2
			
			release_dict = {
				'hasasin':		bool(releaseResult.asin),
				'asin':			releaseResult.asin,
				'trackscount':	len(releaseResult.getTracks()),
				'releaseid':	u.extractUuid(releaseResult.id),
				'releasedate':	releaseResult.getEarliestReleaseDate(),
				'format':		format,
				'country':		country
				}
			
			tracks = []
			
			i = 1
			for track in releaseResult.tracks:
				
				tracks.append({
						'number':		i,
						'title':		track.title,
						'id':			u.extractUuid(track.id),
						'url':			track.id,
						'duration':		track.duration
						})
				i += 1
			
			release_dict['tracks'] = tracks		
			
			releaselist.append(release_dict)
Exemple #29
0
def getRelease(releaseid):
    """
	Deep release search to get track info
	"""
    with mb_lock:

        release = {}

        inc = ws.ReleaseIncludes(tracks=True,
                                 releaseEvents=True,
                                 releaseGroup=True,
                                 artist=True)
        results = None
        attempt = 0

        while attempt < 5:

            try:
                results = q.getReleaseById(releaseid, inc)
                break
            except WebServiceError, e:
                logger.warn(
                    'Attempt to retrieve information from MusicBrainz for release "%s" failed: %s. SLeeping 5 seconds'
                    % (releaseid, e))
                attempt += 1
                time.sleep(5)

        if not results:
            return False

        time.sleep(1)

        release['title'] = results.title
        release['id'] = u.extractUuid(results.id)
        release['asin'] = results.asin
        release['date'] = results.getEarliestReleaseDate()

        rg = results.getReleaseGroup()
        if rg:
            release['rgid'] = u.extractUuid(rg.id)
            release['rg_title'] = rg.title
            release['rg_type'] = u.extractFragment(rg.type)
        else:
            logger.warn("Release " + releaseid +
                        "had no ReleaseGroup associated")
        #so we can start with a releaseID from anywhere and get the artist info
        #it looks like MB api v1 only returns 1 artist object - 2.0 returns more...
        release['artist_name'] = results.artist.name
        release['artist_id'] = u.extractUuid(results.artist.id)

        tracks = []

        i = 1
        for track in results.tracks:
            tracks.append({
                'number': i,
                'title': track.title,
                'id': u.extractUuid(track.id),
                'url': track.id,
                'duration': track.duration
            })
            i += 1

        release['tracks'] = tracks

        return release
Exemple #30
0
def getRelease(releaseid):
	"""
	Deep release search to get track info
	"""
	with mb_lock:
	
		release = {}
	
		inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True, releaseGroup=True, artist=True)
		results = None
		attempt = 0
			
		while attempt < 5:
		
			try:
				results = q.getReleaseById(releaseid, inc)
				break
			except WebServiceError, e:
				logger.warn('Attempt to retrieve information from MusicBrainz for release "%s" failed: %s. SLeeping 5 seconds' % (releaseid, e))
				attempt += 1
				time.sleep(5)	
		
		if not results:
			return False
		
		time.sleep(1)
		
		release['title'] = results.title
		release['id'] = u.extractUuid(results.id)
		release['asin'] = results.asin
		release['date'] = results.getEarliestReleaseDate()


		rg = results.getReleaseGroup()
		if rg:
			release['rgid'] = u.extractUuid(rg.id)
			release['rg_title'] = rg.title
			release['rg_type'] = u.extractFragment(rg.type)
		else:
			logger.warn("Release " + releaseid + "had no ReleaseGroup associated")
		#so we can start with a releaseID from anywhere and get the artist info
		#it looks like MB api v1 only returns 1 artist object - 2.0 returns more...
		release['artist_name'] = results.artist.name
		release['artist_id'] = u.extractUuid(results.artist.id)
		
		tracks = []
		
		i = 1
		for track in results.tracks:
			tracks.append({
					'number':		i,
					'title':		track.title,
					'id':			u.extractUuid(track.id),
					'url':			track.id,
					'duration':		track.duration
					})
			i += 1
			
		release['tracks'] = tracks
		
		return release
Exemple #31
0
			logger.warn('Attempt to query MusicBrainz for %s failed: %s. Sleeping 5 seconds.' % (name, e))
			attempt += 1
			time.sleep(5)	
	
	time.sleep(1)
	
	if not results:
		return False

	artist_dict = {}
	
	for result in results:
		releaseGroup = result.releaseGroup
		artist_dict['name'] = releaseGroup.artist.name
		artist_dict['uniquename'] = releaseGroup.artist.getUniqueName()
		artist_dict['id'] = u.extractUuid(releaseGroup.artist.id)
		artist_dict['url'] = releaseGroup.artist.id
		artist_dict['score'] = result.score
	
	return artist_dict
	
def findAlbumID(artist=None, album=None):

	term = '"'+album+'" AND artist:"'+artist+'"'

	f = ws.ReleaseGroupFilter(query=term, limit=1)
	results = None
	attempt = 0
			
	while attempt < 5:
			
Exemple #32
0
def getReleaseGroup(rgid):
    """
	Returns a dictionary of the best stuff from a release group
	"""
    with mb_lock:

        releaselist = []

        inc = ws.ReleaseGroupIncludes(releases=True, artist=True)
        releaseGroup = None
        attempt = 0

        while attempt < 5:

            try:
                releaseGroup = q.getReleaseGroupById(rgid, inc)
                break
            except WebServiceError, e:
                logger.warn(
                    'Attempt to retrieve information from MusicBrainz for release group "%s" failed. Sleeping 5 seconds'
                    % rgid
                )
                attempt += 1
                time.sleep(5)

        if not releaseGroup:
            return False

        time.sleep(1)
        # I think for now we have to make separate queries for each release, in order
        # to get more detailed release info (ASIN, track count, etc.)
        for release in releaseGroup.releases:

            inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True)
            releaseResult = None
            attempt = 0

            while attempt < 5:

                try:
                    releaseResult = q.getReleaseById(release.id, inc)
                    break
                except WebServiceError, e:
                    logger.warn(
                        "Attempt to retrieve release information for %s from MusicBrainz failed: %s. Sleeping 5 seconds"
                        % (releaseResult.title, e)
                    )
                    attempt += 1
                    time.sleep(5)

            if not releaseResult:
                continue

                # Release filter for non-official live albums
            types = releaseResult.getTypes()
            if any("Live" in type for type in types):
                if not any("Official" in type for type in types):
                    logger.debug("%s is not an official live album. Skipping" % releaseResult.name)
                    continue

            time.sleep(1)

            formats = {"2xVinyl": "2", "Vinyl": "2", "CD": "0", "Cassette": "3", "2xCD": "1", "Digital Media": "0"}

            country = {"US": "0", "GB": "1", "JP": "2"}

            try:
                format = int(replace_all(u.extractFragment(releaseResult.releaseEvents[0].format), formats))
            except:
                format = 3

            try:
                country = int(replace_all(releaseResult.releaseEvents[0].country, country))
            except:
                country = 3

            release_dict = {
                "hasasin": bool(releaseResult.asin),
                "asin": releaseResult.asin,
                "trackscount": len(releaseResult.getTracks()),
                "releaseid": u.extractUuid(releaseResult.id),
                "releasedate": releaseResult.getEarliestReleaseDate(),
                "format": format,
                "country": country,
            }

            tracks = []

            i = 1
            for track in releaseResult.tracks:

                tracks.append(
                    {
                        "number": i,
                        "title": track.title,
                        "id": u.extractUuid(track.id),
                        "url": track.id,
                        "duration": track.duration,
                    }
                )
                i += 1

            release_dict["tracks"] = tracks

            releaselist.append(release_dict)
Exemple #33
0
            item['trackscount_delta'] = abs(average_tracks -
                                            item['trackscount'])

        a = multikeysort(
            releaselist,
            ['-hasasin', 'country', 'format', 'trackscount_delta'])

        release_dict = {
            'releaseid': a[0]['releaseid'],
            'releasedate': releaselist[0]['releasedate'],
            'trackcount': a[0]['trackscount'],
            'tracks': a[0]['tracks'],
            'asin': a[0]['asin'],
            'releaselist': releaselist,
            'artist_name': releaseGroup.artist.name,
            'artist_id': u.extractUuid(releaseGroup.artist.id),
            'title': releaseGroup.title,
            'type': u.extractFragment(releaseGroup.type)
        }

        return release_dict


def getRelease(releaseid):
    """
	Deep release search to get track info
	"""
    with mb_lock:

        release = {}
Exemple #34
0
def getReleaseGroup(rgid):
    """
	Returns a dictionary of the best stuff from a release group
	"""
    with mb_lock:

        releaselist = []

        inc = ws.ReleaseGroupIncludes(releases=True, artist=True)
        releaseGroup = None
        attempt = 0

        while attempt < 5:

            try:
                releaseGroup = q.getReleaseGroupById(rgid, inc)
                break
            except WebServiceError, e:
                logger.warn(
                    'Attempt to retrieve information from MusicBrainz for release group "%s" failed. Sleeping 5 seconds'
                    % rgid)
                attempt += 1
                time.sleep(5)

        if not releaseGroup:
            return False

        time.sleep(1)
        # I think for now we have to make separate queries for each release, in order
        # to get more detailed release info (ASIN, track count, etc.)
        for release in releaseGroup.releases:

            inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True)
            releaseResult = None
            attempt = 0

            while attempt < 5:

                try:
                    releaseResult = q.getReleaseById(release.id, inc)
                    break
                except WebServiceError, e:
                    logger.warn(
                        'Attempt to retrieve release information for %s from MusicBrainz failed: %s. Sleeping 5 seconds'
                        % (releaseResult.title, e))
                    attempt += 1
                    time.sleep(5)

            if not releaseResult:
                continue

            # Release filter for non-official live albums
            types = releaseResult.getTypes()
            if any('Live' in type for type in types):
                if not any('Official' in type for type in types):
                    logger.debug('%s is not an official live album. Skipping' %
                                 releaseResult.name)
                    continue

            time.sleep(1)

            formats = {
                '2xVinyl': '2',
                'Vinyl': '2',
                'CD': '0',
                'Cassette': '3',
                '2xCD': '1',
                'Digital Media': '0'
            }

            country = {
                'US': '0',
                'GB': '1',
                'JP': '2',
            }

            try:
                format = int(
                    replace_all(
                        u.extractFragment(
                            releaseResult.releaseEvents[0].format), formats))
            except:
                format = 3

            try:
                country = int(
                    replace_all(releaseResult.releaseEvents[0].country,
                                country))
            except:
                country = 3

            release_dict = {
                'hasasin': bool(releaseResult.asin),
                'asin': releaseResult.asin,
                'trackscount': len(releaseResult.getTracks()),
                'releaseid': u.extractUuid(releaseResult.id),
                'releasedate': releaseResult.getEarliestReleaseDate(),
                'format': format,
                'country': country
            }

            tracks = []

            i = 1
            for track in releaseResult.tracks:

                tracks.append({
                    'number': i,
                    'title': track.title,
                    'id': u.extractUuid(track.id),
                    'url': track.id,
                    'duration': track.duration
                })
                i += 1

            release_dict['tracks'] = tracks

            releaselist.append(release_dict)
Exemple #35
0
def findArtist(name, limit=1):

    with mb_lock:

        artistlist = []
        attempt = 0
        artistResults = None

        chars = set('!?*')
        if any((c in chars) for c in name):
            name = '"' + name + '"'

        while attempt < 5:

            try:
                artistResults = q.getArtists(
                    ws.ArtistFilter(query=name, limit=limit))
                break
            except WebServiceError, e:
                logger.warn('Attempt to query MusicBrainz for %s failed: %s' %
                            (name, e))
                attempt += 1
                time.sleep(5)

        time.sleep(1)

        if not artistResults:
            return False

        for result in artistResults:

            if result.artist.name != result.artist.getUniqueName(
            ) and limit == 1:

                logger.debug(
                    'Found an artist with a disambiguation: %s - doing an album based search'
                    % name)
                artistdict = findArtistbyAlbum(name)

                if not artistdict:
                    logger.debug(
                        'Cannot determine the best match from an artist/album search. Using top match instead'
                    )
                    artistlist.append({
                        'name':
                        result.artist.name,
                        'uniquename':
                        result.artist.getUniqueName(),
                        'id':
                        u.extractUuid(result.artist.id),
                        'url':
                        result.artist.id,
                        'score':
                        result.score
                    })

                else:
                    artistlist.append(artistdict)

            else:
                artistlist.append({
                    'name': result.artist.name,
                    'uniquename': result.artist.getUniqueName(),
                    'id': u.extractUuid(result.artist.id),
                    'url': result.artist.id,
                    'score': result.score
                })

        return artistlist
Exemple #36
0
def getArtist(artistid, extrasonly=False):

    with mb_lock:

        artist_dict = {}

        #Get all official release groups
        inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL,
                                          m.Release.TYPE_ALBUM),
                                releaseGroups=True)
        artist = None
        attempt = 0

        while attempt < 5:

            try:
                artist = q.getArtistById(artistid, inc)
                break
            except WebServiceError, e:
                logger.warn(
                    'Attempt to retrieve artist information from MusicBrainz failed for artistid: %s. Sleeping 5 seconds'
                    % artistid)
                attempt += 1
                time.sleep(5)

        if not artist:
            return False

        time.sleep(1)

        artist_dict['artist_name'] = artist.name
        artist_dict['artist_sortname'] = artist.sortName
        artist_dict['artist_uniquename'] = artist.getUniqueName()
        artist_dict['artist_type'] = u.extractFragment(artist.type)
        artist_dict['artist_begindate'] = artist.beginDate
        artist_dict['artist_enddate'] = artist.endDate

        releasegroups = []

        if not extrasonly:

            for rg in artist.getReleaseGroups():

                releasegroups.append({
                    'title': rg.title,
                    'id': u.extractUuid(rg.id),
                    'url': rg.id,
                    'type': u.getReleaseTypeName(rg.type)
                })

        # See if we need to grab extras
        myDB = db.DBConnection()

        try:
            includeExtras = myDB.select(
                'SELECT IncludeExtras from artists WHERE ArtistID=?',
                [artistid])[0][0]
        except IndexError:
            includeExtras = False

        if includeExtras or headphones.INCLUDE_EXTRAS:
            includes = [
                m.Release.TYPE_COMPILATION, m.Release.TYPE_REMIX,
                m.Release.TYPE_SINGLE, m.Release.TYPE_LIVE, m.Release.TYPE_EP,
                m.Release.TYPE_SOUNDTRACK
            ]
            for include in includes:
                inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL,
                                                  include),
                                        releaseGroups=True)

                artist = None
                attempt = 0

                while attempt < 5:

                    try:
                        artist = q.getArtistById(artistid, inc)
                        break
                    except WebServiceError, e:
                        logger.warn(
                            'Attempt to retrieve artist information from MusicBrainz failed for artistid: %s. Sleeping 5 seconds'
                            % artistid)
                        attempt += 1
                        time.sleep(5)

                if not artist:
                    continue

                for rg in artist.getReleaseGroups():

                    releasegroups.append({
                        'title': rg.title,
                        'id': u.extractUuid(rg.id),
                        'url': rg.id,
                        'type': u.getReleaseTypeName(rg.type)
                    })