예제 #1
0
    def __init__(self, session: spotipy.Spotify, album_id: str) -> None:
        source: Dict[str, str] = session.album(album_id)

        self._id: str = source["id"]
        self._release_date: str = str(source["release_date"])
        self._release_date_precision: str = source["release_date_precision"]
        self._session = session
    def get_album_information_from_track(sp_api: Spotify, base_track: dict):
        album_data: SpotifyAlbumDoc = object.__new__(SpotifyAlbumDoc)
        try:
            base_album: dict = base_track.get("album")
            album: dict = sp_api.album(album_id=base_album.get("id"))
            album_data: SpotifyAlbumDoc = SpotifyAlbumDoc(album=album)

        except Exception as e:
            logger.error(e)
        return album_data
예제 #3
0
class Login:
    def __init__(self, token):
        self.spo = Spotify(generate_token())

        self.req = Session()
        self.req.cookies['arl'] = token

        user_id = (self.req.get("https://www.deezer.com/").text.split(
            "'deezer_user_id': ")[1].split(",")[0])

        if user_id == "0":
            raise exceptions.BadCredentials("Wrong token: %s :(" % token)

    def get_api(self, method, api_token="null", json=None):
        params = {
            "api_version": "1.0",
            "api_token": api_token,
            "input": "3",
            "method": method
        }

        try:
            return self.req.post(api_link, params=params,
                                 json=json).json()['results']
        except:
            return self.req.post(api_link, params=params,
                                 json=json).json()['results']

    def download(self,
                 link,
                 name,
                 quality,
                 recursive_quality,
                 recursive_download,
                 datas,
                 not_interface,
                 directory,
                 zips=False):
        if not quality in qualities:
            raise exceptions.QualityNotFound(
                "The qualities have to be FLAC or MP3_320 or MP3_256 or MP3_128"
            )

        self.token = self.get_api("deezer.getUserData")['checkForm']

        def get_infos(method, json):
            infos = None

            while not "MD5_ORIGIN" in str(infos):
                infos = self.get_api(method, self.token, json)

            return infos

        def ultimatum(infos, datas, name, quality):
            extension = ".mp3"
            ids = infos['SNG_ID']
            key = "FILESIZE_" + quality

            if int(infos[key]) > 0 and quality == "FLAC":
                quality = "9"
                extension = ".flac"
                qualit = "FLAC"

            elif int(infos[key]) > 0 and quality == "MP3_320":
                quality = "3"
                qualit = "320"

            elif int(infos[key]) > 0 and quality == "MP3_256":
                quality = "5"
                qualit = "256"

            elif int(infos[key]) > 0 and quality == "MP3_128":
                quality = "1"
                qualit = "128"

            else:
                if not recursive_quality:
                    raise exceptions.QualityNotFound(
                        "The quality chosen can't be downloaded")

                for a in qualities:
                    if int(infos['FILESIZE_' + a]) > 0:
                        quality = qualities[a]['quality']
                        extension = qualities[a]['extension']
                        qualit = qualities[a]['qualit']
                        break
                    else:
                        if a == "MP3_128":
                            raise exceptions.TrackNotFound(
                                "There isn't any quality avalaible for download this song: %s"
                                % name)

            name += " ({}){}".format(qualit, extension)

            if os.path.isfile(name):
                if recursive_download:
                    return name

                ans = input(
                    "Track %s already exists, do you want to redownload it?(y or n):"
                    % name)

                if not ans in answers:
                    return name

            try:
                md5 = infos['FALLBACK']['MD5_ORIGIN']
            except KeyError:
                md5 = infos['MD5_ORIGIN']

            hashs = genurl(md5, quality, ids, infos['MEDIA_VERSION'])

            try:
                crypt = request(
                    "https://e-cdns-proxy-{}.dzcdn.net/mobile/1/{}".format(
                        md5[0], hashs))
            except IndexError:
                raise exceptions.TrackNotFound("Track: %s not found:(" % name)

            if len(crypt.content) == 0:
                raise exceptions.TrackNotFound(
                    "Something is wrong with %s :(" % name)

            encry = open(name, "wb")
            encry.write(crypt.content)
            encry.close()
            decry = open(name, "wb")

            decryptfile(crypt.iter_content(2048), calcbfkey(ids), decry)

            write_tags(name, add_more_tags(datas, infos, ids))

            return name

        def add_more_tags(datas, infos, ids):
            json = {"sng_id": ids}

            try:
                datas['author'] = " & ".join(
                    infos['SNG_CONTRIBUTORS']['author'])
            except:
                datas['author'] = ""

            try:
                datas['composer'] = " & ".join(
                    infos['SNG_CONTRIBUTORS']['composer'])
            except:
                datas['composer'] = ""

            try:
                datas['lyricist'] = " & ".join(
                    infos['SNG_CONTRIBUTORS']['lyricist'])
            except:
                datas['lyricist'] = ""

            try:
                datas['version'] = infos['VERSION']
            except KeyError:
                datas['version'] = ""

            need = self.get_api("song.getLyrics", self.token, json)

            try:
                datas['lyric'] = need['LYRICS_TEXT']
                datas['copyright'] = need['LYRICS_COPYRIGHTS']
                datas['lyricist'] = need['LYRICS_WRITERS']
            except KeyError:
                datas['lyric'] = ""
                datas['copyright'] = ""
                datas['lyricist'] = ""

            return datas

        ids = link.split("/")[-1]

        if "track" in link:
            json = {"sng_id": ids}

            infos = get_infos(method_get_track, json)
            image = choose_img(infos['ALB_PICTURE'])
            datas['image'] = image
            song = "{} - {}".format(datas['music'], datas['artist'])

            if not not_interface:
                print("Downloading: %s" % song)

            try:
                nams = ultimatum(infos, datas, name, quality)
            except exceptions.TrackNotFound:
                url = request(
                    "https://api.deezer.com/search/track/?q=%s" %
                    song.replace("#", ""), True).json()

                try:
                    for b in range(url['total'] + 1):
                        if url['data'][b]['title'] == datas['music'] or datas[
                                'music'] in url['data'][b]['title_short']:
                            URL = url['data'][b]['link']
                            break
                except IndexError:
                    raise exceptions.TrackNotFound("Track not found: %s" %
                                                   song)

                json = {"sng_id": URL.split("/")[-1]}

                infos = get_infos(method_get_track, json)
                nams = ultimatum(infos, datas, name, quality)

            return nams

        nams = []
        detas = {}
        zip_name = ""
        quali = ""

        json = {"alb_id": ids, "nb": -1}

        infos = get_infos(method_get_album, json)['data']

        image = choose_img(infos[0]['ALB_PICTURE'])

        detas['image'] = image
        detas['album'] = datas['album']
        detas['year'] = datas['year']
        detas['genre'] = datas['genre']
        detas['ar_album'] = datas['ar_album']
        detas['label'] = datas['label']

        for a in tqdm(range(len(name)), disable=not_interface):
            detas['music'] = datas['music'][a]
            detas['artist'] = datas['artist'][a]
            detas['tracknum'] = datas['tracknum'][a]
            detas['discnum'] = datas['discnum'][a]
            detas['bpm'] = datas['bpm'][a]
            detas['gain'] = datas['gain'][a]
            detas['duration'] = datas['duration'][a]
            detas['isrc'] = datas['isrc'][a]
            song = "{} - {}".format(detas['music'], detas['artist'])

            try:
                nams.append(ultimatum(infos[a], detas, name[a], quality))
            except exceptions.TrackNotFound:
                try:
                    url = request(
                        "https://api.deezer.com/search/track/?q=%s" %
                        song.replace("#", ""), True).json()

                    for b in range(url['total'] + 1):
                        if url['data'][b]['title'] == detas['music'] or detas[
                                'music'] in url['data'][b]['title_short']:
                            URL = url['data'][b]['link']
                            break

                    json = {"sng_id": URL.split("/")[-1]}

                    nams.append(
                        ultimatum(get_infos(method_get_track, json), detas,
                                  name[a], quality))
                except (exceptions.TrackNotFound, IndexError,
                        exceptions.InvalidLink):
                    nams.append(name[a])
                    print("Track not found: %s :(" % song)
                    continue

            quali = (nams[a].split("(")[-1].split(")")[0])

        if zips:
            zip_name = ("%s%s (%s).zip" %
                        (directory, directory.split("/")[-2], quali))

            create_zip(zip_name, nams)

        return nams, zip_name

    def download_trackdee(self,
                          URL,
                          output=stock_output + "/",
                          quality=stock_quality,
                          recursive_quality=stock_recursive_quality,
                          recursive_download=stock_recursive_download,
                          not_interface=stock_not_interface):
        datas = {}
        URL = URL.split("?utm")[0]
        URL1 = "https://www.deezer.com/track/%s" % URL.split("/")[-1]
        URL2 = "https://api.deezer.com/track/%s" % URL.split("/")[-1]
        url = request(URL2, True).json()

        url1 = request("http://api.deezer.com/album/%d" % url['album']['id'],
                       True).json()

        datas['music'] = url['title']
        array = []

        for a in url['contributors']:
            if a['name'] != "":
                array.append(a['name'])

        array.append(url['artist']['name'])

        datas['artist'] = artist_sort(array)
        datas['album'] = url1['title']
        datas['tracknum'] = str(url['track_position'])
        datas['discnum'] = str(url['disk_number'])
        datas['year'] = url['release_date']
        datas['genre'] = []

        try:
            for a in url1['genres']['data']:
                datas['genre'].append(a['name'])
        except KeyError:
            pass

        datas['genre'] = " & ".join(datas['genre'])
        datas['ar_album'] = []

        for a in url1['contributors']:
            if a['role'] == "Main":
                datas['ar_album'].append(a['name'])

        datas['ar_album'] = " & ".join(datas['ar_album'])
        datas['label'] = url1['label']
        datas['bpm'] = str(url['bpm'])
        datas['gain'] = str(url['gain'])
        datas['duration'] = str(url['duration'])
        datas['isrc'] = url['isrc']
        album = var_excape(datas['album'])

        directory = ("%s%s %s/" % (output, album, url1['upc']))

        check_dir(directory)

        name = ("%s%s CD %s TRACK %s" %
                (directory, album, datas['discnum'], datas['tracknum']))

        name = self.download(URL, name, quality, recursive_quality,
                             recursive_download, datas, not_interface,
                             directory)

        return name

    def download_albumdee(self,
                          URL,
                          output=stock_output + "/",
                          quality=stock_quality,
                          recursive_quality=stock_recursive_quality,
                          recursive_download=stock_recursive_download,
                          not_interface=stock_not_interface,
                          zips=stock_zip):
        datas = {}
        datas['music'] = []
        datas['artist'] = []
        datas['tracknum'] = []
        datas['discnum'] = []
        datas['bpm'] = []
        datas['gain'] = []
        datas['duration'] = []
        datas['isrc'] = []
        names = []
        array = []
        URL = URL.split("?utm")[0]
        URL1 = "https://www.deezer.com/album/%s" % URL.split("/")[-1]
        URL2 = "https://api.deezer.com/album/%s" % URL.split("/")[-1]
        url = request(URL2, True).json()
        datas['album'] = url['title']
        datas['label'] = url['label']
        datas['year'] = url['release_date']
        datas['genre'] = []

        try:
            for a in url['genres']['data']:
                datas['genre'].append(a['name'])
        except KeyError:
            pass

        datas['genre'] = " & ".join(datas['genre'])
        datas['ar_album'] = []

        for a in url['contributors']:
            if a['role'] == "Main":
                datas['ar_album'].append(a['name'])

        datas['ar_album'] = " & ".join(datas['ar_album'])
        album = var_excape(datas['album'])

        directory = ("%s%s %s/" % (output, album, url['upc']))

        for a in url['tracks']['data']:
            del array[:]
            datas['music'].append(a['title'])

            ur = request("https://api.deezer.com/track/%d" % a['id'],
                         True).json()

            discnum = str(ur['disk_number'])
            tracknum = str(ur['track_position'])

            names.append("%s%s CD %s TRACK %s" %
                         (directory, album, discnum, tracknum))

            datas['tracknum'].append(tracknum)
            datas['discnum'].append(discnum)

            datas['bpm'].append(str(ur['bpm']))

            datas['gain'].append(str(ur['gain']))

            datas['duration'].append(str(ur['duration']))

            datas['isrc'].append(ur['isrc'])

            for a in ur['contributors']:
                if a['name'] != "":
                    array.append(a['name'])

            array.append(ur['artist']['name'])

            datas['artist'].append(artist_sort(array))

        check_dir(directory)

        names, zip_name = self.download(URL, names, quality, recursive_quality,
                                        recursive_download, datas,
                                        not_interface, directory, zips)

        if zips:
            return names, zip_name

        return names

    def download_playlistdee(self,
                             URL,
                             output=stock_output + "/",
                             quality=stock_quality,
                             recursive_quality=True,
                             recursive_download=True,
                             not_interface=stock_not_interface,
                             zips=stock_zip):
        array = []
        URL = URL.split("?utm")[0]
        ids = URL.split("/")[-1]

        url = request("https://api.deezer.com/playlist/%s" % ids, True).json()

        for a in url['tracks']['data']:
            try:
                array.append(
                    self.download_trackdee(a['link'], output, quality,
                                           recursive_quality,
                                           recursive_download, not_interface))
            except (exceptions.TrackNotFound, exceptions.NoDataApi):
                song = "{} - {}".format(a['title'], a['artist']['name'])
                print("Track not found: %s" % song)
                array.append(song)

        if zips:
            zip_name = "{}playlist {}.zip".format(output, ids)
            create_zip(zip_name, array)
            return array, zip_name

        return array

    def download_trackspo(self,
                          URL,
                          output=stock_output + "/",
                          quality=stock_quality,
                          recursive_quality=stock_recursive_quality,
                          recursive_download=stock_recursive_download,
                          not_interface=stock_not_interface):
        URL = URL.split("?")[0]

        try:
            url = self.spo.track(URL)
        except Exception as a:
            if not "The access token expired" in str(a):
                raise exceptions.InvalidLink("Invalid link ;)")

            self.spo = Spotify(generate_token())

            url = self.spo.track(URL)

        isrc = url['external_ids']['isrc']

        url = request("https://api.deezer.com/track/isrc:%s" % isrc,
                      True).json()

        name = self.download_trackdee(url['link'], output, quality,
                                      recursive_quality, recursive_download,
                                      not_interface)

        return name

    def download_albumspo(self,
                          URL,
                          output=stock_output + "/",
                          quality=stock_quality,
                          recursive_quality=stock_recursive_quality,
                          recursive_download=stock_recursive_download,
                          not_interface=stock_not_interface,
                          zips=stock_zip):
        URL = URL.split("?")[0]

        try:
            tracks = self.spo.album(URL)
        except Exception as a:
            if not "The access token expired" in str(a):
                raise exceptions.InvalidLink("Invalid link ;)")

            self.spo = Spotify(generate_token())

            tracks = self.spo.album(URL)

        tot = tracks['total_tracks']

        try:
            upc = tracks['external_ids']['upc']

            while upc[0] == "0":
                upc = upc[1:]

            url = request("https://api.deezer.com/album/upc:%s" % upc).json()

            names = self.download_albumdee(url['link'], output, quality,
                                           recursive_quality,
                                           recursive_download, not_interface,
                                           zips)
        except KeyError:
            search = tot // 5

            try:
                url = self.spo.track(tracks['tracks']['items'][search]
                                     ['external_urls']['spotify'])
            except:
                self.spo = Spotify(generate_token())

                url = self.spo.track(tracks['tracks']['items'][search]
                                     ['external_urls']['spotify'])

            isrc = url['external_ids']['isrc']

            try:
                ids = request("https://api.deezer.com/track/isrc:%s" % isrc,
                              True).json()['album']['id']

                tracks = request("https://api.deezer.com/album/%d" % ids,
                                 True).json()

                if tot != tracks['nb_tracks']:
                    raise exceptions.TrackNotFound("")

                names = self.download_albumdee(tracks['link'], output, quality,
                                               recursive_quality,
                                               recursive_download,
                                               not_interface, zips)
            except (exceptions.TrackNotFound, exceptions.NoDataApi):
                raise exceptions.AlbumNotFound("Album %s not found :(" %
                                               tracks['name'])

        return names

    def download_playlistspo(self,
                             URL,
                             output=stock_output + "/",
                             quality=stock_quality,
                             recursive_quality=stock_recursive_quality,
                             recursive_download=stock_recursive_download,
                             not_interface=stock_not_interface,
                             zips=stock_zip):
        array = []
        URL = URL.split("?")[0].split("/")

        try:
            tracks = self.spo.user_playlist_tracks(URL[-3],
                                                   playlist_id=URL[-1])
        except Exception as a:
            if not "The access token expired" in str(a):
                raise exceptions.InvalidLink("Invalid link ;)")

            self.spo = Spotify(generate_token())

            tracks = self.spo.user_playlist_tracks(URL[-3],
                                                   playlist_id=URL[-1])

        for a in tracks['items']:
            try:
                array.append(
                    self.download_trackspo(
                        a['track']['external_urls']['spotify'], output,
                        quality, recursive_quality, recursive_download,
                        not_interface))
            except:
                print("Track not found :(")
                array.append("None")

        if tracks['total'] != 100:
            for a in range(tracks['total'] // 100):
                try:
                    tracks = self.spo.next(tracks)
                except:
                    self.spo = Spotify(generate_token())

                    tracks = self.spo.next(tracks)

                for a in tracks['items']:
                    try:
                        array.append(
                            self.download_trackspo(
                                a['track']['external_urls']['spotify'], output,
                                quality, recursive_quality, recursive_download,
                                not_interface))
                    except:
                        print("Track not found :(")
                        array.append("None")

        if zips:
            zip_name = "{}playlist {}.zip".format(output, URL[-1])
            create_zip(zip_name, array)
            return array, zip_name

        return array

    def download_name(self,
                      artist,
                      song,
                      output=stock_output + "/",
                      quality=stock_quality,
                      recursive_quality=stock_recursive_quality,
                      recursive_download=stock_recursive_download,
                      not_interface=stock_not_interface):
        query = "track:{} artist:{}".format(song, artist)

        try:
            search = self.spo.search(query)
        except:
            self.spo = Spotify(generate_token())

            search = self.spo.search(query)

        try:
            return self.download_trackspo(
                search['tracks']['items'][0]['external_urls']['spotify'],
                output, quality, recursive_quality, recursive_download,
                not_interface)
        except IndexError:
            raise exceptions.TrackNotFound("Track not found: :(")
class AuthTestSpotipy(unittest.TestCase):
    """
    These tests require client authentication - provide client credentials
    using the following environment variables

    ::

        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
    """

    playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
    four_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB", "4VrWlk8IQxevMvERoX08iC",
        "http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"
    ]

    two_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB"
    ]

    other_tracks = [
        "spotify:track:2wySlB6vMzCbQrRnNGOYKa",
        "spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
        "spotify:track:1PB7gRWcvefzu7t3LJLUlf"
    ]

    bad_id = 'BAD_ID'

    creep_urn = 'spotify:track:6b2oQwSGFkzsMtQruIWm2p'
    creep_id = '6b2oQwSGFkzsMtQruIWm2p'
    creep_url = 'http://open.spotify.com/track/6b2oQwSGFkzsMtQruIWm2p'
    el_scorcho_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ'
    el_scorcho_bad_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQK'
    pinkerton_urn = 'spotify:album:04xe676vyiTeYNXw15o9jT'
    weezer_urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
    pablo_honey_urn = 'spotify:album:6AZv3m27uyRxi8KyJSfUxL'
    radiohead_urn = 'spotify:artist:4Z8W4fKeB5YxbusRsdQVPb'
    angeles_haydn_urn = 'spotify:album:1vAbqAeuJVWNAe7UR00bdM'
    heavyweight_urn = 'spotify:show:5c26B28vZMN8PG0Nppmn5G'
    heavyweight_id = '5c26B28vZMN8PG0Nppmn5G'
    heavyweight_url = 'https://open.spotify.com/show/5c26B28vZMN8PG0Nppmn5G'
    reply_all_urn = 'spotify:show:7gozmLqbcbr6PScMjc0Zl4'
    heavyweight_ep1_urn = 'spotify:episode:68kq3bNz6hEuq8NtdfwERG'
    heavyweight_ep1_id = '68kq3bNz6hEuq8NtdfwERG'
    heavyweight_ep1_url = 'https://open.spotify.com/episode/68kq3bNz6hEuq8NtdfwERG'
    reply_all_ep1_urn = 'spotify:episode:1KHjbpnmNpFmNTczQmTZlR'

    @classmethod
    def setUpClass(self):
        self.spotify = Spotify(
            client_credentials_manager=SpotifyClientCredentials())
        self.spotify.trace = False

    def test_audio_analysis(self):
        result = self.spotify.audio_analysis(self.four_tracks[0])
        assert ('beats' in result)

    def test_audio_features(self):
        results = self.spotify.audio_features(self.four_tracks)
        self.assertTrue(len(results) == len(self.four_tracks))
        for track in results:
            assert ('speechiness' in track)

    def test_audio_features_with_bad_track(self):
        bad_tracks = ['spotify:track:bad']
        input = self.four_tracks + bad_tracks
        results = self.spotify.audio_features(input)
        self.assertTrue(len(results) == len(input))
        for track in results[:-1]:
            if track is not None:
                assert ('speechiness' in track)
        self.assertTrue(results[-1] is None)

    def test_recommendations(self):
        results = self.spotify.recommendations(seed_tracks=self.four_tracks,
                                               min_danceability=0,
                                               max_loudness=0,
                                               target_popularity=50)
        self.assertTrue(len(results['tracks']) == 20)

    def test_artist_urn(self):
        artist = self.spotify.artist(self.radiohead_urn)
        self.assertTrue(artist['name'] == 'Radiohead')

    def test_artists(self):
        results = self.spotify.artists([self.weezer_urn, self.radiohead_urn])
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 2)

    def test_album_urn(self):
        album = self.spotify.album(self.pinkerton_urn)
        self.assertTrue(album['name'] == 'Pinkerton')

    def test_album_tracks(self):
        results = self.spotify.album_tracks(self.pinkerton_urn)
        self.assertTrue(len(results['items']) == 10)

    def test_album_tracks_many(self):
        results = self.spotify.album_tracks(self.angeles_haydn_urn)
        tracks = results['items']
        total, received = results['total'], len(tracks)
        while received < total:
            results = self.spotify.album_tracks(self.angeles_haydn_urn,
                                                offset=received)
            tracks.extend(results['items'])
            received = len(tracks)

        self.assertEqual(received, total)

    def test_albums(self):
        results = self.spotify.albums(
            [self.pinkerton_urn, self.pablo_honey_urn])
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']) == 2)

    def test_track_urn(self):
        track = self.spotify.track(self.creep_urn)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_id(self):
        track = self.spotify.track(self.creep_id)
        self.assertTrue(track['name'] == 'Creep')
        self.assertTrue(track['popularity'] > 0)

    def test_track_url(self):
        track = self.spotify.track(self.creep_url)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_bad_urn(self):
        try:
            self.spotify.track(self.el_scorcho_bad_urn)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_tracks(self):
        results = self.spotify.tracks([self.creep_url, self.el_scorcho_urn])
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 2)

    def test_artist_top_tracks(self):
        results = self.spotify.artist_top_tracks(self.weezer_urn)
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 10)

    def test_artist_related_artists(self):
        results = self.spotify.artist_related_artists(self.weezer_urn)
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 20)
        for artist in results['artists']:
            if artist['name'] == 'Jimmy Eat World':
                found = True
        self.assertTrue(found)

    def test_artist_search(self):
        results = self.spotify.search(q='weezer', type='artist')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_search_with_market(self):
        results = self.spotify.search(q='weezer', type='artist', market='GB')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_search_with_multiple_markets(self):
        total = 5
        countries_list = ['GB', 'US', 'AU']
        countries_tuple = ('GB', 'US', 'AU')

        results_multiple = self.spotify.search_markets(q='weezer',
                                                       type='artist',
                                                       markets=countries_list)
        results_all = self.spotify.search_markets(q='weezer', type='artist')
        results_tuple = self.spotify.search_markets(q='weezer',
                                                    type='artist',
                                                    markets=countries_tuple)
        results_limited = self.spotify.search_markets(q='weezer',
                                                      limit=3,
                                                      type='artist',
                                                      markets=countries_list,
                                                      total=total)

        self.assertTrue(
            all('artists' in results_multiple[country]
                for country in results_multiple))
        self.assertTrue(
            all('artists' in results_all[country] for country in results_all))
        self.assertTrue(
            all('artists' in results_tuple[country]
                for country in results_tuple))
        self.assertTrue(
            all('artists' in results_limited[country]
                for country in results_limited))

        self.assertTrue(
            all(
                len(results_multiple[country]['artists']['items']) > 0
                for country in results_multiple))
        self.assertTrue(
            all(
                len(results_all[country]['artists']['items']) > 0
                for country in results_all))
        self.assertTrue(
            all(
                len(results_tuple[country]['artists']['items']) > 0
                for country in results_tuple))
        self.assertTrue(
            all(
                len(results_limited[country]['artists']['items']) > 0
                for country in results_limited))

        self.assertTrue(
            all(results_multiple[country]['artists']['items'][0]['name'] ==
                'Weezer' for country in results_multiple))
        self.assertTrue(
            all(results_all[country]['artists']['items'][0]['name'] == 'Weezer'
                for country in results_all))
        self.assertTrue(
            all(results_tuple[country]['artists']['items'][0]['name'] ==
                'Weezer' for country in results_tuple))
        self.assertTrue(
            all(results_limited[country]['artists']['items'][0]['name'] ==
                'Weezer' for country in results_limited))

        total_limited_results = 0
        for country in results_limited:
            total_limited_results += len(
                results_limited[country]['artists']['items'])
        self.assertTrue(total_limited_results <= total)

    def test_artist_albums(self):
        results = self.spotify.artist_albums(self.weezer_urn)
        self.assertTrue('items' in results)
        self.assertTrue(len(results['items']) > 0)

        found = False
        for album in results['items']:
            if album['name'] == 'Hurley':
                found = True

        self.assertTrue(found)

    def test_search_timeout(self):
        client_credentials_manager = SpotifyClientCredentials()
        sp = spotipy.Spotify(
            requests_timeout=0.01,
            client_credentials_manager=client_credentials_manager)

        # depending on the timing or bandwidth, this raises a timeout or connection error"
        self.assertRaises(
            (requests.exceptions.Timeout, requests.exceptions.ConnectionError),
            lambda: sp.search(q='my*', type='track'))

    def test_album_search(self):
        results = self.spotify.search(q='weezer pinkerton', type='album')
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']['items']) > 0)
        self.assertTrue(
            results['albums']['items'][0]['name'].find('Pinkerton') >= 0)

    def test_track_search(self):
        results = self.spotify.search(q='el scorcho weezer', type='track')
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']['items']) > 0)
        self.assertTrue(results['tracks']['items'][0]['name'] == 'El Scorcho')

    def test_user(self):
        user = self.spotify.user(user='******')
        self.assertTrue(user['uri'] == 'spotify:user:plamere')

    def test_track_bad_id(self):
        try:
            self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_show_urn(self):
        show = self.spotify.show(self.heavyweight_urn, market="US")
        self.assertTrue(show['name'] == 'Heavyweight')

    def test_show_id(self):
        show = self.spotify.show(self.heavyweight_id, market="US")
        self.assertTrue(show['name'] == 'Heavyweight')

    def test_show_url(self):
        show = self.spotify.show(self.heavyweight_url, market="US")
        self.assertTrue(show['name'] == 'Heavyweight')

    def test_show_bad_urn(self):
        with self.assertRaises(SpotifyException):
            self.spotify.show("bogus_urn", market="US")

    def test_shows(self):
        results = self.spotify.shows(
            [self.heavyweight_urn, self.reply_all_urn], market="US")
        self.assertTrue('shows' in results)
        self.assertTrue(len(results['shows']) == 2)

    def test_show_episodes(self):
        results = self.spotify.show_episodes(self.heavyweight_urn, market="US")
        self.assertTrue(len(results['items']) > 1)

    def test_show_episodes_many(self):
        results = self.spotify.show_episodes(self.reply_all_urn, market="US")
        episodes = results['items']
        total, received = results['total'], len(episodes)
        while received < total:
            results = self.spotify.show_episodes(self.reply_all_urn,
                                                 offset=received,
                                                 market="US")
            episodes.extend(results['items'])
            received = len(episodes)

        self.assertEqual(received, total)

    def test_episode_urn(self):
        episode = self.spotify.episode(self.heavyweight_ep1_urn, market="US")
        self.assertTrue(episode['name'] == '#1 Buzz')

    def test_episode_id(self):
        episode = self.spotify.episode(self.heavyweight_ep1_id, market="US")
        self.assertTrue(episode['name'] == '#1 Buzz')

    def test_episode_url(self):
        episode = self.spotify.episode(self.heavyweight_ep1_url, market="US")
        self.assertTrue(episode['name'] == '#1 Buzz')

    def test_episode_bad_urn(self):
        with self.assertRaises(SpotifyException):
            self.spotify.episode("bogus_urn", market="US")

    def test_episodes(self):
        results = self.spotify.episodes(
            [self.heavyweight_ep1_urn, self.reply_all_ep1_urn], market="US")
        self.assertTrue('episodes' in results)
        self.assertTrue(len(results['episodes']) == 2)

    def test_unauthenticated_post_fails(self):
        with self.assertRaises(SpotifyException) as cm:
            self.spotify.user_playlist_create("spotify",
                                              "Best hits of the 90s")
        self.assertTrue(cm.exception.http_status == 401
                        or cm.exception.http_status == 403)

    def test_custom_requests_session(self):
        sess = requests.Session()
        sess.headers["user-agent"] = "spotipy-test"
        with_custom_session = spotipy.Spotify(
            client_credentials_manager=SpotifyClientCredentials(),
            requests_session=sess)
        self.assertTrue(
            with_custom_session.user(user="******")["uri"] == "spotify:user:akx")
        sess.close()

    def test_force_no_requests_session(self):
        with_no_session = spotipy.Spotify(
            client_credentials_manager=SpotifyClientCredentials(),
            requests_session=False)
        self.assertNotIsInstance(with_no_session._session, requests.Session)
        user = with_no_session.user(user="******")
        self.assertEqual(user["uri"], "spotify:user:akx")
