Ejemplo n.º 1
0
    def extractMetadataHelper(self, mediawrapper, fieldMap, filename):
        ''' Retrieves artist, album, and track data, forcing it to unicode '''
        artists = []
        for artistField in self.artistFieldPref:
            if (fieldMap[artistField] in mediawrapper):
                tmpartist = mediawrapper[fieldMap[artistField]][0]
                if (not common.isempty(tmpartist)):
                    artists.append(unicode(tmpartist).lower())
                if (self.useBothArtistFields):
                    continue
                break
        artists = set(artists).difference(self.meaninglessArtists)
        if (len(artists) == 0):
            common.safeStderr('No artist info found for [' + filename + ']')
            return None

        # album
        album = u'-unknown-'
        if (fieldMap['album'] in mediawrapper):
            tmpalbum = mediawrapper[fieldMap['album']][0]
            if (not common.isempty(tmpalbum)):
                album = unicode(tmpalbum).lower()

        # track
        track = None
        if (fieldMap['track'] in mediawrapper):
            tmptrack = mediawrapper[fieldMap['track']][0]
            if (not common.isempty(tmptrack)):
                track = unicode(tmptrack).lower()
        if (track is None):
            common.safeStderr('No track title found for [' + filename + ']')
            return None
        return {'artists': artists, 'album': album, 'track': track}
Ejemplo n.º 2
0
 def addToMediaLibrary(self, artist, album, track, artistTags=None, trackTags=None):
     if (common.isempty(artist)):
         raise Exception('No artist info provided')
     elif (common.isempty(track)):
         raise Exception('No track title provided')
     elif (common.isempty(album)):
         raise Exception('No album title provided')
             
     if (artist not in self.mediaLibrary):
         self.mediaLibrary[artist] = { 'albums':{}, 'tags':artistTags }
         
     if (album not in self.mediaLibrary[artist]['albums']):
         self.mediaLibrary[artist]['albums'][album] = { 'tracks':{} }
 
     if (track not in self.mediaLibrary[artist]['albums'][album]['tracks']):
         self.mediaLibrary[artist]['albums'][album]['tracks'][track] = { 'tags':trackTags }
Ejemplo n.º 3
0
 def updateTagsHelper(self, mediawrapper, tagPayload, fieldMap):
     ''' This version saves the tag data in Unicode encoding '''
     retVal = False
     for bucket in tagPayload:
         if (bucket not in fieldMap):
             raise Exception('Unknown field type requested [' + bucket +
                             ']')
         curField = fieldMap[bucket]
         # If we're not required to verwrite, check if we actually need to and should
         if (bucket not in self.forceOverwriteFields):
             # Is the payload empty? Don't update.
             if (len(tagPayload[bucket]) == 0):
                 continue
             # Is there an existing value? Don't update if this isn't an overwritable field or if the current value is the same as the update value
             elif (curField in mediawrapper
                   and not common.isempty(mediawrapper[curField][0])):
                 if (bucket not in self.overwriteFields
                         or unicode(mediawrapper[curField][0]) == unicode(
                             tagPayload[bucket])):
                     continue
         mediawrapper[curField] = unicode(tagPayload[bucket])
         retVal = True
     if (retVal == True):
         mediawrapper.save()
     return retVal
Ejemplo n.º 4
0
 def getPopularityWeight(self, tag):
     ''' Returns the popularity weight for the given tag, or 0 if the tag is empty or not present '''
     if (common.isempty(tag)):
         return 0
     key = tag.lower()
     if (self.localTagLibrary[key] is not None): 
         return self.localTagLibrary[key]['lasthits']
     return 0
Ejemplo n.º 5
0
 def lookupSynonyms(self, tag):
     ''' Returns a set of synonyms for the given tag, or None if none exist '''
     if (common.isempty(tag)):
         return None
     key = tag.lower()
     if (key in self.synonyms):
         return self.synonyms[key]
     return None
