def test_metadata(self):
        raw_song = 'https://open.spotify.com/track/0JlS7BXXD07hRmevDnbPDU'

        expect_number = 23
        global meta_tags
        meta_tags = spotify_tools.generate_metadata(raw_song)
        assert len(meta_tags) == expect_number
Ejemplo n.º 2
0
def get_playlist(playlist_uri):
    tracks = []
    if 'playlist' in playlist_uri:  # playlist
        try:
            playlist = spotify_tools.fetch_playlist(playlist_uri)
        except spotipy.client.SpotifyException as e:
            log.error(e)
            log.debug('Token expired, generating new one and authorizing')
            new_token = spotify_tools.generate_token()
            spotify_tools.spotify = spotipy.Spotify(auth=new_token)
            playlist = spotify_tools.fetch_playlist(playlist_uri)
        if playlist is None:
            # self.error = "Could not find playlist. Please check the playlist URL and try again."
            return
        tracks = get_tracks(playlist['tracks'])
    else:  # song
        try:
            meta_tags = spotify_tools.generate_metadata(playlist_uri)
        except spotipy.client.SpotifyException as e:
            log.error(e)
            # self.error = "Could not find song. Please check the song URL and try again."
            return
        track_name = meta_tags['name']
        track_artist = meta_tags['artists'][0]['name']
        track_url = playlist_uri
    return tracks
Ejemplo n.º 3
0
def fetch_yt_url(url):
    meta_tags = spotify_tools.generate_metadata(url)
    content = youtube_tools.go_pafy(url, meta_tags)

    if content:
        return content.watchv_url

    return
Ejemplo n.º 4
0
def test_metadata():
    expect_metadata = None
    meta_tags = spotify_tools.generate_metadata(raw_song)
    if meta_tags:
        metadata_output = metadata.embed(
            os.path.join(const.args.folder, output_song), meta_tags)
        metadata_input = metadata.embed(
            os.path.join(const.args.folder, input_song), meta_tags)
    else:
        metadata_input = None
        metadata_output = None
    assert (metadata_output == expect_metadata) and (metadata_input
                                                     == expect_metadata)
Ejemplo n.º 5
0
def download_single(raw_song, number=None, folder=None) -> bool:
    """ Logic behind downloading a song. """
    meta_tags = spotify_tools.generate_metadata(raw_song)

    if const.args.download_only_metadata and meta_tags is None:
        log.info('Found no metadata. Skipping the download')
        return False

    # generate file name of the song to download
    songname = 'foo'

    if meta_tags is not None:
        refined_songname = internals.format_string(const.args.file_format,
                                                   meta_tags,
                                                   slugification=True)
        log.debug('Refining songname from "{0}" to "{1}"'.format(
            songname, refined_songname))
        if not refined_songname == ' - ':
            songname = refined_songname
    else:
        log.warning('Could not find metadata')
        songname = internals.sanitize_title(songname)

    if not check_exists(songname, raw_song, meta_tags, folder):
        # deal with file formats containing slashes to non-existent directories
        if folder:
            folder_path = folder
        else:
            folder_path = const.args.folder
        songpath = os.path.join(folder_path, os.path.dirname(songname))
        os.makedirs(songpath, exist_ok=True)
        file_name = os.path.join(folder_path, songname + const.args.output_ext)
        play_time = player.play_and_record(meta_tags['uri'], file_name,
                                           songname)
        if not record.verify_length(file_name, meta_tags['duration'],
                                    play_time):
            log.error('Duration mismatch! Deleting: {}'.format(songname))
            if duration_debug:
                fail_path = os.path.join(folder_path, 'mismatch')
                if not os.path.exists(fail_path):
                    os.mkdir(fail_path)
                _, file_only = os.path.split(file_name)
                copyfile(file_name, os.path.join(fail_path, file_only))
            os.remove(file_name)
            return False
        if not const.args.no_metadata and meta_tags is not None:
            metadata.embed(file_name, meta_tags)
        return True
    return True
Ejemplo n.º 6
0
def test_metadata():
    expect_number = 22
    global meta_tags
    meta_tags = spotify_tools.generate_metadata(raw_song)
    assert len(meta_tags) == expect_number