예제 #5
0
    async def spotify(self, ctx: Context, url: str = None, type_: str = None):
        if not url:
            return await ctx.send(embed=ErrorEmbed(
                author=ctx.author,
                title=':x: Missing Spotify link or ID'
            ))
        elif not type_:
            try:
                type_ = url.split('&')[0].split('?')[0].split('/')[3]
            except IndexError:
                pass

        if type_ == 'user':
            return await ctx.send(embed=ErrorEmbed(
                author=ctx.author,
                title=':x: User profiles are not supported',
                description='...yet?'
            ))
        elif type_ not in ['track', 'album', 'artist', 'playlist']:
            return await ctx.send(embed=ErrorEmbed(
                author=ctx.author,
                title=':x: What is this?',
                description='Is it `track`, `album`, `artist` or `playlist`?'
            ))

        if url.startswith(('http://open.spotify.com', 'https://open.spotify.com')):
            url = url.split('?')[0].split('/')[-1]

        type_ = type_.lower()

        try:
            sp = Spotify(auth_manager=SpotifyClientCredentials(
                client_id=spotify_client_id(),
                client_secret=spotify_client_secret()
            ))
        except SpotifyOauthError:
            sp = None

        if not sp:
            return await ctx.send(embed=ErrorEmbed(
                author=ctx.author,
                title=':x: Unable to connect to Spotify!'
            ))

        result = error_code = None
        em = SuccessEmbed(
            author=ctx.author
        ).set_author(
            name=f'{ctx.author.display_name} shared a{"n" if type_[0] == "a" else ""} {type_}:',
            icon_url=ctx.author.avatar_url
        )

        if type_ == 'track':
            try:
                result = sp.track(url)
            except SpotifyException as e:
                error_code = int(e.http_status)
        elif type_ == 'album':
            try:
                result = sp.album(url)
            except SpotifyException as e:
                error_code = int(e.http_status)
        elif type_ == 'playlist':
            try:
                result = sp.playlist(url)
            except SpotifyException as e:
                error_code = int(e.http_status)
        elif type_ == 'artist':
            try:
                result = sp.artist(url)
            except SpotifyException as e:
                error_code = int(e.http_status)
        else:
            return await ctx.send(embed=ErrorEmbed(
                author=ctx.author,
                title=':x: Unknown object type',
                description='Check `>help` for valid object types.'
            ))

        if error_code:
            if error_code == 400:
                d = 'Invalid ID or URL.'
            elif error_code == 429:
                d = 'Unable to do that now, please try again in 5 minutes.'
            elif str(error_code).startswith('5'):
                d = 'Spotify is not responding.'
            else:
                d = 'Unknown error. Please try again in a few minutes and please make sure URL or ID is valid.'
            return await ctx.send(embed=ErrorEmbed(
                author=ctx.author,
                title=':x: An error occurred!',
                description=d
            ))
        elif not result:
            return await ctx.send(embed=ErrorEmbed(
                author=ctx.author,
                title=':x: Unable to find anything on Spotify',
                description='Probably URL/ID is wrong.'
            ))

        title = result['name']

        # Artists
        if type_ not in ['artist', 'playlist']:
            artists = list(map(lambda x: [x['name'], x['external_urls']['spotify']], result['artists']))
        elif type_ in ['playlist']:
            artists = [[result['owner']['display_name'], result['owner']['external_urls']['spotify']]]
        else:
            artists = None

        # Released
        if type_ == 'track':
            released = result['album']['release_date']
        elif type_ == 'album':
            released = result['release_date']
        else:
            released = None

        # Genres
        if type_ in ['artist', 'album']:
            genres = ', '.join(result['genres']) or 'Not specified'
        else:
            genres = None

        ex_url = result['external_urls']['spotify']
        thumbnail = result['album']['images'][0]['url'] if type_ == 'track' else result['images'][0]['url']

        # Title
        if title:
            em.add_field(
                name='Name' if type_ in ['artist'] else 'Title',
                value=title
            )

        # Author / Artist(s)
        if artists:
            em.add_field(
                name='Author' if type_ == 'playlist' else 'Artist' if len(artists) == 1 else 'Artists',
                value=', '.join(map(lambda x: f'[{x[0]}]({x[1]} "Check it on Spotify")', artists))
            )

        # Followers
        if type_ in ['artist', 'playlist']:
            em.add_field(
                name='Followers',
                value=result['followers']['total']
            )

        # Album
        if type_ == 'track':
            em.add_field(
                name='Album',
                value=f'[{result["name"]}]({result["album"]["external_urls"]["spotify"]} "Check it on Spotify")'
            )

        # Released
        if released:
            em.add_field(
                name='Released',
                value=released
            )

        # Tracks
        if type_ in ['playlist', 'album']:
            em.add_field(
                name='Tracks',
                value=str(result['tracks']['total'])
            )

        # Genres
        if genres:
            em.add_field(
                name='Genres',
                value=genres
            )

        # Popularity
        if type_ in ['track', 'artist', 'album']:
            em.add_field(
                name='Popularity',
                value=str(result['popularity'])
            )

        # Label
        elif type_ == 'album':
            em.add_field(
                name='Label',
                value=result['label']
            )

        # Spotify link
        if ex_url:
            em.add_field(
                name='Spotify',
                value=ex_url,
                inline=False
            )

        # YouTube link
        if type_ == 'track':
            # Lookup YouTube
            query = '{} {}'.format(result['name'], ' '.join(map(lambda x: x['name'], result['artists'])))
            yt = SearchVideos(
                query,
                mode='dict',
                max_results=1
            ).result()
            # noinspection PyTypeChecker
            yt = yt['search_result'][0]['link'] if yt else None
            em.add_field(
                name='YouTube',
                value=yt,
                inline=False
            )

        # Thumbnail
        if thumbnail:
            em.set_thumbnail(
                url=thumbnail
            )

        await ctx.send(embed=em)

        try:
            await ctx.message.delete()
        except Forbidden or NotFound or HTTPException:
            pass