Ejemplo n.º 6
0
	def getImageList(self, params):
		common.trace("Starting to search images using parameters: %s" % str(params), "theaudiodb")
		images = []
		self._setFilepaths(params)
		url, url_params = self._getUrlDetails(params, self.URL_ARTISTSEARCH)
		if url:
			json_data = self._getData(self.ARTISTFILEPATH, self.CACHEFILEPATH, url, url_params)
			if json_data:
				content = json_data.get('artists')
				if content is not None:
					if "strMusicBrainzID" in content[0]:
						params["mbid"] = content[0].get("strMusicBrainzID")
					if "strArtistFanart" in  content[0]:
						image = content[0].get('strArtistFanart')
						if image:
							images.append(image)
					if "strArtistFanart2" in  content[0]:
						image = content[0].get('strArtistFanart2')
						if image:
							images.append(image)
					if "strArtistFanart3" in  content[0]:
						image = content[0].get('strArtistFanart3')
						if image:
							images.append(image)
					if "strArtistThumb" in  content[0]:
						image = content[0].get('strArtistWideThumb')
						if image:
							images.append(image)
					if "strArtistWideThumb" in  content[0]:
						image = content[0].get('strArtistWideThumb')
						if image:
							images.append(image)
					if "strArtistClearart" in  content[0]:
						image = content[0].get('strArtistClearart')
						if image:
							images.append(image)
					if "strArtistAlternate" in content[0] and not common.isempty(content[0].get('strArtistAlternate')):
						params['fullname'] = content[0].get('strArtistAlternate')
					if "strArtist" in content[0] and not common.isempty(content[0].get('strArtist')):
						params['alias'] = content[0].get('strArtist')
					if "strCountryCode" in content[0] and not common.isempty(content[0].get('strCountryCode')):
						params['location'] = content[0].get('strCountryCode')
		if not images:
			return []
		else:
			return self._delExclusions(images, params.get('exclusionsfile', ''))
Ejemplo n.º 7
0
 def loadSynonyms(self):
     synfile = self.config.get('tagSynonymsFile')
     if (common.isempty(synfile)):
         return
     if (not os.path.exists(synfile) or not os.access(synfile, os.R_OK)):
         common.safeStderr('Synonyms file either does not exist or cannot be accessed ['+synfile+']')
     
     # Read the synonmyms file. The expected format is:
     # original token(tab)replacement token[,replacement token]...
     # e.g. 
     # rnb    rhythm and blues, r&b
     # This would replace any instance of 'rnb' seen in the LastFM tag set with both 'rhythm and blues' and 'r&b'
     # We preserve order, for the replacement values (so you can order them as you would like them to be replaced)
     for line in fileinput.input(synfile):
         # Allow inline comments
         if ('#' in line):
             line = line.split('#')[0]
         line = line.strip()
         if (common.isempty(line)):
             continue
         if (isinstance(line, str)):                
             line = unicode(line, 'latin1')
         synline = line.split('\t')
         if (len(synline) < 2):
             common.safeStderr('Invalid synonym file line: '+line)
             continue
         original = synline[0].lower()
         replacements = map(string.strip, synline[1].split(','))
         if ('-none-' in map(lambda val: val.lower(), replacements)):
             self.synonyms[original] = []
         elif (original in self.synonyms):
             self.synonyms[original] = common.distinctSeq(self.synonyms[original] + replacements)
         else:
             self.synonyms[original] = common.distinctSeq(replacements)
     #for syn in sorted(self.synonyms):
     #    common.safeStdout('Synonyms: '+ syn + ' :: '+ ', '.join(sorted(self.synonyms[syn])))
     if (self.config.getboolean('verbose')):
         print 'Loaded ['+str(len(self.synonyms.keys()))+'] tag synonyms'           
Ejemplo n.º 8
0
    def decode_string(self, str):
        if (common.isempty(str)):
            return ''

        if (str.lower() == 'space'):
            return ' '
        elif (str.lower() == 'semi'):
            return ';'
        elif (str.lower() == 'hash'):
            return '#'
        elif (str.lower() == 'percent'):
            return '%'
        else:
            return str