def test_metadata():
    expect_metadata = None
    global metadata
    metadata = spotify_tools.generate_metadata(raw_song)
    assert metadata == expect_metadata
from core import config, const, internals, spotdl, spotify_tools, youtube_tools

config.init_config()
raw_song = "Tony's Videos VERY SHORT VIDEO 28.10.2016"
raw_song_spotify = 'https://open.spotify.com/track/33IOhptvC2Qoy2UhjiHXLV'
meta_tags = spotify_tools.generate_metadata(raw_song_spotify)

file_format = '{artist} - {track_name}'


class TestArgsManualResultCount:
    # Regresson test for issue #264
    def test_scrape(self):
        const.config.manual = True
        url = youtube_tools.GenerateYouTubeURL("she is still sleeping SAO",
                                               meta_tags=None)
        video_ids = url.scrape(bestmatch=False)
        # Web scraping gives us all videos on the 1st page
        assert len(video_ids) == 20

    def test_api(self):
        url = youtube_tools.GenerateYouTubeURL("she is still sleeping SAO",
                                               meta_tags=None)
        video_ids = url.api(bestmatch=False)
        const.config.manual = False
        # API gives us 50 videos (or as requested)
        assert len(video_ids) == 50


class TestYouTubeURL:
    def test_only_music_category(self):
Ejemplo n.º 9
0
def download_single(raw_song, number=None):
    """ Logic behind downloading a song. """
    if internals.is_youtube(raw_song):
        log.debug('Input song is a YouTube URL')
        content = youtube_tools.go_pafy(raw_song, meta_tags=None)
        raw_song = slugify(content.title).replace('-', ' ')
        meta_tags = spotify_tools.generate_metadata(raw_song)
    else:
        meta_tags = spotify_tools.generate_metadata(raw_song)
        content = youtube_tools.go_pafy(raw_song, meta_tags)

    if content is None:
        log.debug('Found no matching video')
        return

    if const.args.download_only_metadata and meta_tags is None:
        log.info('Found no metadata. Skipping the download')
        return

    # "[number]. [artist] - [song]" if downloading from list
    # otherwise "[artist] - [song]"
    youtube_title = youtube_tools.get_youtube_title(content, number)
    log.info('{} ({})'.format(youtube_title, content.watchv_url))

    # generate file name of the song to download
    songname = content.title

    if meta_tags is not None:
        refined_songname = internals.format_string(const.args.file_format,
                                                   meta_tags,
                                                   slugification=True)
        log.debug('Refining songname from "{0}" to "{1}"'.format(
            songname, refined_songname))
        if not refined_songname == ' - ':
            songname = refined_songname
    else:
        log.warning('Could not find metadata')
        songname = internals.sanitize_title(songname)

    if const.args.dry_run:
        return

    if not check_exists(songname, raw_song, meta_tags):
        # deal with file formats containing slashes to non-existent directories
        songpath = os.path.join(const.args.folder, os.path.dirname(songname))
        os.makedirs(songpath, exist_ok=True)
        input_song = songname + const.args.input_ext
        output_song = songname + const.args.output_ext
        if youtube_tools.download_song(input_song, content):
            print('')
            try:
                convert.song(input_song,
                             output_song,
                             const.args.folder,
                             avconv=const.args.avconv,
                             trim_silence=const.args.trim_silence)
            except FileNotFoundError:
                encoder = 'avconv' if const.args.avconv else 'ffmpeg'
                log.warning(
                    'Could not find {0}, skipping conversion'.format(encoder))
                const.args.output_ext = const.args.input_ext
                output_song = songname + const.args.output_ext

            if not const.args.input_ext == const.args.output_ext:
                os.remove(os.path.join(const.args.folder, input_song))
            if not const.args.no_metadata and meta_tags is not None:
                metadata.embed(os.path.join(const.args.folder, output_song),
                               meta_tags)
            return True
