def _parse_album_track(self, track_html): """Returns a TrackInfo derived from the html describing a track in a bandcamp album page. """ track_num = track_html['rel'].split('=')[1] track_num = int(track_num) title_html = track_html.find(attrs={'class': 'title-col'}) title = title_html.find(attrs={'itemprop': 'name'}).text.strip() artist = None if self.config['split_artist_title']: artist, title = self._split_artist_title(title) track_url = title_html.find(attrs={'itemprop': 'url'}) if track_url is None: raise BandcampException( 'No track url (id) for track {0} - {1}'.format( track_num, title)) track_id = track_url['href'] try: duration = title_html.find('meta', attrs={'itemprop': 'duration'})['content'] duration = duration.replace('P', 'PT') track_length = isodate.parse_duration(duration).total_seconds() except TypeError: track_length = None return TrackInfo(title, track_id, index=track_num, length=track_length, artist=artist)
def get_track_info(self, url): """Returns a TrackInfo object for a bandcamp track page. """ try: html = self._get(url) name_section = html.find(id='name-section') title = name_section.find(attrs={'itemprop': 'name'}).text.strip() artist_url = url.split('/track/')[0] artist = name_section.find(attrs={ 'itemprop': 'byArtist' }).text.strip() try: duration = html.find('meta', attrs={'itemprop': 'duration'})['content'] track_length = float(duration) if track_length == 0: track_length = None except TypeError: track_length = None return TrackInfo(title, url, length=track_length, artist=artist, artist_id=artist_url, data_source='bandcamp', media='Digital Media', data_url=url) except requests.exceptions.RequestException as e: self._log.debug("Communication error while fetching track {0!r}: " "{1}".format(url, e))
def _get_track(self, track_data): """Convert a Spotify track object dict to a TrackInfo object. :param track_data: Simplified track object (https://developer.spotify.com/documentation/web-api/reference/object-model/#track-object-simplified) :type track_data: dict :return: TrackInfo object for track :rtype: beets.autotag.hooks.TrackInfo """ artist, artist_id = self.get_artist(track_data['artists']) # Get album information for spotify tracks try: album = track_data['album']['name'] except KeyError: album = None return TrackInfo( title=track_data['name'], track_id=track_data['id'], spotify_track_id=track_data['id'], artist=artist, album=album, artist_id=artist_id, spotify_artist_id=artist_id, length=track_data['duration_ms'] / 1000, index=track_data['track_number'], medium=track_data['disc_number'], medium_index=track_data['track_number'], data_source=self.data_source, data_url=track_data['external_urls']['spotify'], )
def get_track_info(self, track): """Returns a TrackInfo object for a Metal Archives track object. """ track_id = _add_prefix(track.id) artist_id = _add_prefix(track.band.id) return TrackInfo(unicode(track.title), track_id, unicode(track.band.name), artist_id, track.duration, track.overall_number, track.disc_number, track.number)
def get_track_info(self, track, index): """Returns a TrackInfo object for a discogs track. """ title = track['title'] track_id = None medium, medium_index, _ = self.get_track_index(track['position']) artist, artist_id = MetadataSourcePlugin.get_artist( track.get('artists', []) ) feats = self.get_feats(track.get('extraartists', [])) if artist and feats: artist = artist + ' feat. ' + feats length = self.get_track_length(track['duration']) trackinfo = TrackInfo(title, track_id, artist=artist, artist_id=artist_id, length=length, index=index, medium=medium, medium_index=medium_index, artist_sort=None, disctitle=None, artist_credit=None) trackinfo.feats = feats return trackinfo
def get_track_info(self, track, artist=None): """Given a dict of Gracenote track metadata, returns the TrackInfo object for that track.""" title = track.get('track_title') track_id = track.get('track_gnid') index = track.get('track_number') artist = track.get('track_artist_name', artist) if index is not None and index.isdecimal(): index = int(index) return TrackInfo(title, track_id, artist=artist, index=index)
def get_track_info(self, track, index): """Returns a TrackInfo object for a discogs track. """ title = track['title'] track_id = None medium, medium_index, _ = self.get_track_index(track['position']) artist, artist_id = self.get_artist(track.get('artists', [])) length = self.get_track_length(track['duration']) return TrackInfo(title, track_id, artist, artist_id, length, index, medium, medium_index, artist_sort=None, disctitle=None, artist_credit=None)
def set_singleton(self, artist: str, title: str, length: int, **kwargs) -> None: data = self.track_data( title=title, track_id=self.album_id, artist=artist, length=length, index=1, ) if NEW_BEETS: data.update(**kwargs) self.singleton = TrackInfo(**data)
def _get_track_info(self, track, index=None): """Returns a TrackInfo object for a Beatport Track object. """ title = track.name if track.mix_name != u"Original Mix": title += u" ({})".format(track.mix_name) artist, artist_id = self._get_artist(track.artists) length = track.length.total_seconds() return TrackInfo(title=title, track_id=track.beatport_id, artist=artist, artist_id=artist_id, length=length, index=index)
def _get_track_info(self, track): """Returns a TrackInfo object for a Beatport Track object. """ title = track.name if track.mix_name != u"Original Mix": title += u" ({0})".format(track.mix_name) artist, artist_id = self._get_artist(track.artists) length = track.length.total_seconds() return TrackInfo(title=title, track_id=track.beatport_id, artist=artist, artist_id=artist_id, length=length, index=track.track_number, medium_index=track.track_number, data_source=u'Beatport', data_url=track.url, bpm=track.bpm, musical_key=track.musical_key)
def get_album_info(self, result, artist, album, items): """Returns an AlbumInfo object for a discogs Release object. """ if result.kind in ['playlist', 'album']: user = result.user.get('username') tracks = list() for track_result in result.tracks: title = '' if hasattr(track_result, 'title'): title = track_result.get('title') title = re.sub('\(clip\)$', '', title, flags=re.IGNORECASE) artist_remove_exp = '^' + artist + ' \- ' title = re.sub(artist_remove_exp, '', title, flags=re.IGNORECASE) track_number = result.tracks.index(track_result) + 1 track = TrackInfo(artist=artist, album=album, title=title.strip(), index=track_number, medium_index=track_number, soundcloud_trackid=track_result.get('id')) tracks.append(track) return AlbumInfo(tracks, soundcloud_playlistid=result.id, soundcloud_userid=result.user_id, album=result.title, artist=artist, soundcloud_username=user, data_source='Soundcloud') if result.kind == 'track': user = result.user.get('username') title = result.title title = re.sub('\(clip\)$', '', title, flags=re.IGNORECASE) artist_remove_exp = '^' + artist + ' \- ' title = re.sub(artist_remove_exp, '', title, flags=re.IGNORECASE) tracks = self.get_tracks_from_comments(result, artist, album, items) return AlbumInfo(tracks, soundcloud_userid=result.user_id, album=result.title, artist=artist, soundcloud_username=user, data_source='Soundcloud') return None
def generate_track_info(track_id='track info', values={}): """Return `TrackInfo` populated with mock data. The `track_id` field is set to the corresponding argument. All other string fields are set to "track info". """ track = TrackInfo( title=u'track info', track_id=track_id, ) for field in TRACK_INFO_FIELDS: setattr(track, field, u'track info') for field, value in values.items(): setattr(track, field, value) return track
def get_track_info(self, track, index, divisions): """Returns a TrackInfo object for a discogs track. """ title = track['title'] if self.config['index_tracks']: prefix = ', '.join(divisions) title = ': '.join([prefix, title]) track_id = None medium, medium_index, _ = self.get_track_index(track['position']) artist, artist_id = MetadataSourcePlugin.get_artist( track.get('artists', []) ) length = self.get_track_length(track['duration']) return TrackInfo(title=title, track_id=track_id, artist=artist, artist_id=artist_id, length=length, index=index, medium=medium, medium_index=medium_index)
def get_track_info(self, item): """"Convert JSON data into a format beets can read.""" song = item['song'] title, _ = self.get_preferred_name(item['song']) track_id = song['id'] artist = song['artistString'] artist_credit = None artist_id = None length = song['lengthSeconds'] medium = item['discNumber'] medium_index = item['trackNumber'] lyricist = self.config['separator'].get().join( [(_artist['artist']['name'] if 'artist' in _artist else _artist['name']) for _artist in song['artists'] if 'Lyricist' in _artist['roles'].split(', ')]) or None composer = self.config['separator'].get().join( [(_artist['artist']['name'] if 'artist' in _artist else _artist['name']) for _artist in song['artists'] if 'Composer' in _artist['roles'].split(', ')]) or None arranger = self.config['separator'].get().join( [(_artist['artist']['name'] if 'artist' in _artist else _artist['name']) for _artist in song['artists'] if 'Arranger' in _artist['roles'].split(', ')]) or None return TrackInfo(title, track_id, artist=artist, artist_id=artist_id, length=length, medium=medium, medium_index=medium_index, medium_total=None, artist_credit=artist_credit, data_source='VocaDB', lyricist=lyricist, composer=composer, arranger=arranger)
def get_tracks_from_comments(self, track_result, artist, album, items): tracks = list() comments = self.get_comments(track_result.id) filtered_comments = self.get_track_names_from_comments( comments, track_result.user_id, items) if filtered_comments: for item in items: if item.track in filtered_comments: track = filtered_comments[item.track] tracks.append( TrackInfo(artist=artist, album=album, title=track.body, soundcloud_tracktimestamp=track.timestamp, index=item.track, medium_index=item.track, soundcloud_trackid=track_result.id)) return tracks
def _get_track_info(self, track): """Returns a TrackInfo object for a Beatport Track object. """ title = track.name if track.mix_name != "Original Mix": title += f" ({track.mix_name})" artist, artist_id = self._get_artist(track.artists) length = track.length.total_seconds() return TrackInfo(title=title, track_id=track.beatport_id, artist=artist, artist_id=artist_id, length=length, index=track.track_number, medium_index=track.track_number, data_source=self.data_source, data_url=track.url, bpm=track.bpm, initial_key=track.initial_key, genre=track.genre)
def _get_tracks(self, album_url, soup=None): """ returns list of TrackInfo objects in album linked to by `album_url`. """ if soup is None: soup = self._open_url(album_url) tracks = [] # separate into discs tracklist = soup.find("div", class_="tracklist").find_all("table") disctitles = [s.get_text(strip=True) for s in soup.find("div", class_="left fl").find("ul", class_="clearfix").find_all("a")] # because diverse.direct only indexes by individual disc index = 1 for medium, table in enumerate(tracklist, start=1): medium_total = len(table) disctitle = disctitles[medium - 1] # process individual discs for medium_index, tr in enumerate(table.find_all("tr"), start=1): _, title, artist = [s.get_text(strip=True) for s in tr.find_all("td")] track = TrackInfo(title, album_url, artist=artist, index=index, medium=medium, medium_index=medium_index, medium_total=medium_total, disctitle=disctitle, data_source=DATA_SOURCE) index += 1 tracks.append(track) return tracks
def set_albuminfo(self, tracks, **kwargs): fields = ["index", "title_id", "artist", "title", "length", "alt"] iter_tracks = [zip(fields, (idx, *track)) for idx, track in enumerate(tracks, 1)] self.albuminfo = AlbumInfo( album=kwargs["album"], album_id=self.album_id, artist=kwargs["albumartist"], artist_id=self.artist_id, data_url=self.album_id, year=kwargs["release_date"].year, month=kwargs["release_date"].month, day=kwargs["release_date"].day, label=kwargs["label"], va=kwargs["va"], albumtype=kwargs["albumtype"], catalognum=kwargs["catalognum"], country=kwargs["country"], mediums=kwargs["mediums"], albumstatus=OFFICIAL, media=self.media, data_source=DATA_SOURCE, tracks=[TrackInfo(**self.track_data(**dict(t))) for t in iter_tracks], )
def get_album_info(self, item, ns, va_likely): album = item.findtext('{0}ItemAttributes/{0}Title'.format(ns)) album_id = item.findtext('{0}ItemAttributes/{0}EAN'.format(ns)) album_UPC = item.findtext('{0}ItemAttributes/{0}UPC'.format(ns)) country = ",".join([cat.text.replace("Country Of Release:", '') for cat in item.findall('{0}ItemAttributes/{0}Feature'.format(ns)) if "Country Of Release:" in cat.text]) catnumlisbig = None catalog = ",".join([cat.text.replace("Catalog#", '') for cat in item.findall('{0}ItemAttributes/{0}Feature'.format(ns)) if "Catalog#" in cat.text]) catnumlis = [it.text for it in item.findall( '{0}ItemAttributes/{0}CatalogNumberList/{0}CatalogNumberListElement' .format(ns))] catnumlis.sort() catnumlisbig = catnumlis[0] if catnumlis else catalog perf = ",".join([role.text for role in item.findall( '{0}ItemAttributes/{0}Creator'.format(ns)) if role.attrib.get("Role") == "Performer"]) art = ",".join([artist.text for artist in item.findall( '{0}ItemAttributes/{0}Artist'.format(ns))]) artists = art or perf va = False if artists == album and va_likely: artists = "Various Artists" va = True artist_id = artists.split(",")[0] Tracks = [] trn = 1 for disc in item.iterfind(".//{0}Disc".format(ns)): tr = disc.findall(".//{0}Track".format(ns)) for track in disc.iterfind(".//{0}Track".format(ns)): title = track.text index = trn medium = disc.attrib.get("Number") medium_index = track.attrib.get("Number") newtrack = TrackInfo( self.decod(title), int(index), index=int(index), medium=int(medium), medium_index=int(medium_index), medium_total=len(tr) ) Tracks.append(newtrack) trn = trn + 1 asin = item.findtext('{0}ASIN'.format(ns)) albumtype = item.findtext( '{0}ItemAttributes/{0}Binding'.format(ns)) rd = item.findtext( '{0}ItemAttributes/{0}ReleaseDate'.format(ns)) year = month = day = None if rd: releasedate = rd.split("-") year = releasedate[0] month = releasedate[1] day = releasedate[2] label = item.findtext('{0}ItemAttributes/{0}Label'.format(ns)) ProductTypeName = item.findtext( '{0}ItemAttributes/{0}ProductTypeName'.format(ns)) label = label if label else ProductTypeName mediums = item.findtext( '{0}ItemAttributes/{0}NumberOfDiscs'.format(ns)) if mediums is None: mediums = 1 Composers = [role.text for role in item.findall( '{0}ItemAttributes/{0}Creator'.format(ns)) if role.attrib.get("Role") == "Composer"] Conductors = [role.text for role in item.findall( '{0}ItemAttributes/{0}Creator'.format(ns)) if role.attrib.get("Role") == "Conductor"] Orchestras = [role.text for role in item.findall( '{0}ItemAttributes/{0}Creator'.format(ns)) if role.attrib.get("Role") == "Orchestra"] comps = ",". join(Composers) cond = ",".join(Conductors) orch = ",".join(Orchestras) media = item.findtext('{0}ItemAttributes/{0}Binding'.format(ns)) data_url = item.findtext('{0}DetailPageURL'.format(ns)) return AlbumInfo(self.decod(album), self.decod(album_id), self.decod(artists), self.decod(artist_id), Tracks, asin=self.decod(asin), albumtype=self.decod(albumtype), va=va, year=int(year), month=int(month), day=int(day), label=self.decod(label), mediums=int(mediums), media=self.decod(media), data_source=self.decod('Amazon'), data_url=self.decod(data_url), country=self.decod(country), catalognum=self.decod(catnumlisbig) )
def get_album_info(self, item, va_likely): """Convert json data into a format beets can read""" # If a preferred lang is available use that instead album_name = item["name"] for lang in self.lang: if lang in item["names"]: album_name = item["names"][lang] break album_id = item["link"][6:] country = "JP" catalognum = item["catalog"] # Get Artist information if "performers" in item and len(item["performers"]) > 0: artist_type = "performers" else: artist_type = "composers" artists = [] for artist in item[artist_type]: for lang in self.lang: if lang in artist["names"]: artists.append(artist["names"][lang]) break artist = artists[0] if "link" in item[artist_type][0]: artist_id = item[artist_type][0]["link"][7:] else: artist_id = None # Get Track metadata Tracks = [] total_index = 0 for disc_index, disc in enumerate(item["discs"]): for track_index, track in enumerate(disc["tracks"]): total_index += 1 title = list(track["names"].values())[0] for lang in self.lang: if lang in track["names"]: title = track["names"][lang] break index = total_index if track["track_length"] == "Unknown": length = 0 else: length = track["track_length"].split(":") length = (float(length[0]) * 60) + float(length[1]) media = item["media_format"] medium = disc_index medium_index = track_index new_track = TrackInfo( title, int(index), length=float(length), index=int(index), medium=int(medium), medium_index=int(medium_index), medium_total=item["discs"].count, ) Tracks.append(new_track) # Format Album release date release_date = item["release_date"].split("-") year = release_date[0] month = release_date[1] day = release_date[2] for lang in self.lang: if lang in item["publisher"]["names"]: label = item["publisher"]["names"][lang] mediums = len(item["discs"]) media = item["media_format"] data_url = item["vgmdb_link"] return AlbumInfo( album_name, str(album_id), artist, str(artist_id), Tracks, asin=None, albumtype=None, va=False, year=int(year), month=int(month), day=int(day), label=label, mediums=int(mediums), media=str(media), data_source="VGMdb", data_url=str(data_url), country=str(country), catalognum=str(catalognum), )