Ejemplo n.º 9
0
 def updateTagsHelperID3(self, mediawrapper, tagPayload, fieldMap):
     ''' 
     ID3 requires uniquely encoded values, so this custom method is necessary to properly save the updated tags. 
     If the comments field is used, values will be saved with an empty description and lang=eng.  
     '''
     retVal = False
     for bucket in tagPayload:
         if (bucket not in fieldMap):
             raise Exception('Unknown field type requested [' + bucket +
                             ']')
         curField = fieldMap[bucket]
         # If we're not required to verwrite, check if we actually need to and should
         if (bucket not in self.forceOverwriteFields):
             # Is the payload empty? Don't update.
             if (len(tagPayload[bucket]) == 0):
                 continue
             # Is there an existing value? Don't update if this isn't an overwritable field or if the current value is the same as the update value
             elif (curField in mediawrapper
                   and not common.isempty(mediawrapper[curField][0])):
                 if (bucket not in self.overwriteFields
                         or unicode(mediawrapper[curField][0]) == unicode(
                             tagPayload[bucket])):
                     continue
         mediawrapper[curField] = self.id3FuncMap[bucket](
             tagPayload[bucket])
         retVal = True
     if (retVal == True):
         # There's an odd bug somewhere in the interaction between some set of Mutagen, iTunes, and/or WMP that causes
         # duplicate ID3v2 headers. This tends to break playback at least in iTunes. The following pre-save block makes a
         # copy of whatever the 'current' header is, deletes 'all' v2 headers, and then re-adds the current header frames.
         # We seem to end up with some unnecessary blank padding between the frames and content, though.
         curFrames = {}
         for key in mediawrapper.keys():
             curFrames[key] = mediawrapper[key]
         mediawrapper.delete(delete_v2=True)
         for key in curFrames:
             mediawrapper[key] = curFrames[key]
         mediawrapper.save(v1=self.id3v1Handling)
     return retVal
Ejemplo n.º 10
0
	def getImageList(self, params):
		common.trace("Starting to search images using parameters: %s" %str(params), "duckgo")
		images = []
		if params.get('mbid', '') == '':
			common.warn("No artist identified over MusicBrainz, search stopped")
			return images
		if "fullname" in params and not common.isempty(params['fullname']):
			keywords = params['fullname'] + " AND (singer OR band)"
		elif "alias" in params and not common.isempty(params['alias']):
			keywords = params['alias'] + " AND (singer OR band)"
		elif "artist" in params and not common.isempty(params['artist']):
			keywords = params['artist'] + " AND (singer OR band)"
		else:
			keywords = None
		if keywords is not None and "location" in params and not common.isempty(params['location']):
			keywords = keywords + " AND " + params['location']
		elif keywords is not None and "lang" in params and not common.isempty(params['lang']):
			keywords = keywords + " AND " + params['lang']
		if keywords is not None:
			payload = {'q': keywords}
			common.trace("Hitting DuckDuckGo for token", "duckgo")
			data = common.urlcall(self.DDG_SEARCH_URL, "POST", payload=payload)
			searchObj = re.search(r'vqd=([\d-]+)\&', data, re.M | re.I)
			if not searchObj:
				common.error("Token parsing failed!", "duckgo")
				return images
			else:
				common.debug("Obtained token: %s" % searchObj.group(1), "duckgo")
			headers = {
				'authority': 'duckduckgo.com',
				'accept': 'application/json, text/javascript, */*; q=0.01',
				'sec-fetch-dest': 'empty',
				'x-requested-with': 'XMLHttpRequest',
				'user-agent': common.agent(),
				'sec-fetch-site': 'same-origin',
				'sec-fetch-mode': 'cors',
				'referer': 'https://duckduckgo.com/'
			}
			payload = {
				"q": keywords,
				"vqd": searchObj.group(1),
				"v7exp": "a",
				"o": "json",
				"l": "wt-wt",
				"f": ",,,",
				"p": '1'
			}
			data = None
			while True:
				try:
					data = common.urlcall(self.DDG_SEARCH_URL + "i.js", headers=headers, payload=payload, output='json')
					break
				except ValueError as e:
					common.trace("Calling url failure; sleep and retry", "duckgo")
					common.sleep(500)
					continue
			index = 0
			max = common.any2int(params['limit'], 0)
			for obj in data["results"]:
				contextual = str(obj["title"].encode('utf-8')).lower().find(params['artist'].lower() + " ") >= 0
				dimension = int(obj["width"]) >= 876 if common.any2bool(params.get('getall', 'false')) else int(obj["width"]) >= 1920
				if contextual and dimension:
					index += 1
					images.append(obj["image"])
				if max > 0 and index >= max:
					break
		if not images:
			return []
		else:
			return self._delExclusions(images, params.get('exclusionsfile'))