Ejemplo n.º 10
0
def grab_single(raw_song, number=None):
    """ Logic behind downloading a song. """
    if internals.is_youtube(raw_song):
        log.debug('Input song is a YouTube URL')
        content = youtube_tools.go_pafy(raw_song, meta_tags=None)
        raw_song = slugify(content.title).replace('-', ' ')
        meta_tags = spotify_tools.generate_metadata(raw_song)
    else:
        meta_tags = spotify_tools.generate_metadata(raw_song)
        content = youtube_tools.go_pafy(raw_song, meta_tags)

    if content is None:
        log.debug('Found no matching video')
        return

    if const.args.download_only_metadata and meta_tags is None:
        log.info('Found no metadata. Skipping the download')
        return

    # "[number]. [artist] - [song]" if downloading from list
    # otherwise "[artist] - [song]"
    youtube_title = youtube_tools.get_youtube_title(content, number)
    log.info('{} ({})'.format(youtube_title, content.watchv_url))

    # generate file name of the song to download
    songname = content.title

    if meta_tags is not None:
        refined_songname = internals.generate_songname(meta_tags)
        log.debug('Refining songname from "{0}" to "{1}"'.format(songname, refined_songname))
        if not refined_songname == ' - ':
            songname = refined_songname
    else:
        log.warning('Could not find metadata')


    if const.args.dry_run:
        return

    file_name = internals.sanitize_title(songname)

    if not check_exists(file_name, raw_song, meta_tags):
        if youtube_tools.download_song(file_name, content):
            input_song = file_name + const.args.input_ext
            output_song = file_name + const.args.output_ext
            print('')

            try:
                convert.song(input_song, output_song, const.args.folder,
                             avconv=const.args.avconv)
            except FileNotFoundError:
                encoder = 'avconv' if const.args.avconv else 'ffmpeg'
                log.warning('Could not find {0}, skipping conversion'.format(encoder))
                const.args.output_ext = const.args.input_ext
                output_song = file_name + const.args.output_ext

            if not const.args.input_ext == const.args.output_ext:
                os.remove(os.path.join(const.args.folder, input_song))

            if not const.args.no_metadata and meta_tags is not None:
                metadata.embed(os.path.join(const.args.folder, output_song), meta_tags)

            if const.args.preserve_spaces and "_" in output_song:
                song_path = os.path.join(const.args.folder, output_song.replace('_', ' '))
                os.rename(os.path.join(const.args.folder, output_song), song_path)

        else:
            log.error('No audio streams available')