예제 #6
0
def Link(link, chat_id, quality, message_id):
    global spo
    global del1

    del1 += 1
    done = 0
    quali = quality.split("MP3_")[-1]
    link = link.split("?")[0]
    ids = link.split("/")[-1]

    try:
        if "track/" in link:
            if "spotify" in link:
                try:
                    url = spo.track(link)
                except Exception as a:
                    if not "The access token expired" in str(a):
                        sendMessage(chat_id,
                                    "Invalid link %s ;)" % link,
                                    reply_to_message_id=message_id)

                        delete(chat_id)
                        return

                    spo = Spotify(generate_token())

                    url = spo.track(link)

                try:
                    image1 = url['album']['images'][0]['url']
                except IndexError:
                    image1 = song_default_image

                name = url['name']
                artist = url['album']['artists'][0]['name']
                album = url['album']['name']
                date = url['album']['release_date']

            elif "deezer" in link:
                kind = "track"
                api_link = api_track % ids

                try:
                    url = reque(api_link, chat_id, True).json()
                except AttributeError:
                    delete(chat_id)
                    return

                image1 = check_image(url['album']['cover_xl'], ids, kind)

                name = url['title']
                artist = url['artist']['name']
                album = url['album']['title']
                date = url['album']['release_date']

            if any(a in link for a in services_supported):
                sendPhoto(chat_id,
                          image1,
                          caption=(send_image_track_query %
                                   (name, artist, album, date)))

                track(link, chat_id, quality)
            else:
                sendMessage(chat_id, not_supported_links % link)

        elif "album/" in link:
            links = []
            count = [0]

            if "spotify" in link:
                try:
                    tracks = spo.album(link)
                except Exception as a:
                    if not "The access token expired" in str(a):
                        sendMessage(chat_id,
                                    "Invalid link %s ;)" % link,
                                    reply_to_message_id=message_id)

                        delete(chat_id)
                        return

                    spo = Spotify(generate_token())

                    tracks = spo.album(link)

                try:
                    image3 = tracks['images'][2]['url']
                    image1 = tracks['images'][0]['url']
                except IndexError:
                    image3 = image_resize(song_default_image, 90)
                    image1 = song_default_image

                name = tracks['name']
                artist = tracks['artists'][0]['name']
                date = tracks['release_date']
                tot = tracks['total_tracks']

                def lazy(a):
                    count[0] += a['duration_ms']

                    links.append(a['external_urls']['spotify'])

                for a in tracks['tracks']['items']:
                    lazy(a)

                tracks = tracks['tracks']

                for a in range(tot // 50 - 1):
                    try:
                        tracks = spo.next(tracks)
                    except:
                        spo = Spotify(generate_token())

                        tracks = spo.next(tracks)

                    for a in tracks['items']:
                        lazy(a)

                count[0] //= 1000
                mode = downloa.download_albumspo

            elif "deezer" in link:
                api_link = api_album % ids
                kind = "album"

                try:
                    url = reque(api_link, chat_id, True).json()
                except AttributeError:
                    delete(chat_id)
                    return

                count[0] = url['duration']
                image1 = check_image(url['cover_xl'], ids, kind)
                image3 = image_resize(image1, 90)
                tot = url['nb_tracks']

                links = [a['link'] for a in url['tracks']['data']]

                name = url['title']
                artist = url['artist']['name']
                date = url['release_date']
                mode = downloa.download_albumdee

            if any(a in link for a in services_supported):
                if count[0] > seconds_limits_album:
                    sendMessage(
                        chat_id,
                        "If you do this again I will come to your home and I will ddos your ass :)"
                    )
                    delete(chat_id)
                    return

                message_id = sendPhoto(
                    chat_id,
                    image1,
                    caption=(send_image_album_query %
                             (name, artist, date, tot)))['message_id']

                conn = connect(db_file)
                c = conn.cursor()
                exists = []

                for a in links:
                    ids = a.split("/")[-1]
                    lins = "track/%s" % ids

                    exist = c.execute(where_query.format(lins,
                                                         quali)).fetchone()

                    if exist:
                        exists.append(exist)

                if len(exists) < len(links) // 3:
                    z = mode(link,
                             quality=quality,
                             recursive_quality=True,
                             recursive_download=True,
                             not_interface=not_interface)

                    image3 = get_image(image3)

                    for a in range(len(z)):
                        sendAudio(chat_id, z[a], links[a], image3)
                else:
                    for a in links:
                        track(a, chat_id, quality)

                done = 1
            else:
                sendMessage(chat_id, not_supported_links % link)

        elif "playlist/" in link:
            links = []

            if "spotify" in link:
                musi = link.split("/")

                try:
                    tracks = spo.user_playlist(musi[-3], musi[-1])
                except Exception as a:
                    if not "The access token expired" in str(a):
                        sendMessage(chat_id,
                                    "Invalid link ;)",
                                    reply_to_message_id=message_id)

                        delete(chat_id)
                        return

                    spo = Spotify(generate_token())

                    tracks = spo.user_playlist(musi[-3], musi[-1])

                try:
                    image1 = tracks['images'][0]['url']
                except IndexError:
                    image1 = song_default_image

                def lazy(a):
                    try:
                        links.append(a['track']['external_urls']['spotify'])
                    except (KeyError, TypeError):
                        links.append("Error :(")

                for a in tracks['tracks']['items']:
                    lazy(a)

                added = tracks['tracks']['items'][0]['added_at']
                owner = tracks['owner']['display_name']
                tot = tracks['tracks']['total']
                tracks = tracks['tracks']

                for a in range(tot // 100 - 1):
                    try:
                        tracks = spo.next(tracks)
                    except:
                        spo = Spotify(generate_token())

                        tracks = spo.next(tracks)

                    for a in tracks['items']:
                        lazy(a)

            elif "deezer" in link:
                api_link = api_playlist % ids

                try:
                    url = reque(api_link, chat_id, True).json()
                except AttributeError:
                    delete(chat_id)
                    return

                links = [a['link'] for a in url['tracks']['data']]

                image1 = url['picture_xl']
                tot = url['nb_tracks']
                added = url['creation_date']
                owner = url['creator']['name']

            if any(a in link for a in services_supported):

                if tot > max_songs:
                    sendMessage(chat_id, "F**k you")
                    delete(chat_id)
                    return

                sendPhoto(chat_id,
                          image1,
                          caption=(send_image_playlist_query %
                                   (added, owner, tot)))

                for a in links:
                    if a.startswith("http"):
                        try:
                            track(a, chat_id, quality)
                        except:
                            sendMessage(chat_id, "Cannot download %s:(" % a)
                    else:
                        sendMessage(chat_id, a)

                done = 1
            else:
                sendMessage(chat_id, not_supported_links % link)

        elif "artist/" in link:
            if "deezer" in link:
                api_link = api_artist % ids

                try:
                    url = reque(api_link, chat_id, True).json()
                except AttributeError:
                    delete(chat_id)
                    return

                keyboard = [[
                    InlineKeyboardButton(
                        queries['top']['text'],
                        callback_data=queries['top']['query'] % api_link),
                    InlineKeyboardButton(
                        queries['albums']['text'],
                        callback_data=queries['albums']['query'] % api_link)
                ],
                            [
                                InlineKeyboardButton(
                                    queries['radio']['text'],
                                    callback_data=queries['radio']['query'] %
                                    api_link),
                                InlineKeyboardButton(
                                    queries['related']['text'],
                                    callback_data=queries['related']['query'] %
                                    api_link)
                            ]]

                image1 = url['picture_xl']
                artist = url['name']
                albums = url['nb_album']
                fans = url['nb_fan']

            if any(a in link for a in services_supported[1:]):
                sendPhoto(chat_id,
                          image1,
                          caption=(send_image_artist_query %
                                   (artist, albums, fans)),
                          reply_markup=InlineKeyboardMarkup(keyboard))
            else:
                sendMessage(chat_id, not_supported_links % link)

        else:
            sendMessage(chat_id, not_supported_links % link)

    except FileNotFoundError:
        sendMessage(chat_id,
                    "Resend link please...",
                    reply_to_message_id=message_id)

    except error.TimedOut:
        sendMessage(chat_id, "Retry after a few minutes")

    except exceptions.QuotaExceeded:
        sendMessage(chat_id, "Please send the link %s again :(" % link)

    except exceptions.AlbumNotFound:
        sendMessage(chat_id, "Album %s didn't find on Deezer :(" % link)
        sendMessage(
            chat_id,
            "Try to search it throught inline mode or search the link on Deezer"
        )

    except Exception as a:
        logging.error(a)
        logging.error(quality)
        logging.error(link)

        sendMessage(
            chat_id,
            "OPS :( Something went wrong please send to @AmineSoukara this link: {} {}, if this happens again"
            .format(link, quality))

    if done == 1:
        sendMessage(chat_id,
                    end_message,
                    reply_to_message_id=message_id,
                    reply_markup=InlineKeyboardMarkup(end_keyboard))

    delete(chat_id)
예제 #7
0
def Link(link, chat_id, quality, msg):
	global spo
	global del1

	del1 += 1
	done = 0
	links1 = []
	links2 = []
	quali = quality.split("MP3_")[-1]
	link = link.split("?")[0]

	try:
		if "spotify" in link:
			if "track/" in link:
				try:
					url = spo.track(link)
				except Exception as a:
					if not "The access token expired" in str(a):
						sendMessage(
							chat_id, "Invalid link %s ;)" % link,
							reply_to_message_id = msg['message_id']
						)

						delete(chat_id)
						return

					spo = Spotify(
						generate_token()
					)

					url = spo.track(link)

				try:
					image1 = url['album']['images'][0]['url']
				except IndexError:
					image1 = "https://e-cdns-images.dzcdn.net/images/cover/1000x1000-000000-80-0-0.jpg"

				sendPhoto(
					chat_id, image1,
					caption = (
						send_image_track_query
						% (
							url['name'],
							url['album']['artists'][0]['name'],
							url['album']['name'],
							url['album']['release_date']
						)
					)
				)

				track(link, chat_id, quality)

			elif "album/" in link:
				try:
					tracks = spo.album(link)
				except Exception as a:
					if not "The access token expired" in str(a):
						sendMessage(
							chat_id, "Invalid link %s ;)" % link,
							reply_to_message_id = msg['message_id']
						)

					delete(chat_id)
					return

					spo = Spotify(
						generate_token()
					)

					tracks = spo.album(link)

				try:
					image3 = tracks['images'][2]['url']
					image2 = tracks['images'][1]['url']
					image1 = tracks['images'][0]['url']
				except IndexError:
					image3 = "https://e-cdns-images.dzcdn.net/images/cover/90x90-000000-80-0-0.jpg"
					image2 = "https://e-cdns-images.dzcdn.net/images/cover/320x320-000000-80-0-0.jpg"
					image1 = "https://e-cdns-images.dzcdn.net/images/cover/1000x1000-000000-80-0-0.jpg"

				tot = tracks['total_tracks']
				conn = connect(db_file)
				c = conn.cursor()
				lin = "album/%s" % link.split("/")[-1]
				count = [0]

				sendPhoto(
					chat_id, image1,
					caption = (
						send_image_album_query
						% (
							tracks['name'],
							tracks['artists'][0]['name'],
							tracks['release_date'],
							tot
						)
					)
				)

				def lazy(a):
					count[0] += a['duration_ms']
					lin = "track/%s" % a['external_urls']['spotify'].split("/")[-1]

					c.execute(
						where_query.format(lin, quali)
					)

					links2.append(lin)

					if c.fetchone():
						links1.append(lin)

				for a in tracks['tracks']['items']:
					lazy(a)

				tracks = tracks['tracks']

				if tot != 50:
					for a in range(tot // 50):
						try:
							tracks = spo.next(tracks)
						except:
							spo = Spotify(
								generate_token()
							)

							tracks = spo.next(tracks)

						for a in tracks['items']:
							lazy(a)

				conn.close()

				if (count[0] / 1000) > 40000:
					sendMessage(chat_id, "If you do this again I will come to your home and I will ddos your ass :)")
					delete(chat_id)
					return

				if len(links1) != tot:
					z = downloa.download_albumspo(
						link,
						quality = quality,
						recursive_quality = True,
						recursive_download = True,
						not_interface = True
					)
				else:
					for a in links2:
						track(a, chat_id, quality)

				done = 1

			elif "playlist/" in link:
				musi = link.split("/")

				try:
					tracks = spo.user_playlist(musi[-3], musi[-1])
				except Exception as a:
					if not "The access token expired" in str(a):
						sendMessage(
							chat_id, "Invalid link ;)",
							reply_to_message_id = msg['message_id']
						)

						delete(chat_id)
						return

					spo = Spotify(
						generate_token()
					)

					tracks = spo.user_playlist(musi[-3], musi[-1])

				try:
					image1 = tracks['images'][0]['url']
				except IndexError:
					image1 = "https://e-cdns-images.dzcdn.net/images/cover/1000x1000-000000-80-0-0.jpg"

				tot = tracks['tracks']['total']

				if tot > 400:
					sendMessage(chat_id, "F**k you")
					delete(chat_id)
					return

				sendPhoto(
					chat_id, image1,
					caption = (
						send_image_playlist_query
						% (
							tracks['tracks']['items'][0]['added_at'],
							tracks['owner']['display_name'],
							tot
						)
					)
				)

				def lazy(a):
					try:
						track(
							a['track']['external_urls']['spotify'],
							chat_id,
							quality
						)
					except:
						try:
							sendMessage(chat_id, "%s Not found :(" % a['track']['name'])
						except:
							sendMessage(chat_id, "Error :(")

				for a in tracks['tracks']['items']:
					lazy(a)

				tot = tracks['tracks']['total']
				tracks = tracks['tracks']

				if tot != 100:
					for a in range(tot // 100):
						try:
							tracks = spo.next(tracks)
						except:
							spo = Spotify(
								generate_token()
							)

							tracks = spo.next(tracks)

						for a in tracks['items']:
							lazy(a)

				done = 1

			else:
				sendMessage(chat_id, "Sorry :( The bot doesn't support this link")

		elif "deezer" in link:
			ids = link.split("/")[-1]

			if "track/" in link:
				try:
					url = request(
						"https://api.deezer.com/track/%s" % ids, chat_id, True
					).json()
				except AttributeError:
					delete(chat_id)
					return

				image1 = check_image(
					url['album']['cover_xl'], ids
				)

				sendPhoto(
					chat_id, image1,
					caption = (
						send_image_track_query
						% (
							url['title'],
							url['artist']['name'],
							url['album']['title'],
							url['album']['release_date']
						)
					)
				)

				track(link, chat_id, quality)

			elif "album/" in link:
				try:
					url = request(
						"https://api.deezer.com/album/%s" % ids, chat_id, True
					).json()
				except AttributeError:
					delete(chat_id)
					return

				if url['duration'] > 40000:
					sendMessage(chat_id, "If you do this again I will come to your home and I will ddos your ass :)")
					delete(chat_id)
					return

				image1 = url['cover_xl']

				if not image1:
					URL = "https://www.deezer.com/album/%s" % ids
					image1 = request(URL).text

					image1 = (
						BeautifulSoup(image1, "html.parser")
						.find("img", class_ = "img_main")
						.get("src")
						.replace("200x200", "1000x1000")
					)

				ima = request(image1).content

				if len(ima) == 13:
					image1 = "https://e-cdns-images.dzcdn.net/images/cover/1000x1000-000000-80-0-0.jpg"

				image2 = image1.replace("1000x1000", "320x320")
				image3 = image1.replace("1000x1000", "90x90")
				conn = connect(db_file)
				c = conn.cursor()
				lin = "album/%s" % ids

				for a in url['tracks']['data']:
					lin = "track/%s" % a['link'].split("/")[-1]

					c.execute(
						where_query.format(lin, quali)
					)

					links2.append(lin)

					if c.fetchone():
						links1.append(lin)

				conn.close()
				tot = url['nb_tracks']

				sendPhoto(
					chat_id, image1,
					caption = (
						send_image_album_query
						% (
							url['title'],
							url['artist']['name'],
							url['release_date'],
							tot
						)
					)
				)

				if len(links1) != tot:
					z = downloa.download_albumdee(
						link,
						quality = quality,
						recursive_quality = True,
						recursive_download = True,
						not_interface = True
					)
				else:
					for a in links2:
						track(a, chat_id, quality)

				done = 1

			elif "playlist/" in link:
				try:
					url = request(
						"https://api.deezer.com/playlist/%s" % ids, chat_id, True
					).json()
				except AttributeError:
					delete(chat_id)
					return

				tot = url['nb_tracks']

				if tot > 400:
					sendMessage(chat_id, "F**k you")
					delete(chat_id)
					return

				sendPhoto(
					chat_id, url['picture_xl'],
					caption = (
						send_image_playlist_query
						% (
							url['creation_date'],
							url['creator']['name'],
							tot
						)
					)
				)

				for a in url['tracks']['data']:
					try:
						track(a['link'], chat_id, quality)
					except:
						song = "{} - {}".format(a['title'], a['artist']['name'])
						sendMessage(chat_id, "Cannot download %s :(" % song)

				done = 1

			elif "artist/" in link:
				link = "https://api.deezer.com/artist/%s" % ids

				try:
					url = request(link, chat_id, True).json()
				except AttributeError:
					delete(chat_id)
					return

				sendPhoto(
					chat_id, url['picture_xl'],
					caption = (
						"👤 Artist: %s \n💽 Album numbers: %d \n👥 Fans on Deezer: %d"
						% (
							url['name'],
							url['nb_album'],
							url['nb_fan']
						)
					),
					reply_markup = InlineKeyboardMarkup(
						inline_keyboard = [
							[
								InlineKeyboardButton(
									text = "TOP 30 🔝",
									callback_data = "%s/top?limit=30" % link
								),
								InlineKeyboardButton(
									text = "ALBUMS 💽",
									callback_data = "%s/albums" % link
								)
							],
							[
								InlineKeyboardButton(
									text = "RADIO 📻",
									callback_data = "%s/radio" % link
								),
								InlineKeyboardButton(
									text = "RELATED 🗣",
									callback_data = "%s/related" % link
								)
							]
						]
					)
				)

			else:
				sendMessage(chat_id, "Sorry :( The bot doesn't support this link %s :(" % link)

		else:
			sendMessage(chat_id, "Sorry :( The bot doesn't support this link %s :(" % link)

		try:
			image3 = request(image3).content

			for a in range(
				len(z)
			):
				sendAudio(chat_id, z[a], links2[a], image3)
		except NameError:
			pass

	except exceptions.QuotaExceeded:
		sendMessage(chat_id, "Please send the link %s again :(" % link)

	except exceptions.AlbumNotFound:
		sendMessage(chat_id, "Album %s didn't find on Deezer :(" % link)
		sendMessage(chat_id, "Try to search it throught inline mode or search the link on Deezer")

	except Exception as a:
		logging.warning(a)
		logging.warning(quality)
		logging.warning(link)

		sendMessage(
			chat_id, "OPS :( Something went wrong please send to @An0nimia this link: {} {}, if this happens again".format(link, quality)
		)

	if done == 1:
		sendMessage(
			chat_id, "FINISHED :) Rate me here https://t.me/BotsArchive/298",
			reply_to_message_id = msg['message_id'],
			reply_markup = InlineKeyboardMarkup(
				inline_keyboard = [
					[
						InlineKeyboardButton(
							text = "SHARE",
							url = "tg://msg?text=Start @%s for download all the songs which you want ;)" % bot_name
						)
					]
				]
			)
		)

	delete(chat_id)
예제 #8
0
def get_album(sp: Spotify, album_id: str) -> Dict[str, Any]:
    """Returns an album given its ID or URI"""
    return sp.album(album_id)
예제 #9
0
def main():

    clientRedirect = "http://localhost/"

    username = "******"

    scope = "playlist-read-collaborative " \
            "playlist-read-private " \
            "user-library-read " \
            "playlist-modify-public " \
            "playlist-modify-private"

    token = util.prompt_for_user_token(username, scope, clientID, clientSecret,
                                       clientRedirect)

    spotify = Spotify(auth=token)

    result = spotify.current_user_saved_tracks(offset=0, limit=50)
    data = {}

    songs = {}

    exceptions = ("Depeche Mode", "Grant Miller", "Madonna", "Ministry",
                  "The Beach Boys", "Mickey & Sylvia", "The Clovers",
                  "Village People", "Frank Sinatra", "Rodríguez",
                  "The Bangles", "U2", "UB40", "Tom Petty", "Faces",
                  "Bobby McFerrin", "Dion", "Fancy", "Eddy Huntington",
                  "Michael Jackson", "OutKast", "Gorillaz", "Diddy",
                  "Lipps Inc.", "Chuck Berry", "Marvin Gaye", "The Kinks",
                  "Count Basie", "Player", "Steve Lawrence", "Nelly",
                  "The Killers", "Billy Idol", "Haddaway", "Blondie")
    dontwant = ("Emile Van Krieken")
    '''while result["next"]:
        for track in result["items"]:
            songs.update(track["track"]["name"])
        result = spotify.next(result)

    data = {username: songs}'''
    num = 0
    playlist_id = ""
    for playlist in spotify.current_user_playlists()["items"]:
        if playlist["name"] == "Computer Generated Old 2":
            playlist_id = playlist["id"]

    exceptions_list = []

    while result["next"]:
        for track in result["items"]:
            num = num + 1
            print(num)

            track = track["track"]
            '''songs.update({track["uri"]:
                              {"track": track["name"],
                               "artist": track["artists"][0]["name"],
                               "artist uri": track["artists"][0]["uri"],
                               "album": track["album"]["name"],
                               "album uri": track["album"]["uri"]
                              }
                          })'''

            album = spotify.album(track["album"]["id"])
            '''if (int(album["release_date"][0:4]) < 2000 or track["artists"][0]["name"] in exceptions): #and int(album["release_date"][0:4]) > 2006)\

                    #print(track["uri"])
                    print(track["id"])
                    print(track["name"])
                    spotify.user_playlist_add_tracks("karan.arora.28", playlist_id, [track["uri"]])'''

            if (int(album["release_date"][0:4]) <
                    2006) or track["artists"][0]["name"] in exceptions:
                spotify.user_playlist_add_tracks("karan.arora.28", playlist_id,
                                                 [track["uri"]])

                if track["artists"][0]["name"] not in exceptions_list:
                    exceptions_list.append(track["artists"][0]["name"])

            print(exceptions_list)
            '''else:
                #pid = getPlaylistIDByName(spotify, "Old??")
                pid = "2qSyS6sDfEGSS38cn4GR8U"
                if trackInPlaylist(spotify, track["name"], pid):
                    print(track["name"])
                    print(track["artists"][0]["name"])
                    num = num +1
                    print(num)'''

        result = spotify.next(result)

        #spotify.
        #spotify.user_playlist_create(clientID, "Python Old", False, "")

    #albumuri
    #artist Name and URI
    #when track was added
    #track name and URI

    #From this data, get when album was released, get genres,

    #username -> playlists -> songs -> songs contain all the data about genres and artists, etc.
    '''data = songs
예제 #10
0
class Login:
    def __init__(self, mail, password, token=None):
        self.spo = Spotify(auth=generate_token())
        self.req = requests.Session()
        check = self.get_api("deezer.getUserData")['checkFormLogin']
        post_data = {
            "type": "login",
            "mail": mail,
            "password": password,
            "checkFormLogin": check
        }
        end = self.req.post("https://www.deezer.com/ajax/action.php",
                            post_data).text
        if "success" == end:
            print("Success, you are in :)")
        else:
            if not token:
                raise BadCredentials(end + ", and no token provided")
            self.req.cookies["arl"] = token
            if self.req.get("https://www.deezer.com/").text.split(
                    "'deezer_user_id': ")[1].split(",")[0] == "0":
                raise BadCredentials("Wrong token :(")

    def get_api(self, method=None, api_token="null", json=None):
        params = {
            "api_version": "1.0",
            "api_token": api_token,
            "input": "3",
            "method": method
        }
        try:
            return self.req.post("http://www.deezer.com/ajax/gw-light.php",
                                 params=params,
                                 json=json).json()['results']
        except:
            return self.req.post("http://www.deezer.com/ajax/gw-light.php",
                                 params=params,
                                 json=json).json()['results']

    def download(self,
                 link,
                 name,
                 quality,
                 recursive_quality,
                 recursive_download,
                 datas,
                 create_zip=False):
        if not quality in qualities:
            raise QualityNotFound(
                "The qualities have to be FLAC or MP3_320 or MP3_256 or MP3_128"
            )

        def login(method, json):
            infos = ""
            while not "MD5_ORIGIN" in str(infos):
                self.token = self.get_api("deezer.getUserData")['checkForm']
                infos = self.get_api(method, self.token, json)
            return infos

        def ultimatum(infos, name, datas, quality, recursive_download,
                      recursive_quality):
            extension = ".mp3"
            ids = infos['SNG_ID']
            if int(infos['FILESIZE_' + quality]) > 0 and quality == "FLAC":
                quality = "9"
                extension = ".flac"
                qualit = "FLAC"
            elif int(
                    infos['FILESIZE_' + quality]) > 0 and quality == "MP3_320":
                quality = "3"
                qualit = "320"
            elif int(
                    infos['FILESIZE_' + quality]) > 0 and quality == "MP3_256":
                quality = "5"
                qualit = "256"
            elif int(
                    infos['FILESIZE_' + quality]) > 0 and quality == "MP3_128":
                quality = "1"
                qualit = "128"
            else:
                if recursive_quality:
                    raise QualityNotFound(
                        "The quality chosen can't be downloaded")
                for a in qualities:
                    if int(infos['FILESIZE_' + a]) > 0:
                        quality = qualities[a]['quality']
                        extension = qualities[a]['extension']
                        qualit = qualities[a]['qualit']
                        break
                    else:
                        if a == "MP3_128":
                            raise TrackNotFound(
                                "There isn't any quality avalaible for download this song"
                            )
            name += " (" + qualit + ")" + extension
            if os.path.isfile(name):
                if not recursive_download:
                    return name
                ans = input(
                    "Track " + name +
                    " already exists, do you want to redownload it?(y or n):")
                if ans != "y":
                    return name
            try:
                md5 = infos['FALLBACK']['MD5_ORIGIN']
            except KeyError:
                md5 = infos['MD5_ORIGIN']
            hashs = genurl(md5, quality, ids, infos['MEDIA_VERSION'])
            try:
                crypt = request(
                    "https://e-cdns-proxy-%s.dzcdn.net/mobile/1/%s" %
                    (md5[0], hashs))
            except IndexError:
                raise TrackNotFound("Track not found :(")
            if len(crypt.content) == 0:
                raise TrackNotFound("Error with this track :(")
            open(name, "wb").write(crypt.content)
            decry = open(name, "wb")
            decryptfile(crypt.iter_content(2048), calcbfkey(ids), decry)
            datas = add_more_tags(datas, infos, ids)
            write_tags(name, datas)
            return name

        def add_more_tags(datas, infos, ids):
            try:
                datas['author'] = " & ".join(
                    infos['SNG_CONTRIBUTORS']['author'])
            except:
                datas['author'] = ""
            try:
                datas['composer'] = " & ".join(
                    infos['SNG_CONTRIBUTORS']['composer'])
            except:
                datas['composer'] = ""
            try:
                datas['lyricist'] = " & ".join(
                    infos['SNG_CONTRIBUTORS']['lyricist'])
            except:
                datas['lyricist'] = ""
            try:
                datas['version'] = infos['VERSION']
            except KeyError:
                datas['version'] = ""
            need = self.get_api("song.getLyrics", self.token, {"sng_id": ids})
            try:
                datas['lyric'] = need['LYRICS_TEXT']
                datas['copyright'] = need['LYRICS_COPYRIGHTS']
                datas['lyricist'] = need['LYRICS_WRITERS']
            except KeyError:
                datas['lyric'] = ""
                datas['copyright'] = ""
                datas['lyricist'] = ""
            return datas

        ids = link.split("/")[-1]
        zip_name = ""
        quali = ""
        if "track" in link:
            method = "song.getData"
            json = {"sng_id": ids}
            infos = login(method, json)
            image = request("https://e-cdns-images.dzcdn.net/images/cover/" +
                            infos['ALB_PICTURE'] +
                            "/1200x1200-000000-80-0-0.jpg").content
            if len(image) == 13:
                image = request(
                    "https://e-cdns-images.dzcdn.net/images/cover/1200x1200-000000-80-0-0.jpg"
                ).content
            datas['image'] = image
            song = datas['music'] + " - " + datas['artist']
            song = var_excape(song)
            print("\nDownloading:" + song)
            try:
                nams = ultimatum(infos, name, datas, quality,
                                 recursive_download, recursive_quality)
            except TrackNotFound:
                url = request(
                    "https://api.deezer.com/search/track/?q=" +
                    datas['music'].replace("#", "") + " + " +
                    datas['artist'].replace("#", ""), True).json()
                try:
                    for b in range(url['total'] + 1):
                        if url['data'][b]['title'] == datas['music'] or datas[
                                'music'] in url['data'][b]['title_short']:
                            URL = url['data'][b]['link']
                            break
                except IndexError:
                    raise TrackNotFound("Track not found: " + song)
                json = {"sng_id": URL.split("/")[-1]}
                infos = login(method, json)
                nams = ultimatum(infos, name, datas, quality,
                                 recursive_download, recursive_quality)
        else:
            nams = []
            detas = {}
            method = "song.getListByAlbum"
            json = {"alb_id": ids, "nb": -1}
            infos = login(method, json)['data']
            image = request("https://e-cdns-images.dzcdn.net/images/cover/" +
                            infos[0]['ALB_PICTURE'] +
                            "/1200x1200-000000-80-0-0.jpg").content
            if len(image) == 13:
                image = request(
                    "https://e-cdns-images.dzcdn.net/images/cover/1200x1200-000000-80-0-0.jpg"
                ).content
            detas['image'] = image
            detas['album'] = datas['album']
            detas['year'] = datas['year']
            detas['genre'] = datas['genre']
            detas['ar_album'] = datas['ar_album']
            detas['label'] = datas['label']
            for a in tqdm(range(len(name))):
                detas['music'] = datas['music'][a]
                detas['artist'] = datas['artist'][a]
                detas['tracknum'] = datas['tracknum'][a]
                detas['discnum'] = datas['discnum'][a]
                detas['bpm'] = datas['bpm'][a]
                detas['gain'] = datas['gain'][a]
                detas['duration'] = datas['duration'][a]
                detas['isrc'] = datas['isrc'][a]
                try:
                    nams.append(
                        ultimatum(infos[a], name[a], detas, quality,
                                  recursive_download, recursive_quality))
                except TrackNotFound:
                    url = request(
                        "https://api.deezer.com/search/track/?q=" +
                        detas['music'].replace("#", "") + " + " +
                        detas['artist'].replace("#", ""), True).json()
                    try:
                        for b in range(url['total'] + 1):
                            if url['data'][b]['title'] == detas[
                                    'music'] or detas['music'] in url['data'][
                                        b]['title_short']:
                                URL = url['data'][b]['link']
                                break
                    except IndexError:
                        nams.append(name[a])
                        print("\nTrack not found: " + detas['music'] + " - " +
                              detas['artist'])
                        continue
                    try:
                        method = "song.getData"
                        json = {"sng_id": URL.split("/")[-1]}
                        nams.append(
                            ultimatum(login(method,
                                            json), name[a], detas, quality,
                                      recursive_download, recursive_quality))
                    except TrackNotFound:
                        nams.append(name[a])
                        print("\nTrack not found: " + detas['music'] + " - " +
                              detas['artist'])
                        continue
                quali = nams[a].split("(")[-1].split(")")[0]
            if create_zip:
                dir = "/".join(name[a].split("/")[:-1]) + "/"
                if len(nams) > 0:
                    zip_name = dir + dir.split(
                        "/")[-2] + " (" + quali + ").zip"
                    z = zipfile.ZipFile(zip_name, "w", zipfile.ZIP_DEFLATED)
                    for a in nams:
                        b = a.split("/")[-1]
                        try:
                            z.write(a, b)
                        except FileNotFoundError:
                            pass
                    z.close()
        return nams, zip_name

    def download_trackdee(self,
                          URL,
                          output=localdir + "/Songs/",
                          quality="MP3_320",
                          recursive_quality=True,
                          recursive_download=True):
        datas = {}
        if "?utm" in URL:
            URL, a = URL.split("?utm")
        URL1 = "https://www.deezer.com/track/" + URL.split("/")[-1]
        URL2 = "https://api.deezer.com/track/" + URL.split("/")[-1]
        url = request(URL2, True).json()
        url1 = request(
            "http://api.deezer.com/album/" + str(url['album']['id']),
            True).json()
        datas['music'] = url['title']
        array = []
        for a in url['contributors']:
            array.append(a['name'])
        array.append(url['artist']['name'])
        if len(array) > 1:
            for a in array:
                for b in array:
                    if a in b and a != b:
                        array.remove(b)
        datas['artist'] = ", ".join(OrderedDict.fromkeys(array))
        datas['album'] = url1['title']
        datas['tracknum'] = str(url['track_position'])
        datas['discnum'] = str(url['disk_number'])
        datas['year'] = url['release_date']
        datas['genre'] = []
        try:
            for a in url1['genres']['data']:
                datas['genre'].append(a['name'])
        except KeyError:
            pass
        datas['genre'] = " & ".join(datas['genre'])
        datas['ar_album'] = []
        for a in url1['contributors']:
            if a['role'] == "Main":
                datas['ar_album'].append(a['name'])
        datas['ar_album'] = " & ".join(datas['ar_album'])
        datas['label'] = url1['label']
        datas['bpm'] = str(url['bpm'])
        datas['gain'] = str(url['gain'])
        datas['duration'] = str(url['duration'])
        datas['isrc'] = url['isrc']
        album = var_excape(datas['album'])
        dir = output + album + " " + url1['upc'] + "/"
        try:
            os.makedirs(dir)
        except FileExistsError:
            pass
        name = dir + album + " CD " + datas['discnum'] + " TRACK " + datas[
            'tracknum']
        name, a = self.download(URL, name, quality, recursive_quality,
                                recursive_download, datas)
        return name

    def download_albumdee(self,
                          URL,
                          output=localdir + "/Songs/",
                          quality="MP3_320",
                          recursive_quality=True,
                          recursive_download=True,
                          create_zip=False):
        datas = {}
        datas['music'] = []
        datas['artist'] = []
        datas['tracknum'] = []
        datas['discnum'] = []
        datas['bpm'] = []
        datas['gain'] = []
        datas['duration'] = []
        datas['isrc'] = []
        names = []
        array = []
        if "?utm" in URL:
            URL, a = URL.split("?utm")
        URL1 = "https://www.deezer.com/album/" + URL.split("/")[-1]
        URL2 = "https://api.deezer.com/album/" + URL.split("/")[-1]
        url = request(URL2, True).json()
        datas['album'] = url['title']
        datas['label'] = url['label']
        datas['year'] = url['release_date']
        datas['genre'] = []
        try:
            for a in url['genres']['data']:
                datas['genre'].append(a['name'])
        except KeyError:
            pass
        datas['genre'] = " & ".join(datas['genre'])
        datas['ar_album'] = []
        for a in url['contributors']:
            if a['role'] == "Main":
                datas['ar_album'].append(a['name'])
        datas['ar_album'] = " & ".join(datas['ar_album'])
        album = var_excape(datas['album'])
        dir = output + "/" + album + " " + url['upc'] + "/"
        for a in url['tracks']['data']:
            del array[:]
            datas['music'].append(a['title'])
            ur = request("https://api.deezer.com/track/" + str(a['id']),
                         True).json()
            discnum = str(ur['disk_number'])
            tracknum = str(ur['track_position'])
            names.append(dir + album + " CD " + discnum + " TRACK " + tracknum)
            datas['tracknum'].append(tracknum)
            datas['discnum'].append(discnum)
            datas['bpm'].append(str(ur['bpm']))
            datas['gain'].append(str(ur['gain']))
            datas['duration'].append(str(ur['duration']))
            datas['isrc'].append(ur['isrc'])
            for a in ur['contributors']:
                array.append(a['name'])
            array.append(ur['artist']['name'])
            if len(array) > 1:
                for a in array:
                    for b in array:
                        if a in b and a != b:
                            array.remove(b)
            datas['artist'].append(", ".join(OrderedDict.fromkeys(array)))
        try:
            os.makedirs(dir)
        except FileExistsError:
            pass
        names, zip_name = self.download(URL, names, quality, recursive_quality,
                                        recursive_download, datas, create_zip)
        if create_zip:
            return names, zip_name
        return names

    def download_playlistdee(self,
                             URL,
                             output=localdir + "/Songs/",
                             quality="MP3_320",
                             recursive_quality=True,
                             recursive_download=True):
        array = []
        if "?utm" in URL:
            URL, a = URL.split("?utm")
        url = request("https://api.deezer.com/playlist/" + URL.split("/")[-1],
                      True).json()
        for a in url['tracks']['data']:
            try:
                array.append(
                    self.download_trackdee(a['link'], output, quality,
                                           recursive_quality,
                                           recursive_download))
            except TrackNotFound:
                print("\nTrack not found " + a['title'])
                array.append("None")
        return array

    def download_trackspo(self,
                          URL,
                          output=localdir + "/Songs/",
                          quality="MP3_320",
                          recursive_quality=True,
                          recursive_download=True):
        if "?" in URL:
            URL, a = URL.split("?")
        try:
            url = self.spo.track(URL)
        except Exception as a:
            if not "The access token expired" in str(a):
                raise InvalidLink("Invalid link ;)")
            self.spo = Spotify(auth=generate_token())
            url = self.spo.track(URL)
        isrc = url['external_ids']['isrc']
        url = request("https://api.deezer.com/track/isrc:" + isrc, True).json()
        name = self.download_trackdee(url['link'], output, quality,
                                      recursive_quality, recursive_download)
        return name

    def download_albumspo(self,
                          URL,
                          output=localdir + "/Songs/",
                          quality="MP3_320",
                          recursive_quality=True,
                          recursive_download=True,
                          create_zip=False):
        if "?" in URL:
            URL, a = URL.split("?")
        try:
            tracks = self.spo.album(URL)
        except Exception as a:
            if not "The access token expired" in str(a):
                raise InvalidLink("Invalid link ;)")
            self.spo = Spotify(auth=generate_token())
            tracks = self.spo.album(URL)
        try:
            upc = tracks['external_ids']['upc']
            while upc[0] == "0":
                upc = upc[1:]
            url = request("https://api.deezer.com/album/upc:" + upc).json()
            names = self.download_albumdee(url['link'], output, quality,
                                           recursive_quality,
                                           recursive_download, create_zip)
        except KeyError:
            search = len(tracks['tracks']['items']) // 8
            try:
                url = self.spo.track(tracks['tracks']['items'][search]
                                     ['external_urls']['spotify'])
            except:
                self.spo = Spotify(auth=generate_token())
                url = self.spo.track(tracks['tracks']['items'][search]
                                     ['external_urls']['spotify'])
            isrc = url['external_ids']['isrc']
            try:
                url = request("https://api.deezer.com/track/isrc:" + isrc,
                              True).json()
                names = self.download_albumdee(url['album']['link'], output,
                                               quality, recursive_quality,
                                               recursive_download, create_zip)
            except TrackNotFound:
                raise AlbumNotFound("Album not found :(")
        return names

    def download_playlistspo(self,
                             URL,
                             output=localdir + "/Songs/",
                             quality="MP3_320",
                             recursive_quality=True,
                             recursive_download=True):
        array = []
        if "?" in URL:
            URL, a = URL.split("?")
        URL = URL.split("/")
        try:
            tracks = self.spo.user_playlist_tracks(URL[-3],
                                                   playlist_id=URL[-1])
        except Exception as a:
            if not "The access token expired" in str(a):
                raise InvalidLink("Invalid link ;)")
            self.spo = Spotify(auth=generate_token())
            tracks = self.spo.user_playlist_tracks(URL[-3],
                                                   playlist_id=URL[-1])
        for a in tracks['items']:
            try:
                array.append(
                    self.download_trackspo(
                        a['track']['external_urls']['spotify'], output,
                        quality, recursive_quality, recursive_download))
            except:
                print("\nTrack not found :(")
                array.append("None")
        if tracks['total'] != 100:
            for a in range(tracks['total'] // 100):
                try:
                    tracks = self.spo.next(tracks)
                except:
                    self.spo = Spotify(auth=generate_token())
                    tracks = self.spo.next(tracks)
                for a in tracks['items']:
                    try:
                        array.append(
                            self.download_trackspo(
                                a['track']['external_urls']['spotify'], output,
                                quality, recursive_quality,
                                recursive_download))
                    except:
                        print("\nTrack not found :(")
                        array.append("None")
        return array

    def download_name(self,
                      artist,
                      song,
                      output=localdir + "/Songs/",
                      quality="MP3_320",
                      recursive_quality=True,
                      recursive_download=True):
        try:
            search = self.spo.search(q="track:" + song + " artist:" + artist)
        except:
            self.spo = Spotify(auth=generate_token())
            search = self.spo.search(q="track:" + song + " artist:" + artist)
        try:
            return self.download_trackspo(
                search['tracks']['items'][0]['external_urls']['spotify'],
                output, quality, recursive_quality, recursive_download)
        except IndexError:
            raise TrackNotFound("Track not found: " + artist + " - " + song)
예제 #11
0
class Login:
    def __init__(self, token):
        self.spo = Spotify(utils.generate_token())

        self.req = Session()
        self.req.cookies["arl"] = token
        self.get_user_data = methods.method_get_user_data
        self.private_api_link = deezer_settings.private_api_link
        user_id = self.get_api(self.get_user_data)["USER"]["USER_ID"]

        if user_id == 0:
            raise exceptions.BadCredentials("Wrong token: %s :(" % token)

        self.qualities = deezer_settings.qualities
        self.songs_server = deezer_settings.songs_server
        self.get_song_data = methods.method_get_song_data
        self.get_lyric = methods.method_get_lyric
        self.get_album = methods.method_get_album
        self.get_album_data = methods.method_get_album_data
        self.api_track = deezer_settings.api_track
        self.api_album = deezer_settings.api_album
        self.api_playlist = deezer_settings.api_playlist

    def get_api(self, method, api_token="null", json_data=None):
        params = {
            "api_version": "1.0",
            "api_token": api_token,
            "input": "3",
            "method": method,
        }

        try:
            return self.req.post(
                self.private_api_link, params=params, json=json_data
            ).json()["results"]
        except:
            return self.req.post(
                self.private_api_link, params=params, json=json_data
            ).json()["results"]

    def download(
        self,
        link,
        details,
        recursive_quality=None,
        recursive_download=None,
        not_interface=None,
        zips=False,
    ):
        if not details["quality"] in self.qualities:
            raise exceptions.QualityNotFound(
                "The qualities have to be FLAC or MP3_320 or MP3_256 or MP3_128"
            )

        self.token = self.get_api(self.get_user_data)["checkForm"]
        ids = utils.get_ids(link)
        datas = details["datas"]
        quality = details["quality"]
        output = details["output"]

        def get_infos(method, json_data):
            infos = self.get_api(method, self.token, json_data)
            return infos

        def check_quality_song(infos, datas):
            ids = infos["SNG_ID"]
            num_quality = self.qualities[quality]["n_quality"]
            file_format = self.qualities[quality]["f_format"]
            song_quality = self.qualities[quality]["s_quality"]
            song_md5, version = utils.check_md5_song(infos)
            song_hash = download_utils.genurl(song_md5, num_quality, ids, version)

            try:
                crypted_audio = utils.song_exist(song_md5[0], song_hash)
            except (IndexError, exceptions.TrackNotFound):
                if not recursive_quality:
                    raise exceptions.QualityNotFound(
                        "The quality chosen can't be downloaded"
                    )

                for a in self.qualities:
                    if details["quality"] == a:
                        continue

                    num_quality = self.qualities[a]["n_quality"]
                    file_format = self.qualities[a]["f_format"]
                    song_quality = self.qualities[a]["s_quality"]
                    song_hash = download_utils.genurl(
                        song_md5, num_quality, ids, infos["MEDIA_VERSION"]
                    )

                    try:
                        crypted_audio = utils.song_exist(song_md5[0], song_hash)
                    except exceptions.TrackNotFound:
                        raise exceptions.TrackNotFound("Error with this song %s" % link)

            album = utils.var_excape(datas["album"])

            directory = "%s%s %s/" % ("%s/" % output, album, datas["upc"])

            name = "%s%s CD %s TRACK %s" % (
                directory,
                album,
                datas["discnum"],
                datas["tracknum"],
            )

            utils.check_dir(directory)
            name += " ({}){}".format(song_quality, file_format)

            if isfile(name):
                if recursive_download:
                    return name

                ans = input(
                    "Track %s already exists, do you want to redownload it? (y or n):"
                    % name
                )

                if not ans in answers:
                    return name

            decrypted_audio = open(name, "wb")

            download_utils.decryptfile(
                crypted_audio.iter_content(2048),
                download_utils.calcbfkey(ids),
                decrypted_audio,
            )

            utils.write_tags(name, add_more_tags(datas, infos, ids))

            return name

        def add_more_tags(datas, infos, ids):
            json_data = {"sng_id": ids}

            try:
                datas["author"] = " & ".join(infos["SNG_CONTRIBUTORS"]["author"])
            except:
                datas["author"] = ""

            try:
                datas["composer"] = " & ".join(infos["SNG_CONTRIBUTORS"]["composer"])
            except:
                datas["composer"] = ""

            try:
                datas["lyricist"] = " & ".join(infos["SNG_CONTRIBUTORS"]["lyricist"])
            except:
                datas["lyricist"] = ""

            try:
                datas["version"] = infos["VERSION"]
            except KeyError:
                datas["version"] = ""

            need = get_infos(self.get_lyric, json_data)

            try:
                datas["lyric"] = need["LYRICS_TEXT"]
                datas["copyright"] = need["LYRICS_COPYRIGHTS"]
                datas["lyricist"] = need["LYRICS_WRITERS"]
            except KeyError:
                datas["lyric"] = ""
                datas["copyright"] = ""
                datas["lyricist"] = ""

            return datas

        def tracking2(infos, datas):
            image = utils.choose_img(infos["ALB_PICTURE"])
            datas["image"] = image
            song = "{} - {}".format(datas["music"], datas["artist"])

            if not not_interface:
                print("Downloading: %s" % song)

            try:
                nams = check_quality_song(infos, datas)
            except exceptions.TrackNotFound:
                try:
                    ids = utils.not_found(song, datas["music"])
                except IndexError:
                    raise exceptions.TrackNotFound("Track not found: %s" % song)

                json_data = {"sng_id": ids}

                infos = get_infos(self.get_song_data, json_data)
                nams = check_quality_song(infos, datas)

            return nams

        if "track" in link:
            json_data = {"sng_id": ids}

            infos = get_infos(self.get_song_data, json_data)
            nams = tracking2(infos, datas)
            return nams

        zip_name = ""

        if "album" in link:
            nams = []
            detas = {}
            quali = ""

            json_data = {"alb_id": ids, "nb": -1}

            infos = get_infos(self.get_album, json_data)["data"]

            image = utils.choose_img(infos[0]["ALB_PICTURE"])

            detas["image"] = image
            detas["album"] = datas["album"]
            detas["year"] = datas["year"]
            detas["genre"] = datas["genre"]
            detas["ar_album"] = datas["ar_album"]
            detas["label"] = datas["label"]
            detas["upc"] = datas["upc"]

            t = tqdm(range(len(infos)), desc=detas["album"], disable=not_interface)

            for a in t:
                detas["music"] = datas["music"][a]
                detas["artist"] = datas["artist"][a]
                detas["tracknum"] = datas["tracknum"][a]
                detas["discnum"] = datas["discnum"][a]
                detas["bpm"] = datas["bpm"][a]
                detas["duration"] = datas["duration"][a]
                detas["isrc"] = datas["isrc"][a]
                song = "{} - {}".format(detas["music"], detas["artist"])
                t.set_description_str(song)

                try:
                    nams.append(check_quality_song(infos[a], detas))
                except exceptions.TrackNotFound:
                    try:
                        ids = utils.not_found(song, detas["music"])

                        json = {"sng_id": ids}

                        nams.append(
                            check_quality_song(
                                get_infos(self.get_song_data, json), detas
                            )
                        )
                    except (exceptions.TrackNotFound, IndexError):
                        nams.append(song)
                        print("Track not found: %s :(" % song)
                        continue

                quali = nams[a].split("(")[-1].split(")")[0]

            if zips:
                album = utils.var_excape(datas["album"])

                directory = "%s%s %s/" % ("%s/" % output, album, datas["upc"])

                zip_name = "%s%s (%s).zip" % (directory, album, quali)

                try:
                    utils.create_zip(zip_name, nams)
                except FileNotFoundError:
                    raise exceptions.QualityNotFound(
                        'Can\'t download album "{}" in {} quality'.format(
                            album, details["quality"]
                        )
                    )

        elif "playlist" in link:
            json_data = {"playlist_id": ids, "nb": -1}

            infos = get_infos(methods.method_get_playlist_data, json_data)["data"]
            nams = []

            for a in range(len(infos)):
                try:
                    nams.append(tracking2(infos[a], datas[a]))
                except TypeError:
                    c = infos[a]
                    song = "{} - {}".format(c["SNG_TITLE"], c["ART_NAME"])
                    nams.append("Track not found")

            quali = "ALL"

            if zips:
                zip_name = "%s %s (%s).zip" % ("%s/playlist" % output, ids, quali)

                utils.create_zip(zip_name, nams)

        return nams, zip_name

    def download_trackdee(
        self,
        URL,
        output=stock_output,
        quality=stock_quality,
        recursive_quality=stock_recursive_quality,
        recursive_download=stock_recursive_download,
        not_interface=stock_not_interface,
    ):
        datas = {}
        ids = utils.get_ids(URL)
        URL2 = self.api_track % ids
        datas = utils.tracking(URL2)

        details = {"datas": datas, "quality": quality, "output": output}

        name = self.download(
            URL2, details, recursive_quality, recursive_download, not_interface
        )

        return name

    def download_albumdee(
        self,
        URL,
        output=stock_output,
        quality=stock_quality,
        recursive_quality=stock_recursive_quality,
        recursive_download=stock_recursive_download,
        not_interface=stock_not_interface,
        zips=stock_zip,
    ):
        datas = {}
        datas["music"] = []
        datas["artist"] = []
        datas["tracknum"] = []
        datas["discnum"] = []
        datas["bpm"] = []
        datas["duration"] = []
        datas["isrc"] = []
        names = []
        ids = utils.get_ids(URL)
        URL2 = self.api_album % ids
        album_json = utils.request(URL2, True).json()
        datas["album"] = album_json["title"]
        datas["label"] = album_json["label"]
        datas["year"] = album_json["release_date"]
        datas["upc"] = album_json["upc"]
        datas["genre"] = []

        try:
            for a in album_json["genres"]["data"]:
                datas["genre"].append(a["name"])
        except KeyError:
            pass

        datas["genre"] = " & ".join(datas["genre"])
        datas["ar_album"] = []

        for a in album_json["contributors"]:
            if a["role"] == "Main":
                datas["ar_album"].append(a["name"])

        datas["ar_album"] = " & ".join(datas["ar_album"])

        for a in album_json["tracks"]["data"]:
            URL3 = self.api_track % str(a["id"])
            detas = utils.tracking(URL3, True)
            datas["music"].append(detas["music"])
            discnum = detas["discnum"]
            tracknum = detas["tracknum"]
            datas["tracknum"].append(tracknum)
            datas["discnum"].append(discnum)
            datas["bpm"].append(detas["bpm"])
            datas["duration"].append(detas["duration"])
            datas["isrc"].append(detas["isrc"])
            datas["artist"].append(detas["artist"])

        details = {"datas": datas, "quality": quality, "output": output}

        names, zip_name = self.download(
            URL2, details, recursive_quality, recursive_download, not_interface, zips
        )

        if zips:
            return names, zip_name

        return names

    def download_playlistdee(
        self,
        URL,
        output=stock_output,
        quality=stock_quality,
        recursive_quality=stock_recursive_quality,
        recursive_download=stock_recursive_download,
        not_interface=stock_not_interface,
        zips=stock_zip,
    ):
        datas = []
        ids = utils.get_ids(URL)
        URL2 = self.api_playlist % ids
        playlist_json = utils.request(URL2, True).json()["tracks"]["data"]

        for a in playlist_json:
            URL3 = self.api_track % str(a["id"])

            try:
                detas = utils.tracking(URL3)
                datas.append(detas)
            except exceptions.NoDataApi:
                datas.append(None)

        details = {"datas": datas, "quality": quality, "output": output}

        names, zip_name = self.download(
            URL2, details, recursive_quality, recursive_download, not_interface, zips
        )

        if zips:
            return names, zip_name

        return names

    def download_trackspo(
        self,
        URL,
        output=stock_output,
        quality=stock_quality,
        recursive_quality=stock_recursive_quality,
        recursive_download=stock_recursive_download,
        not_interface=stock_not_interface,
    ):
        URL = URL.split("?")[0]

        try:
            url = self.spo.track(URL)
        except Exception as a:
            if not "The access token expired" in str(a):
                raise exceptions.InvalidLink("Invalid link ;)")

            self.spo = Spotify(utils.generate_token())

            url = self.spo.track(URL)

        isrc = "isrc:%s" % url["external_ids"]["isrc"]

        url = utils.request(self.api_track % isrc, True).json()

        name = self.download_trackdee(
            url["link"],
            output,
            quality,
            recursive_quality,
            recursive_download,
            not_interface,
        )

        return name

    def download_albumspo(
        self,
        URL,
        output=stock_output,
        quality=stock_quality,
        recursive_quality=stock_recursive_quality,
        recursive_download=stock_recursive_download,
        not_interface=stock_not_interface,
        zips=stock_zip,
    ):
        URL = URL.split("?")[0]

        try:
            tracks = self.spo.album(URL)
        except Exception as a:
            if not "The access token expired" in str(a):
                raise exceptions.InvalidLink("Invalid link ;)")

            self.spo = Spotify(utils.generate_token())

            tracks = self.spo.album(URL)

        try:
            upc = "0%s" % tracks["external_ids"]["upc"]

            while upc[0] == "0":
                upc = upc[1:]

                try:
                    upc = "upc:%s" % upc
                    url = utils.request(self.api_album % upc, True).json()

                    names = self.download_albumdee(
                        url["link"],
                        output,
                        quality,
                        recursive_quality,
                        recursive_download,
                        not_interface,
                        zips,
                    )

                    break
                except exceptions.NoDataApi:
                    if upc[0] != "0":
                        raise KeyError
        except KeyError:
            tot = tracks["total_tracks"]

            for a in tracks["tracks"]["items"]:
                try:
                    isrc = self.spo.track(a["external_urls"]["spotify"])[
                        "external_ids"
                    ]["isrc"]
                except:
                    self.spo = Spotify(utils.generate_token())

                    isrc = self.spo.track(a["external_urls"]["spotify"])[
                        "external_ids"
                    ]["isrc"]

                try:
                    isrc = "isrc:%s" % isrc

                    ids = utils.request(self.api_track % isrc, True).json()["album"][
                        "id"
                    ]

                    tracks = utils.request(self.api_album % str(ids), True).json()

                    if tot == tracks["nb_tracks"]:
                        break
                except exceptions.NoDataApi:
                    pass

            try:
                if tot != tracks["nb_tracks"]:
                    raise KeyError

                names = self.download_albumdee(
                    tracks["link"],
                    output,
                    quality,
                    recursive_quality,
                    recursive_download,
                    not_interface,
                    zips,
                )
            except KeyError:
                raise exceptions.AlbumNotFound("Album not found :(")

        return names

    def download_playlistspo(
        self,
        URL,
        output=stock_output,
        quality=stock_quality,
        recursive_quality=stock_recursive_quality,
        recursive_download=stock_recursive_download,
        not_interface=stock_not_interface,
        zips=stock_zip,
    ):
        array = []

        URL = URL.split("?")[0].split("/")

        try:
            tracks = self.spo.user_playlist_tracks(URL[-3], URL[-1])
        except Exception as a:
            if not "The access token expired" in str(a):
                raise exceptions.InvalidLink("Invalid link ;)")

            self.spo = Spotify(utils.generate_token())

            tracks = self.spo.user_playlist_tracks(URL[-3], URL[-1])

        def lazy(tracks):
            for a in tracks["items"]:
                try:
                    array.append(
                        self.download_trackspo(
                            a["track"]["external_urls"]["spotify"],
                            output,
                            quality,
                            recursive_quality,
                            recursive_download,
                            not_interface,
                        )
                    )
                except:
                    print("Track not found :(")
                    array.append("None")

        lazy(tracks)
        tot = tracks["total"]

        for a in range(tot // 100 - 1):
            try:
                tracks = self.spo.next(tracks)
            except:
                self.spo = Spotify(utils.generate_token())

                tracks = self.spo.next(tracks)

            lazy(tracks)

        if zips:
            zip_name = "{}playlist {}.zip".format(output, URL[-1])
            utils.create_zip(zip_name, array)
            return array, zip_name

        return array

    def download_name(
        self,
        artist,
        song,
        output=stock_output,
        quality=stock_quality,
        recursive_quality=stock_recursive_quality,
        recursive_download=stock_recursive_download,
        not_interface=stock_not_interface,
    ):
        query = "track:{} artist:{}".format(song, artist)

        try:
            search = self.spo.search(query)
        except:
            self.spo = Spotify(utils.generate_token())

            search = self.spo.search(query)

        try:
            return self.download_trackspo(
                search["tracks"]["items"][0]["external_urls"]["spotify"],
                output,
                quality,
                recursive_quality,
                recursive_download,
                not_interface,
            )
        except IndexError:
            raise exceptions.TrackNotFound("Track not found")
예제 #12
0
def main():
    scope = "user-read-playback-state,user-modify-playback-state"
    sp = Spotify(client_credentials_manager=SpotifyClientCredentials(),
                 auth_manager=SpotifyOAuth(scope=scope))

    allchars = 'qwertyuiopasdfghjklzxcvbnm'
    market = "CA"  # start with a canadian market (this will change later)

    while True:
        try:  # normally get a ReadTimeoutError but I don't actually care what the error is - I just want it to power through until I stop it manually
            # initiate random query
            char = random.choice(allchars)
            n = 10000
            offset = random.randint(0, n - 1)  # random spot on the list
            try:
                results = sp.search(
                    q='%' + char + '%',
                    type='track',
                    offset=offset,
                    market=market
                )  # start a query with the letter somewhere in the middle - results ordered by popularity
            except:  # most queries don't return n results
                continue

            # parse query
            result = results['tracks']['items'][
                0]  # select the "first" song (offset by up to n)
            album_id = result['album']['id']
            album_ = sp.album(album_id)
            markets = album_['available_markets']
            market = random.choice(markets)  # choose new market
            artists = result['artists']

            # filter
            if result['explicit']:  # skip explicit
                continue
            skip_artist = False
            for artist in artists:
                if artist['name'] in [
                        'Daddy Yankee', 'J Balvin', 'Don Omar', 'Bad Bunny',
                        'KAROL G', 'Wisin & Yandel'
                ]:  # skip reggaeton
                    skip_artist = True
                    break
            if skip_artist:
                continue

            # play track
            sp.start_playback(uris=['spotify:track:' + result['id']
                                    ])  # play track
            sleep(0.5)  # wait for track to start

            pprint(result)

            # simplest event listener
            while True:  # start next track when current one finishes
                while True:
                    if sp.current_playback(
                    )['progress_ms']:  # playback started
                        break
                    sleep(0.1)  # don't consume too much CPU
                while True:
                    if not sp.current_playback(
                    )['progress_ms']:  # playback stopped
                        # Triggers at end of track (a simple method for which I didn't find)
                        # Doesn't trigger if paused as long as progress is nonzero
                        # In theory, can trigger if track is set back to start while playing (progress = 0), but unlikely since the intepreter only checks this condition every 100 milliseconds or so, while the track begins to play much more quickly than that (making nonzero progress)
                        # DOES trigger if track is set back to zero while paused
                        break
                    sleep(0.1)  # don't consume too much CPU
                break

            print('Changing track')

        except Exception as e:
            print(e)
            continue  # send the interpreter back to the top of the loop to ensure the current track keeps playing
예제 #13
0
def download_albumspo(URL,
                      output=stock_output + "/",
                      recursive_download=stock_recursive_download,
                      not_interface=stock_not_interface,
                      zips=stock_zip):
    global spo

    datas = {}
    detas = {}
    datas['music'] = []
    datas['artist'] = []
    datas['tracknum'] = []
    datas['discnum'] = []
    datas['duration'] = []
    names = []
    nams = []

    try:
        url = spo.album(URL)
    except Exception as a:
        if not "The access token expired" in str(a):
            raise exceptions.InvalidLink("Invalid link ;)")

        spo = Spotify(generate_token())

        url = spo.album(URL)

    detas['image'] = request(url['images'][0]['url']).content

    detas['album'] = url['name']
    detas['year'] = url['release_date']
    detas['genre'] = " & ".join(url['genres'])

    array = [a['name'] for a in url['artists']]

    detas['ar_album'] = ", ".join(array)
    detas['label'] = url['label']
    detas['bpm'] = ""
    detas['gain'] = "0"
    detas['isrc'] = ""
    album = var_excape(detas['album'])

    directory = ("%s%s %s/" % (output, album, url['external_ids']['upc']))

    check_dir(directory)
    tot = url['total_tracks']

    def lazy(a):
        datas['music'].append(a['name'])
        discnum = str(a['disc_number'])
        tracknum = str(a['track_number'])

        names.append("%s%s CD %s TRACK %s" %
                     (directory, album, discnum, tracknum))

        datas['tracknum'].append(tracknum)
        datas['discnum'].append(discnum)

        datas['duration'].append(str(a['duration_ms'] * 1000))

        array = [b['name'] for b in a['artists']]

        datas['artist'].append(", ".join(array))

    for a in url['tracks']['items']:
        lazy(a)

    for a in range(tot // 50 - 1):
        try:
            url = spo.next(url['tracks'])
        except:
            spo = Spotify(generate_token())

            url = spo.next(url['tracks'])

        for a in url['items']:
            lazy(a)

    for a in tqdm(range(len(names)), disable=not_interface):
        detas['music'] = datas['music'][a]
        detas['artist'] = datas['artist'][a]
        detas['tracknum'] = datas['tracknum'][a]
        detas['discnum'] = datas['discnum'][a]
        detas['duration'] = datas['duration'][a]
        song = "{} - {}".format(detas['music'], detas['artist'])

        try:
            nams.append(
                download(directory, names[a], recursive_download,
                         not_interface, detas))
        except exceptions.TrackNotFound:
            nams.append(names[a])
            print("Track not found: %s :(" % song)
            continue

    if zips:
        zip_name = "{}{}.zip".format(directory, directory.split("/")[-2])

        create_zip(zip_name, nams)
        return nams, zip_name

    return nams
예제 #14
0
def download_trackspo(URL,
                      output=stock_output + "/",
                      recursive_download=stock_recursive_download,
                      not_interface=stock_not_interface):
    global spo

    datas = {}
    URL = URL.split("?")[0]

    try:
        url = spo.track(URL)
    except Exception as a:
        if not "The access token expired" in str(a):
            raise exceptions.InvalidLink("Invalid link ;)")

        spo = Spotify(generate_token())

        url = spo.track(URL)

    URL1 = url['album']['external_urls']['spotify']

    try:
        url1 = spo.album(URL1)
    except Exception as a:
        if not "The access token expired" in str(a):
            raise exceptions.InvalidLink("Invalid link ;)")

        spo = Spotify(generate_token())

        url1 = spo.album(URL1)

    datas['image'] = request(url1['images'][0]['url']).content

    datas['music'] = url['name']

    array = [a['name'] for a in url['artists']]

    datas['artist'] = ", ".join(array)
    datas['album'] = url1['name']
    datas['tracknum'] = str(url['track_number'])
    datas['discnum'] = str(url['disc_number'])
    datas['year'] = url1['release_date']
    datas['genre'] = " & ".join(url1['genres'])

    array = [a['name'] for a in url1['artists']]

    datas['ar_album'] = ", ".join(array)
    datas['label'] = url1['label']
    datas['bpm'] = ""
    datas['gain'] = "0"
    datas['duration'] = str(url['duration_ms'] * 1000)
    datas['isrc'] = url['external_ids']['isrc']
    album = var_excape(datas['album'])

    directory = ("%s%s %s/" % (output, album, url1['external_ids']['upc']))

    check_dir(directory)

    name = ("%s%s CD %s TRACK %s" %
            (directory, album, datas['discnum'], datas['tracknum']))

    out = download(directory, name, recursive_download, not_interface, datas)

    return out
예제 #15
0
class AuthTestSpotipy(unittest.TestCase):
    """
    These tests require client authentication - provide client credentials
    using the following environment variables

    ::

        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
    """

    playlist = "spotify:user:plamere:playlist:2oCEWyyAPbZp9xhVSxZavx"
    four_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB", "4VrWlk8IQxevMvERoX08iC",
        "http://open.spotify.com/track/3cySlItpiPiIAzU3NyHCJf"
    ]

    two_tracks = [
        "spotify:track:6RtPijgfPKROxEzTHNRiDp",
        "spotify:track:7IHOIqZUUInxjVkko181PB"
    ]

    other_tracks = [
        "spotify:track:2wySlB6vMzCbQrRnNGOYKa",
        "spotify:track:29xKs5BAHlmlX1u4gzQAbJ",
        "spotify:track:1PB7gRWcvefzu7t3LJLUlf"
    ]

    bad_id = 'BAD_ID'

    creep_urn = 'spotify:track:3HfB5hBU0dmBt8T0iCmH42'
    creep_id = '3HfB5hBU0dmBt8T0iCmH42'
    creep_url = 'http://open.spotify.com/track/3HfB5hBU0dmBt8T0iCmH42'
    el_scorcho_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ'
    el_scorcho_bad_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQK'
    pinkerton_urn = 'spotify:album:04xe676vyiTeYNXw15o9jT'
    weezer_urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
    pablo_honey_urn = 'spotify:album:6AZv3m27uyRxi8KyJSfUxL'
    radiohead_urn = 'spotify:artist:4Z8W4fKeB5YxbusRsdQVPb'
    angeles_haydn_urn = 'spotify:album:1vAbqAeuJVWNAe7UR00bdM'

    @classmethod
    def setUpClass(self):
        self.spotify = Spotify(
            client_credentials_manager=SpotifyClientCredentials())
        self.spotify.trace = False

    def test_audio_analysis(self):
        result = self.spotify.audio_analysis(self.four_tracks[0])
        assert ('beats' in result)

    def test_audio_features(self):
        results = self.spotify.audio_features(self.four_tracks)
        self.assertTrue(len(results) == len(self.four_tracks))
        for track in results:
            assert ('speechiness' in track)

    def test_audio_features_with_bad_track(self):
        bad_tracks = ['spotify:track:bad']
        input = self.four_tracks + bad_tracks
        results = self.spotify.audio_features(input)
        self.assertTrue(len(results) == len(input))
        for track in results[:-1]:
            if track is not None:
                assert ('speechiness' in track)
        self.assertTrue(results[-1] is None)

    def test_recommendations(self):
        results = self.spotify.recommendations(seed_tracks=self.four_tracks,
                                               min_danceability=0,
                                               max_loudness=0,
                                               target_popularity=50)
        self.assertTrue(len(results['tracks']) == 20)

    def test_artist_urn(self):
        artist = self.spotify.artist(self.radiohead_urn)
        self.assertTrue(artist['name'] == 'Radiohead')

    def test_artists(self):
        results = self.spotify.artists([self.weezer_urn, self.radiohead_urn])
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 2)

    def test_album_urn(self):
        album = self.spotify.album(self.pinkerton_urn)
        self.assertTrue(album['name'] == 'Pinkerton')

    def test_album_tracks(self):
        results = self.spotify.album_tracks(self.pinkerton_urn)
        self.assertTrue(len(results['items']) == 10)

    def test_album_tracks_many(self):
        results = self.spotify.album_tracks(self.angeles_haydn_urn)
        tracks = results['items']
        total, received = results['total'], len(tracks)
        while received < total:
            results = self.spotify.album_tracks(self.angeles_haydn_urn,
                                                offset=received)
            tracks.extend(results['items'])
            received = len(tracks)

        self.assertEqual(received, total)

    def test_albums(self):
        results = self.spotify.albums(
            [self.pinkerton_urn, self.pablo_honey_urn])
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']) == 2)

    def test_track_urn(self):
        track = self.spotify.track(self.creep_urn)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_id(self):
        track = self.spotify.track(self.creep_id)
        self.assertTrue(track['name'] == 'Creep')
        self.assertTrue(track['popularity'] > 0)

    def test_track_url(self):
        track = self.spotify.track(self.creep_url)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_bad_urn(self):
        try:
            self.spotify.track(self.el_scorcho_bad_urn)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_tracks(self):
        results = self.spotify.tracks([self.creep_url, self.el_scorcho_urn])
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 2)

    def test_artist_top_tracks(self):
        results = self.spotify.artist_top_tracks(self.weezer_urn)
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 10)

    def test_artist_related_artists(self):
        results = self.spotify.artist_related_artists(self.weezer_urn)
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 20)
        for artist in results['artists']:
            if artist['name'] == 'Jimmy Eat World':
                found = True
        self.assertTrue(found)

    def test_artist_search(self):
        results = self.spotify.search(q='weezer', type='artist')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_search_with_market(self):
        results = self.spotify.search(q='weezer', type='artist', market='GB')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_albums(self):
        results = self.spotify.artist_albums(self.weezer_urn)
        self.assertTrue('items' in results)
        self.assertTrue(len(results['items']) > 0)

        found = False
        for album in results['items']:
            if album['name'] == 'Hurley':
                found = True

        self.assertTrue(found)

    def test_search_timeout(self):
        client_credentials_manager = SpotifyClientCredentials()
        sp = spotipy.Spotify(
            client_credentials_manager=client_credentials_manager,
            requests_timeout=.01)

        try:
            sp.search(q='my*', type='track')
            self.assertTrue(False, 'unexpected search timeout')
        except requests.exceptions.Timeout:
            self.assertTrue(True, 'expected search timeout')

    def test_album_search(self):
        results = self.spotify.search(q='weezer pinkerton', type='album')
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']['items']) > 0)
        self.assertTrue(
            results['albums']['items'][0]['name'].find('Pinkerton') >= 0)

    def test_track_search(self):
        results = self.spotify.search(q='el scorcho weezer', type='track')
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']['items']) > 0)
        self.assertTrue(results['tracks']['items'][0]['name'] == 'El Scorcho')

    def test_user(self):
        user = self.spotify.user(user='******')
        self.assertTrue(user['uri'] == 'spotify:user:plamere')

    def test_track_bad_id(self):
        try:
            self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_unauthenticated_post_fails(self):
        with self.assertRaises(SpotifyException) as cm:
            self.spotify.user_playlist_create("spotify",
                                              "Best hits of the 90s")
        self.assertTrue(cm.exception.http_status == 401
                        or cm.exception.http_status == 403)

    def test_custom_requests_session(self):
        sess = requests.Session()
        sess.headers["user-agent"] = "spotipy-test"
        with_custom_session = spotipy.Spotify(
            client_credentials_manager=SpotifyClientCredentials(),
            requests_session=sess)
        self.assertTrue(
            with_custom_session.user(user="******")["uri"] == "spotify:user:akx")
        sess.close()

    def test_force_no_requests_session(self):
        from requests import Session
        with_no_session = spotipy.Spotify(
            client_credentials_manager=SpotifyClientCredentials(),
            requests_session=False)
        self.assertFalse(isinstance(with_no_session._session, Session))
        self.assertTrue(
            with_no_session.user(user="******")["uri"] == "spotify:user:akx")
예제 #16
0
class TestSpotipy(unittest.TestCase):
    """
    These tests require user authentication - provide client credentials using the
    following environment variables

    ::

        'SPOTIPY_CLIENT_USERNAME'
        'SPOTIPY_CLIENT_ID'
        'SPOTIPY_CLIENT_SECRET'
        'SPOTIPY_REDIRECT_URI'
    """

    creep_urn = 'spotify:track:3HfB5hBU0dmBt8T0iCmH42'
    creep_id = '3HfB5hBU0dmBt8T0iCmH42'
    creep_url = 'http://open.spotify.com/track/3HfB5hBU0dmBt8T0iCmH42'
    el_scorcho_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQJ'
    el_scorcho_bad_urn = 'spotify:track:0Svkvt5I79wficMFgaqEQK'
    pinkerton_urn = 'spotify:album:04xe676vyiTeYNXw15o9jT'
    weezer_urn = 'spotify:artist:3jOstUTkEu2JkjvRdBA5Gu'
    pablo_honey_urn = 'spotify:album:6AZv3m27uyRxi8KyJSfUxL'
    radiohead_urn = 'spotify:artist:4Z8W4fKeB5YxbusRsdQVPb'
    angeles_haydn_urn = 'spotify:album:1vAbqAeuJVWNAe7UR00bdM'

    bad_id = 'BAD_ID'

    @classmethod
    def setUpClass(self):
        missing = list(filter(lambda var: not os.getenv(CCEV[var]), CCEV))

        if missing:
            raise Exception(
                'Please set the client credentials for the test application using the following environment variables: {}'
                .format(CCEV.values()))

        self.username = os.getenv(CCEV['client_username'])

        self.scope = 'user-library-read'

        self.token = prompt_for_user_token(self.username, scope=self.scope)

        self.spotify = Spotify(auth=self.token)

    def test_artist_urn(self):
        artist = self.spotify.artist(self.radiohead_urn)
        self.assertTrue(artist['name'] == 'Radiohead')

    def test_artists(self):
        results = self.spotify.artists([self.weezer_urn, self.radiohead_urn])
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 2)

    def test_album_urn(self):
        album = self.spotify.album(self.pinkerton_urn)
        self.assertTrue(album['name'] == 'Pinkerton')

    def test_album_tracks(self):
        results = self.spotify.album_tracks(self.pinkerton_urn)
        self.assertTrue(len(results['items']) == 10)

    def test_album_tracks_many(self):
        results = self.spotify.album_tracks(self.angeles_haydn_urn)
        tracks = results['items']
        total, received = results['total'], len(tracks)
        while received < total:
            results = self.spotify.album_tracks(self.angeles_haydn_urn,
                                                offset=received)
            tracks.extend(results['items'])
            received = len(tracks)

        self.assertEqual(received, total)

    def test_albums(self):
        results = self.spotify.albums(
            [self.pinkerton_urn, self.pablo_honey_urn])
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']) == 2)

    def test_track_urn(self):
        track = self.spotify.track(self.creep_urn)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_id(self):
        track = self.spotify.track(self.creep_id)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_url(self):
        track = self.spotify.track(self.creep_url)
        self.assertTrue(track['name'] == 'Creep')

    def test_track_bad_urn(self):
        try:
            track = self.spotify.track(self.el_scorcho_bad_urn)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_tracks(self):
        results = self.spotify.tracks([self.creep_url, self.el_scorcho_urn])
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 2)

    def test_artist_top_tracks(self):
        results = self.spotify.artist_top_tracks(self.weezer_urn)
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']) == 10)

    def test_artist_related_artists(self):
        results = self.spotify.artist_related_artists(self.weezer_urn)
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']) == 20)
        for artist in results['artists']:
            if artist['name'] == 'Jimmy Eat World':
                found = True
        self.assertTrue(found)

    def test_artist_search(self):
        results = self.spotify.search(q='weezer', type='artist')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_search_with_market(self):
        results = self.spotify.search(q='weezer', type='artist', market='GB')
        self.assertTrue('artists' in results)
        self.assertTrue(len(results['artists']['items']) > 0)
        self.assertTrue(results['artists']['items'][0]['name'] == 'Weezer')

    def test_artist_albums(self):
        results = self.spotify.artist_albums(self.weezer_urn)
        self.assertTrue('items' in results)
        self.assertTrue(len(results['items']) > 0)

        found = False
        for album in results['items']:
            if album['name'] == 'Hurley':
                found = True

        self.assertTrue(found)

    def test_search_timeout(self):
        sp = Spotify(auth=self.token, requests_timeout=.01)
        try:
            results = sp.search(q='my*', type='track')
            self.assertTrue(False, 'unexpected search timeout')
        except requests.Timeout:
            self.assertTrue(True, 'expected search timeout')

    def test_album_search(self):
        results = self.spotify.search(q='weezer pinkerton', type='album')
        self.assertTrue('albums' in results)
        self.assertTrue(len(results['albums']['items']) > 0)
        self.assertTrue(
            results['albums']['items'][0]['name'].find('Pinkerton') >= 0)

    def test_track_search(self):
        results = self.spotify.search(q='el scorcho weezer', type='track')
        self.assertTrue('tracks' in results)
        self.assertTrue(len(results['tracks']['items']) > 0)
        self.assertTrue(results['tracks']['items'][0]['name'] == 'El Scorcho')

    def test_user(self):
        user = self.spotify.user(user='******')
        self.assertTrue(user['uri'] == 'spotify:user:plamere')

    def test_track_bad_id(self):
        try:
            track = self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_track_bad_id(self):
        try:
            track = self.spotify.track(self.bad_id)
            self.assertTrue(False)
        except SpotifyException:
            self.assertTrue(True)

    def test_unauthenticated_post_fails(self):
        with self.assertRaises(SpotifyException) as cm:
            self.spotify.user_playlist_create("spotify",
                                              "Best hits of the 90s")
        self.assertTrue(cm.exception.http_status == 401
                        or cm.exception.http_status == 403)

    def test_custom_requests_session(self):
        sess = requests.Session()
        sess.headers["user-agent"] = "spotipy-test"
        with_custom_session = Spotify(auth=self.token, requests_session=sess)
        self.assertTrue(
            with_custom_session.user(user="******")["uri"] == "spotify:user:akx")

    def test_force_no_requests_session(self):
        with_no_session = Spotify(auth=self.token, requests_session=False)
        self.assertFalse(isinstance(with_no_session._session,
                                    requests.Session))
        self.assertTrue(
            with_no_session.user(user="******")["uri"] == "spotify:user:akx")
예제 #17
0
class SpotifyClient:
    def __init__(self):
        token = self.get_token()
        self.sp = Spotify(auth=token)

    def get_token(self):
        scope = 'playlist-modify-private'
        return util.prompt_for_user_token(
            SPOTIFY_AUTH['USERNAME'],
            scope,
            client_id=SPOTIFY_AUTH['CLIENT_ID'],
            client_secret=SPOTIFY_AUTH['CLIENT_SECRET'],
            redirect_uri=SPOTIFY_AUTH['REDIRECT_URI'])

    def search_album(self, album_name, artist_name):
        results = self.sp.search(q=album_name, limit=20, type="album")
        for album in results["albums"]["items"]:
            if 'GB' in album['available_markets']:
                return album

    def get_album(self, album_name, artist_name):
        album_id = self.search_album(album_name, artist_name)
        try:
            return self.sp.album(album_id['uri'])
        except TypeError:
            return {"tracks": []}

    def get_album_tracks(self, album_name, artist_name):
        try:
            return self.get_album(album_name, artist_name)['tracks']
        except TypeError:
            return None

    def list_track_ids(self, album_name, artist_name):
        track_ids = []
        album_items = self.get_album_tracks(album_name, artist_name)
        if album_items:
            for track in album_items['items']:
                track_ids.append(track['id'])
        return track_ids

    def get_playlist(self):
        return self.sp.user_playlist(SPOTIFY_AUTH['USERNAME'], TARGET_PLAYLIST)

    def get_playlist_track_ids(self):
        track_ids = []
        offset = 0
        tracks = self.sp.user_playlist_tracks(
            SPOTIFY_AUTH['USERNAME'], TARGET_PLAYLIST, None, 100, offset)

        track_items = tracks['items']
        while tracks['next']:  # Paginate
            offset = offset + 100
            tracks = self.sp.user_playlist_tracks(
                SPOTIFY_AUTH['USERNAME'], TARGET_PLAYLIST, None, 100, offset)
            track_items = track_items + tracks['items']

        if len(track_items) > 0:
            for track in track_items:
                track_ids.append(track["track"]['id'])
        return track_ids

    def add_tracks(self, track_id_list):
        playlist_id = self.get_playlist()['id']
        self.sp.user_playlist_add_tracks(SPOTIFY_AUTH['USERNAME'],
                                         playlist_id,
                                         track_id_list)
예제 #18
0
class SpotifyConnection(object):
    def __init__(self, user_data):
        self.user_name = user_data['user_name']
        token = spotipy.util.prompt_for_user_token(
            self.user_name,
            scope='user-read-recently-played',
            client_id=user_data['client_id'],
            client_secret=user_data['client_secret'],
            redirect_uri=user_data['redirect_uri'])
        self.client = Spotify(auth=token)
        self.db = self.init_db()

    def init_db(self):
        return PostgreSQLConnection()

    def get_artist(self, artist_id):
        artist = self.db.session.query(Artist).get(artist_id)
        if artist:
            return artist
        else:
            artist_response = self.client.artist(artist_id)
            artist = Artist()
            artist.artist_id = artist_id
            artist.artist_data = artist_response
            self.db.save_instance(artist)
            print("> Artist {} was not in database.".format(
                artist.artist_data['name']))
            return self.db.session.query(Artist).get(artist_id)

    def get_album(self, album_id):
        album = self.db.session.query(Album).get(album_id)
        if album:
            return album
        else:
            album_response = self.client.album(album_id)
            album = Album()
            album.album_data = album_response
            album.album_id = album_response['id']
            # Artists
            for album_artist_response in album_response['artists']:
                album.artists.append(
                    self.get_artist(album_artist_response['id']))
            self.db.save_instance(album)
            print("> Album {} was not in database.".format(
                album.album_data['name']))
            return self.db.session.query(Album).get(album_id)

    def get_track(self, track_id):
        track = self.db.session.query(Track).get(track_id)
        if track:
            return track
        else:
            response = self.client.track(track_id)

            track = Track()
            track.track_id = track_id
            track.track_data = response
            # Album
            track.album = self.get_album(response['album']['id'])
            # Artists
            for artist_response in response['artists']:
                track.artists.append(self.get_artist(artist_response['id']))
            # Audio feature
            audio_feature_response = self.client.audio_features(track_id)[0]
            if audio_feature_response:  # Some tracks do not have audio features
                track.audio_feature_data = audio_feature_response
            print("> Track {} was not in database.".format(
                track.track_data['name']))
            self.db.save_instance(track)
            return self.db.session.query(Track).get(track_id)

    def get_play_from_played_at_utc_and_track_id(self, played_at_utc,
                                                 track_id):
        played_at_utc = convert_played_at_from_response_to_datetime(
            played_at_utc)
        played_at_utc = set_timezone_to_datetime(played_at_utc, timezone='UTC')
        played_at_cet = convert_datetime_from_timezone_to_timezone(
            played_at_utc, from_tz_code='UTC', to_tz_code='CET')
        # Play
        play = Play()
        play.user_name = self.user_name
        play.played_at_utc_timestamp = played_at_utc.timestamp() * 1000
        play.played_at_utc = played_at_utc
        play.played_at_cet = played_at_cet
        play.day = played_at_cet.day
        play.month = played_at_cet.month
        play.year = played_at_cet.year
        play.hour = played_at_cet.hour
        play.minute = played_at_cet.minute
        play.second = played_at_cet.second
        play.day_of_week = played_at_cet.weekday()
        play.week_of_year = played_at_cet.date().isocalendar()[1]
        # Track
        track = self.get_track(track_id)
        play.track = track
        play.track_id = track_id
        return play

    def _get_play_tuples_from_response(self, response):
        plays = []
        for item in response['items']:
            play_tuple = (item['played_at'], item['track']['id'])
            plays.append(play_tuple)
        return plays

    def _get_play_tuples(self, limit=50, after=None):
        play_tuples = []
        response = self.client._get('me/player/recently-played',
                                    after=after,
                                    limit=limit)
        play_tuples.extend(self._get_play_tuples_from_response(response))

        while response and 'next' in response:
            response = self.client.next(response)
            if response:
                play_tuples.extend(
                    self._get_play_tuples_from_response(response))

        return play_tuples

    def extract_plays(self):
        print("* Extracting latest plays of {}.".format(self.user_name))
        play_tuples = self._get_play_tuples()

        for played_at, track_id in play_tuples:
            play = self.get_play_from_played_at_utc_and_track_id(
                played_at, track_id)
            self.db.save_play(play)