Ejemplo n.º 11
0
    def MP3Tagger(self):
        Caminho = self.lineEdit.text()
        if Caminho == "":
            QMessageBox.about(self, "ERRO", "Nenhum caminho especificado.")
        else:
            File = glob.glob(Caminho + "/*.mp3")
            for i in File:  # Caminho completo do arquivo com extensão
                self.label_10.setText(_translate("MainWindow", ""))
                QtWidgets.QApplication.processEvents()
                Path = os.path.dirname(i)  # Caninho completo da pasta do arquivo
                Name1 = os.path.basename(i)  # Nome do arquivo completo com extensão
                Name2 = os.path.splitext(Name1)  # Nome do arquivo dividido na extensão
                Name3 = Name2[0].split(" - ")  # Nome do arquivo divido no artista e musica
                Name4 = ''.join(i for i in Name3[0] if not i.isdigit())  # Nome da música sem os números
                print("Caminho: " + i)
                print("Name1: " + str(Name1))
                print("Name2: " + str(Name2))
                print("Name3: " + str(Name3))
                print("Name4: " + str(Name4))
                self.label_10.setText(_translate("MainWindow", "Renomeando arquivo..."))
                QtWidgets.QApplication.processEvents()
                os.rename(i, Path + "\\" + Name3[1] + " -" + Name4 + ".mp3")  # Renomeia o arquivo
                self.label_10.setText(_translate("MainWindow", "Buscando metadados no banco de dados do Spotify..."))
                QtWidgets.QApplication.processEvents()
                meta_tags = spotify_tools.generate_metadata(Name3[1] + " -" + Name4)  # Gera as tags do mp3
                if meta_tags == None:
                    continue
                else:
                    self.label_6.setText(_translate("MainWindow", str(meta_tags['artists'][0]['name'])))
                    self.label_7.setText(_translate("MainWindow", str(meta_tags['name'])))
                    self.label_8.setText(_translate("MainWindow", str(meta_tags['album']['name'])))
                    self.label_10.setText(_translate("MainWindow", "Aplicando tags..."))
                    ScriptFolder = os.path.dirname(os.path.realpath(sys.argv[0]))
                    IMG = open(ScriptFolder + "\\" + 'cover2.jpg', 'wb')
                    IMG.write(urllib.request.urlopen(meta_tags['album']['images'][0]['url']).read())
                    IMG.close()
                    time.sleep(1)
                    self.GenericCover3 = QPixmap('cover2.jpg')
                    self.GenericCover4 = self.GenericCover3.scaled(141, 141)
                    self.graphicsView.setPixmap(self.GenericCover4)
                    QtWidgets.QApplication.processEvents()
                    audiofile = MP3(Path + "\\" + Name3[1] + " -" + Name4 + ".mp3")
                    audiofile.tags = None  # Exclui qualquer tag antes de aplicar as novas (previne erro)
                    audiofile.add_tags(ID3=EasyID3)
                    audiofile['artist'] = meta_tags['artists'][0]['name']
                    audiofile['albumartist'] = meta_tags['artists'][0]['name']
                    audiofile['album'] = meta_tags['album']['name']
                    audiofile['title'] = meta_tags['name']
                    audiofile['tracknumber'] = [meta_tags['track_number'],
                                                meta_tags['total_tracks']]
                    audiofile['discnumber'] = [meta_tags['disc_number'], 0]
                    audiofile['date'] = meta_tags['release_date']
                    audiofile['originaldate'] = meta_tags['release_date']
                    audiofile['media'] = meta_tags['type']
                    audiofile['author'] = meta_tags['artists'][0]['name']
                    audiofile['lyricist'] = meta_tags['artists'][0]['name']
                    audiofile['arranger'] = meta_tags['artists'][0]['name']
                    audiofile['performer'] = meta_tags['artists'][0]['name']
                    audiofile['website'] = meta_tags['external_urls']['spotify']
                    audiofile['length'] = str(meta_tags['duration_ms'] / 1000.0)
                    if meta_tags['publisher']:
                        audiofile['encodedby'] = meta_tags['publisher']
                    if meta_tags['genre']:
                        audiofile['genre'] = meta_tags['genre']
                    if meta_tags['copyright']:
                        audiofile['copyright'] = meta_tags['copyright']
                    if meta_tags['external_ids']['isrc']:
                        audiofile['isrc'] = meta_tags['external_ids']['isrc']
                    audiofile.save(v2_version=3)

                    # For supported id3 tags:
                    # https://github.com/quodlibet/mutagen/blob/master/mutagen/id3/_frames.py
                    # Each class represents an id3 tag
                    audiofile = ID3(Path + "\\" + Name3[1] + " -" + Name4 + ".mp3")
                    year, *_ = meta_tags['release_date'].split('-')
                    audiofile['TORY'] = TORY(encoding=3, text=year)
                    audiofile['TYER'] = TYER(encoding=3, text=year)
                    audiofile['TPUB'] = TPUB(encoding=3, text=meta_tags['publisher'])
                    audiofile['COMM'] = COMM(encoding=3, text=meta_tags['external_urls']['spotify'])
                    if meta_tags['lyrics']:
                        audiofile['USLT'] = USLT(encoding=3, desc=u'Lyrics', text=meta_tags['lyrics'])
                    try:
                        albumart = urllib.request.urlopen(meta_tags['album']['images'][0]['url'])
                        audiofile['APIC'] = APIC(encoding=3, mime='image/jpeg', type=3,
                                                 desc=u'Cover', data=albumart.read())
                        albumart.close()
                    except IndexError:
                        pass
                    audiofile.save(v2_version=3)
                    self.label_10.setText(_translate("MainWindow", "Concluído."))
                    QtWidgets.QApplication.processEvents()
                    time.sleep(2)  # pausa dramática
                    # Some com os textos:
                    self.label_10.setText(_translate("MainWindow", ""))
                    QtWidgets.QApplication.processEvents()
            QMessageBox.about(self, "Concluído", "Operação concluída.")
Ejemplo n.º 12
0
def convert(self, uri, convert_count, logged_in):
    self.playlist_uri = uri
    self.convert_count = convert_count
    self.logged_in = logged_in
    self.progress = 0
    self.done = 1
    self.out_of = 0
    self.time_left = ""
    self.current_song = ""
    self.error = ""
    self.finished = False
    tracks = []
    if 'playlist' in self.playlist_uri: # playlist
        try:
            playlist = spotify_tools.fetch_playlist(self.playlist_uri)
        except spotipy.client.SpotifyException as e:
            log.error(e)
            log.debug('Token expired, generating new one and authorizing')
            new_token = spotify_tools.generate_token()
            spotify_tools.spotify = spotipy.Spotify(auth=new_token)
            playlist = spotify_tools.fetch_playlist(self.playlist_uri)
        if playlist is None:
            self.error = "Could not find playlist. Please check the playlist URL and try again."
            return
        tracks = get_tracks(playlist['tracks'])
    else: # song
        try:
            meta_tags = spotify_tools.generate_metadata(self.playlist_uri)
        except spotipy.client.SpotifyException as e:
            log.error(e)
            self.error = "Could not find song. Please check the song URL and try again."
            return
        track_name = meta_tags['name']
        track_artist = meta_tags['artists'][0]['name']
        track_url = self.playlist_uri
        tracks.append((track_name, track_artist, track_url))
    self.progress = 10

    length = len(tracks)
    time_per_song = 9
    self.out_of = length
    seconds_left = length * time_per_song
    self.time_left = get_time_left(seconds_left)
    self.update_state(state="STARTED",
                     meta={'status': '200',
                           'error': self.error,
                           'finished': self.finished,
                           'progress': self.progress, 
                           'current_song': self.current_song,
                           'done': self.done,
                           'out_of': self.out_of,
                           'time_left': self.time_left})

    log.info(u'Preparing to convert {} songs'.format(length))
    percentPerSong = 90 / length

    converted_songs = []

    for number, track in enumerate(tracks, 1):
        embed_metadata = self.logged_in
        high_quality = self.logged_in
        if self.logged_in or self.convert_count <= max_converts:
            track_name = track[0]
            track_artist = track[1]
            track_url = track[2]
            start_time = time.time()
            self.current_song = internals.sanitize_title('{} - {}'.format(track_name, track_artist))

            # either not yet converted or not fully converted
                try:
                    auxport.convert_single(track_url, folder, number, embed_metadata, high_quality)
                    time_per_song = (time.time() - start_time)
                    self.convert_count += 1
                # token expires after 1 hour
                except spotipy.client.SpotifyException as e:
                    # refresh token when it expires
                    log.error(e)
                    log.debug('Token expired, generating new one and authorizing')
                    new_token = spotify_tools.generate_token()
                    spotify_tools.spotify = spotipy.Spotify(auth=new_token)
                    auxport.convert_single(track_url, folder, number, embed_metadata, high_quality)
                    time_per_song = (time.time() - start_time)
                    self.convert_count += 1
                # detect network problems
                except (urllib.request.URLError, TypeError, IOError) as e:
                    log.error(e)
                    log.debug('Network error when converting {} by {}'.format(track_name, track_artist))
                    continue
                except Exception as e:
                    log.error(e)
                    continue
            else:
                self.convert_count += 1
            seconds_left = (length - self.done) * time_per_song
            if self.done < self.out_of:
                self.done += 1
            self.progress += percentPerSong
            self.time_left = get_time_left(seconds_left)
            self.update_state(state="PROGRESS",
                    meta={'status': '200',
                        'error': self.error,
                        'finished': self.finished,
                        'progress': self.progress, 
                        'current_song': self.current_song,
                        'done': self.done,
                        'out_of': self.out_of,
                        'time_left': self.time_left})
            log.debug('Percent:' + str(self.progress) + "%")
        else: # limit reached
            break
Ejemplo n.º 13
0
def test_spotify_title():
    expect_title = 'David André Østby - Intro'
    global meta_tags
    meta_tags = spotify_tools.generate_metadata(raw_song)
    title = internals.generate_songname(const.args.file_format, meta_tags)
    assert title == expect_title