Exemplo n.º 1
0
    def downloadArtistAlbum(self, includeSingles=True, artistID=None):
        while True:
            print("-------------ARTIST ALBUM--------------")
            if artistID is not None:
                sID = artistID
            else:
                sID = printChoice("Enter Artist ID(Enter '0' go back):", True,
                                  0)
                if sID == 0:
                    return

            array = self.tool.getArtistAlbum(sID, includeSingles)
            if self.tool.errmsg != "":
                printErr(0, "Get AlbumList Err! " + self.tool.errmsg)
                continue

            redownload = True
            if artistID is None:
                check = printChoice("Skip downloaded files?(y/n):")
                if not cmdHelper.isInputYes(check):
                    redownload = False

            for index, item in enumerate(array):
                print("----Album[{0}/{1}]----".format(index + 1, len(array)))
                self.downloadAlbum(item['id'], redownload)

            if artistID is not None:
                # Break out of the function if we are only downloading one artist's albums
                return
Exemplo n.º 2
0
def logIn(username="", password=""):
    cf = TidalConfig()
    if username == "" or password == "":
        print("----------------LogIn------------------")
        username = myinput("username:"******"password:"******"" and account2.errmsg != "":
            printErr(0, account.errmsg)
            return False
        elif account.errmsg != "":
            account = account2
        elif account2.errmsg != "":
            account2 = account
        cf.set_account(username, password, account.session_id,
                       account.country_code, account.user_id,
                       account2.session_id)

    Curtime = time.time()
    cf.set_lastlogintime(str(Curtime))
    return True
Exemplo n.º 3
0
def logIn(username="", password=""):
    if username == "" or password == "":
        print("----------------LogIn------------------")
        username = myinput("username:"******"password:"******"":
    #     printErr(0, account.errmsg)
    #     return False
    # if account2.errmsg != "":
    #     printErr(0, account2.errmsg)
    #     return False
    if account.errmsg != "" and account2.errmsg != "":
        printErr(0, account.errmsg)
        return False
    elif account.errmsg != "":
        account = account2
    elif account2.errmsg != "":
        account2 = account

    cf = TidalConfig()
    cf.set_account(username, password, account.session_id, account.country_code, account.user_id, account2.session_id)

    Curtime = time.time()
    cf.set_lastlogintime(str(Curtime))
    return True
    def __thradfunc_dl(self, paraList):
        count = 1
        printRet = True
        pstr = paraList['title'] + "(Download Err!)"
        redownload = True
        needDl = True
        bIsSuccess = False
        albumInfo = None
        index = None
        coverpath = None

        if 'redownload' in paraList:
            redownload = paraList['redownload']
        if 'retry' in paraList:
            count = count + paraList['retry']
        if 'show' in paraList:
            printRet = paraList['show']
        if 'album' in paraList:
            albumInfo = paraList['album']
        if 'index' in paraList:
            index = paraList['index']
        if 'coverpath' in paraList:
            coverpath = paraList['coverpath']

        if redownload is False:
            needDl = self.__isNeedDownload(paraList['path'], paraList['url'])

        if needDl:
            try:
                while count > 0:
                    count = count - 1
                    check = netHelper.downloadFile(paraList['url'],
                                                   paraList['path'])
                    if check is True:
                        if paraList['key'] == '':
                            break
                        key, nonce = decrypt_security_token(paraList['key'])
                        decrypt_file(paraList['path'], key, nonce)
                        break
                if check:
                    self.tool.setTrackMetadata(paraList['trackinfo'],
                                               paraList['path'], albumInfo,
                                               index, coverpath)
                    pstr = paraList['title']
                    bIsSuccess = True
            except:
                pass
        else:
            pstr = paraList['title']
            bIsSuccess = True

        if printRet:
            if (bIsSuccess):
                printSUCCESS(14, pstr)
            else:
                printErr(14, pstr)
        return
Exemplo n.º 5
0
    def downloadByFile(self, path):
        if not os.path.exists(path):
            return
        arr = self.tool.parseFile(path)
        print("----------------FILE------------------")
        print("[Number of albums]       %s" % (len(arr['album'])))
        print("[Number of artists]      %s" % (len(arr['artist'])))
        print("[Number of tracks]       %s" % (len(arr['track'])))
        print("[Number of videos]       %s" % (len(arr['video'])))
        print("[Number of URLs]         %s" % (len(arr['url'])))

        if len(arr['album']) > 0:
            redownload = True
            check = printChoice("Skip downloaded files?(y/n):")
            if not cmdHelper.isInputYes(check):
                redownload = False

        for index, item in enumerate(arr['album']):
            print("----Album[{0}/{1}]----".format(index + 1,
                                                  len(arr['album'])))
            print("[ID]          %s" % (item))
            self.downloadAlbum(item, redownload)
        for index, item in enumerate(arr['artist']):
            print(index)
            print("----Artist[{0}/{1}]----".format(index + 1,
                                                   len(arr['artist'])))
            print("[ID]          %s" % (item))
            includeSingles = self.config.includesingle == "True"
            self.downloadArtistAlbum(includeSingles, item)
        for index, item in enumerate(arr['track']):
            print("----Track[{0}/{1}]----".format(index + 1,
                                                  len(arr['track'])))
            print("[ID]                %s" % (item))
            self.downloadTrack(item)
        for index, item in enumerate(arr['video']):
            print("----Video[{0}/{1}]----".format(index + 1,
                                                  len(arr['video'])))
            print("[ID]                %s" % (item))
            self.downloadVideo(item)
        for index, item in enumerate(arr['url']):
            print("----Url[{0}/{1}]----".format(index + 1, len(arr['url'])))
            print("[link]        %s" % (item))
            stype, sid = self.tool.parseLink(item)
            if stype is None or sid is None:
                printErr(14, 'Link can`t parse!')
                continue
            print("[ID]          %s" % (sid))
            if stype == "album":
                print("[Type]        %s" % ("album"))
                self.downloadAlbum(sid)
            if stype == "track":
                print("[Type]        %s" % ("track"))
                self.downloadTrack(sid)
            if stype == "video":
                print("[Type]        %s" % ("video"))
                self.downloadVideo(sid)
Exemplo n.º 6
0
def logIn(username = "", password = ""):
    if username == "" or password == "":
        print("----------------LogIn------------------")
        username = myinput("username:"******"password:"******"":
        printErr(0, account.errmsg)
        return False

    cf = TidalConfig()
    cf.set_account(username, password, account.session_id, account.country_code, account.user_id)
    return True
Exemplo n.º 7
0
def setAccessToken():
    print("------------setAccessToken------------------")
    account = TidalMobileSession()
    cf = TidalConfig()
    while True:
        account.access_token = myinput("AccessToken(Enter '0' cancel):")
        if account.access_token == '0':
            break
        if account.valid() is True:
            account.getCountryCode()
            cf.set_account2(cf.username, cf.password, account.access_token,
                            account.country_code, account.user_id)
            break
        else:
            printErr(0, "AccessToken is not valid!")
Exemplo n.º 8
0
    def downloadArtistAlbum(self):
        while True:
            print("-------------ARTIST ALBUM--------------")
            sID = printChoice("Enter ArtistID(Enter '0' go back):", True, 0)
            if sID == 0:
                return

            array = self.tool.getArtistAlbum(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get AlbumList Err! " + self.tool.errmsg)
                continue

            for index, item in enumerate(array):
                print("----Album[{0}/{1}]----".format(index, len(array)))
                self.downloadAlbum(item['id'])
Exemplo n.º 9
0
    def downloadArtistAlbum(self):
        while True:
            print("-------------ARTIST ALBUM--------------")
            sID = printChoice("Enter ArtistID(Enter '0' go back):", True, 0)
            if sID == 0:
                return

            array = self.tool.getArtistAlbum(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get AlbumList Err! " + self.tool.errmsg)
                continue

            redownload = True
            check = printChoice("Skip downloaded files?(y/n):")
            if not cmdHelper.isInputYes(check):
                redownload = False

            for index, item in enumerate(array):
                print("----Album[{0}/{1}]----".format(index + 1, len(array)))
                self.downloadAlbum(item['id'], redownload)
Exemplo n.º 10
0
 def downloadByFile(self, path):
     if not os.path.exists(path):
         return
     arr = self.tool.parseFile(path)
     print("----------------FILE------------------")
     print("[NumOfAlbum]       %s" % (len(arr['album'])))
     print("[NumOfTrack]       %s" % (len(arr['track'])))
     print("[NumOfVideo]       %s" % (len(arr['video'])))
     print("[NumOfUrl]         %s" % (len(arr['url'])))
     for index, item in enumerate(arr['album']):
         print("----Album[{0}/{1}]----".format(index + 1,
                                               len(arr['album'])))
         print("[ID]          %s" % (item))
         self.downloadAlbum(item)
     for index, item in enumerate(arr['track']):
         print("----Track[{0}/{1}]----".format(index + 1,
                                               len(arr['track'])))
         print("[ID]                %s" % (item))
         self.downloadTrack(item)
     for index, item in enumerate(arr['video']):
         print("----Video[{0}/{1}]----".format(index + 1,
                                               len(arr['video'])))
         print("[ID]                %s" % (item))
         self.downloadVideo(item)
     for index, item in enumerate(arr['url']):
         print("----Url[{0}/{1}]----".format(index + 1, len(arr['url'])))
         print("[link]        %s" % (item))
         stype, sid = self.tool.parseLink(item)
         if stype is None or sid is None:
             printErr(14, 'Link can`t parse!')
             continue
         print("[ID]          %s" % (sid))
         if stype == "album":
             print("[Type]        %s" % ("album"))
             self.downloadAlbum(sid)
         if stype == "track":
             print("[Type]        %s" % ("track"))
             self.downloadTrack(sid)
         if stype == "video":
             print("[Type]        %s" % ("video"))
             self.downloadVideo(sid)
Exemplo n.º 11
0
    def downloadTrack(self):
        while True:
            targetDir = self.config.outputdir + "/Track/"
            print("----------------TRACK------------------")
            sID = printChoice("Enter TrackID(Enter '0' go back):", True, 0)
            if sID == 0:
                return

            aTrackInfo = self.tool.getTrack(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get TrackInfo Err! " + self.tool.errmsg)
                return

            print("[TrackTitle ]       %s" % (aTrackInfo['title']))
            print("[Duration   ]       %s" % (aTrackInfo['duration']))
            print("[TrackNumber]       %s" % (aTrackInfo['trackNumber']))
            print("[Version    ]       %s\n" % (aTrackInfo['version']))
            # download
            streamInfo = self.tool.getStreamUrl(sID, self.config.quality)
            if self.tool.errmsg != "":
                printErr(
                    14, aTrackInfo['title'] + "(Get Stream Url Err!" +
                    self.tool.errmsg + ")")
                continue

            fileType = self._getSongExtension(streamInfo['url'])
            filePath = targetDir + "/" + pathHelper.replaceLimitChar(
                aTrackInfo['title'], '-') + fileType
            paraList = {
                'title': aTrackInfo['title'],
                'trackinfo': aTrackInfo,
                'url': streamInfo['url'],
                'path': filePath,
                'retry': 3,
                'key': streamInfo['encryptionKey']
            }
            self.thread.start(self.__thradfunc_dl, paraList)
            # wait all download thread
            self.thread.waitAll()
            self.tool.removeTmpFile(targetDir)
        return
Exemplo n.º 12
0
    def downloadFavorite(self):
        targetDir = self.config.outputdir + "/Favorite/"
        pathHelper.mkdirs(targetDir)

        trackList, videoList = self.tool.getFavorite(self.config.userid)
        if self.tool.errmsg != "":
            printErr(0, "Get FavoriteList Err! " + self.tool.errmsg)
            return

        print("[NumberOfTracks]       %s" % (len(trackList)))
        print("[NumberOfVideos]       %s" % (len(videoList)))
        # download track
        for item in trackList:
            item = item['item']
            streamInfo = self.tool.getStreamUrl(str(item['id']),
                                                self.config.quality)
            if self.tool.errmsg != "" or not streamInfo:
                printErr(
                    14, item['title'] + "(Get Stream Url Err!!" +
                    self.tool.errmsg + ")")
                continue

            fileType = self._getSongExtension(streamInfo['url'])
            filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                item['title'], '-') + fileType
            aAlbumInfo = self.tool.getAlbum(item['album']['id'])
            paraList = {
                'album': aAlbumInfo,
                'title': item['title'],
                'trackinfo': item,
                'url': streamInfo['url'],
                'path': filePath,
                'retry': 3,
                'key': streamInfo['encryptionKey'],
                'codec': streamInfo['codec']
            }
            self.thread.start(self.__thradfunc_dl, paraList)
        self.thread.waitAll()

        # download video
        for item in videoList:
            item = item['item']

            filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                item['title'], '-') + ".mp4"
            filePath = os.path.abspath(filePath)
            if os.access(filePath, 0):
                os.remove(filePath)

            resolutionList, urlList = self.tool.getVideoResolutionList(
                item['id'])
            selectIndex = self.__getVideoResolutionIndex(resolutionList)
            if self.ffmpeg.mergerByM3u8_Multithreading2(
                    urlList[int(selectIndex)], filePath,
                    showprogress=self.showpro):
                printSUCCESS(14, item['title'])
            else:
                printErr(14, item['title'])
        return
Exemplo n.º 13
0
    def downloadTrack(self, track_id=None):
        while_count = 9999
        while while_count > 0:
            while_count -= 1

            if track_id is not None:
                while_count = 0
                sID = track_id
            else:
                print("----------------TRACK------------------")
                sID = printChoice("Enter TrackID(Enter '0' go back):", True, 0)
                if sID == 0:
                    return
            aTrackInfo = self.tool.getTrack(sID)
            if self.tool.errmsg != "":
                printErr(0,"Get TrackInfo Err! " + self.tool.errmsg)
                return
            aAlbumInfo = self.tool.getAlbum(aTrackInfo['album']['id'])
            if self.tool.errmsg != "":
                printErr(0,"Get TrackInfo Err! " + self.tool.errmsg)
                return
            
            # t = self.tool.getTrackContributors(sID)

            print("[AlbumTitle ]       %s" % (aAlbumInfo['title']))
            print("[TrackTitle ]       %s" % (aTrackInfo['title']))
            print("[Duration   ]       %s" % (aTrackInfo['duration']))
            print("[TrackNumber]       %s" % (aTrackInfo['trackNumber']))
            print("[Version    ]       %s\n" % (aTrackInfo['version']))

            # Creat OutputDir
            targetDir = self.__creatAlbumDir(aAlbumInfo)
            # download cover
            coverPath = targetDir + '/' + pathHelper.replaceLimitChar(aAlbumInfo['title'], '-') + '.jpg'
            coverUrl  = self.tool.getAlbumArtworkUrl(aAlbumInfo['cover'])
            netHelper.downloadFile(coverUrl, coverPath)

            # download
            streamInfo = self.tool.getStreamUrl(sID, self.config.quality)
            if self.tool.errmsg != "":
                printErr(14, aTrackInfo['title'] + "(Get Stream Url Err!" + self.tool.errmsg + ")")
                continue

            fileType = self._getSongExtension(streamInfo['url'])
            filePath = self.__getAlbumSongSavePath(targetDir, aAlbumInfo, aTrackInfo, fileType)
            # filePath = targetDir + "/" + pathHelper.replaceLimitChar(aTrackInfo['title'],'-') + fileType
            paraList = {'album':aAlbumInfo, 
                        'title': aTrackInfo['title'], 
                        'trackinfo':aTrackInfo, 
                        'url': streamInfo['url'], 
                        'path': filePath, 
                        'retry': 3, 
                        'key':streamInfo['encryptionKey'],
                        'coverpath': coverPath}
            self.thread.start(self.__thradfunc_dl, paraList)
            # wait all download thread
            self.thread.waitAll()
            self.tool.removeTmpFile(targetDir)
        return
Exemplo n.º 14
0
    def downloadVideo(self):
        while True:
            targetDir = self.config.outputdir + "/Video/"
            print("----------------VIDEO------------------")
            sID = printChoice("Enter VideoID(Enter '0' go back):", True, 0)
            if sID == 0:
                return
            aVideoInfo = self.tool.getVideo(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get VideoInfo Err! " + self.tool.errmsg)
                continue

            print("[Title      ]       %s" % (aVideoInfo['title']))
            print("[Duration   ]       %s" % (aVideoInfo['duration']))
            print("[TrackNumber]       %s" % (aVideoInfo['trackNumber']))
            print("[Type       ]       %s\n" % (aVideoInfo['type']))

            # get resolution
            index = 0
            resolutionList, urlList = self.tool.getVideoResolutionList(sID)
            if self.tool.errmsg != "":
                printErr(14, self.tool.errmsg)
                continue
            # print("-Index--Resolution--")
            # for item in resolutionList:
            #     print('   ' + str(index) + "    " + resolutionList[index])
            #     index = index + 1
            # print("--------------------")
            # while True:
            #     index = printChoice("Enter ResolutionIndex:", True, 0)
            #     if index == '' or index == None or int(index) >= len(resolutionList):
            #         printErr(0, "ResolutionIndex is err")
            #         continue
            #     break
            index = self.__getVideoResolutionIndex(resolutionList)
            path = targetDir + "/" + pathHelper.replaceLimitChar(
                aVideoInfo['title'], '-') + ".mp4"
            path = os.path.abspath(path)
            if os.access(path, 0):
                os.remove(path)

            if self.ffmpeg.mergerByM3u8_Multithreading(urlList[int(index)],
                                                       path, True):
                printSUCCESS(14, aVideoInfo['title'])
            else:
                printErr(14, aVideoInfo['title'])
        return
Exemplo n.º 15
0
    def downloadVideo(self, video_id=None):
        flag = True
        while flag:
            targetDir = self.config.outputdir + "/Video/"
            if video_id is None:
                print("----------------VIDEO------------------")
                sID = printChoice("Enter VideoID(Enter '0' go back):", True, 0)
                if sID == 0:
                    return
            else:
                flag = False
                sID = video_id

            aVideoInfo = self.tool.getVideo(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get VideoInfo Err! " + self.tool.errmsg)
                continue

            print("[Title      ]       %s" % (aVideoInfo['title']))
            print("[Duration   ]       %s" % (aVideoInfo['duration']))
            print("[TrackNumber]       %s" % (aVideoInfo['trackNumber']))
            print("[Type       ]       %s\n" % (aVideoInfo['type']))

            # get resolution
            index = 0
            resolutionList, urlList = self.tool.getVideoResolutionList(sID)
            if self.tool.errmsg != "":
                printErr(14, self.tool.errmsg)
                continue

            index = self.__getVideoResolutionIndex(resolutionList)
            path = targetDir + "/" + pathHelper.replaceLimitChar(
                aVideoInfo['title'], '-') + ".mp4"
            path = os.path.abspath(path)
            if os.access(path, 0):
                os.remove(path)

            if self.ffmpeg.mergerByM3u8_Multithreading2(
                    urlList[int(index)], path, True):
                printSUCCESS(14, aVideoInfo['title'])
            else:
                printErr(14, aVideoInfo['title'])
        return
Exemplo n.º 16
0
    def downloadAlbum(self):
        while True:
            print("----------------ALBUM------------------")
            sID = printChoice("Enter AlbumID(Enter '0' go back):", True, 0)
            if sID == 0:
                return

            aAlbumInfo = self.tool.getAlbum(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get AlbumInfo Err! " + self.tool.errmsg)
                continue

            print("[Title]       %s" % (aAlbumInfo['title']))
            print("[SongNum]     %s\n" % (aAlbumInfo['numberOfTracks']))

            # Get Tracks
            aAlbumTracks = self.tool.getAlbumTracks(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get AlbumTracks Err!" + self.tool.errmsg)
                return
            # Creat OutputDir
            targetDir = self.__creatAlbumDir(aAlbumInfo)
            # write msg
            string = self.tool.convertAlbumInfoToString(
                aAlbumInfo, aAlbumTracks)
            with open(targetDir + "/AlbumInfo.txt", 'w',
                      encoding='utf-8') as fd:
                fd.write(string)
            # download cover
            coverPath = targetDir + '/' + pathHelper.replaceLimitChar(
                aAlbumInfo['title'], '-') + '.jpg'
            coverUrl = self.tool.getAlbumArtworkUrl(aAlbumInfo['cover'])
            netHelper.downloadFile(coverUrl, coverPath)
            # check exist files
            redownload = True
            existFiles = pathHelper.getDirFiles(targetDir)
            for item in existFiles:
                if '.txt' in item:
                    continue
                if '.jpg' in item:
                    continue
                check = printChoice(
                    "Some TrackFile Exist.Is Redownload?(y/n):")
                if check != 'y' and check != 'yes':
                    redownload = False
                break
            # download album tracks
            for item in aAlbumTracks['items']:
                streamInfo = self.tool.getStreamUrl(str(item['id']),
                                                    self.config.quality)
                if self.tool.errmsg != "":
                    printErr(
                        14, item['title'] + "(Get Stream Url Err!" +
                        self.tool.errmsg + ")")
                    continue

                fileType = self._getSongExtension(streamInfo['url'])
                filePath = self.__getAlbumSongSavePath(targetDir, aAlbumInfo,
                                                       item, fileType)
                paraList = {
                    'album': aAlbumInfo,
                    'redownload': redownload,
                    'title': item['title'],
                    'trackinfo': item,
                    'url': streamInfo['url'],
                    'path': filePath,
                    'retry': 3,
                    'key': streamInfo['encryptionKey']
                }
                self.thread.start(self.__thradfunc_dl, paraList)
            # wait all download thread
            self.thread.waitAll()
            self.tool.removeTmpFile(targetDir)
        return
Exemplo n.º 17
0
def setting():
    cf = TidalConfig()
    print("----------------Setting----------------")
    print("OutputDir    :\t" + cf.outputdir)
    print("SoundQuality :\t" + cf.quality)
    print("Resolution   :\t" + cf.resolution)
    print("ThreadNum    :\t" + cf.threadnum)
    while True:
        outputdir = myinput("Outputdir(Enter '0' Unchanged):".ljust(12))
        if outputdir == '0':
            outputdir = cf.outputdir
            break
        if os.path.isdir(outputdir) == False:
            printErr(0, "Path is Err!")
            continue
        break
    while True:
        index = myinputInt("Quality(0-LOW,1-HIGH,2-LOSSLESS):".ljust(12), 999)
        if index > 2 or index < 0:
            printErr(0, "Quality Err!")
            continue
        if index == 0:
            quality = 'LOW'
        if index == 1:
            quality = 'HIGH'
        if index == 2:
            quality = 'LOSSLESS'
        break
    while True:
        index = myinputInt(
            "Resolution(0-1080,1-720,2-480,3-360,4-240):".ljust(12), 99)
        if index > 4 or index < 0:
            printErr(0, "ThreadNum Err")
            continue
        if index == 0:
            resolution = '1080'
        if index == 1:
            resolution = '720'
        if index == 2:
            resolution = '480'
        if index == 3:
            resolution = '360'
        if index == 4:
            resolution = '240'
        break
    while True:
        threadnum = myinput("ThreadNum:".ljust(12))
        if cf.valid_threadnum(threadnum) == False:
            printErr(0, "ThreadNum Err")
            continue
        break

    cf.set_outputdir(outputdir)
    cf.set_quality(quality)
    cf.set_resolution(resolution)
    cf.set_threadnum(threadnum)

    pathHelper.mkdirs(outputdir + "/Album/")
    pathHelper.mkdirs(outputdir + "/Playlist/")
    pathHelper.mkdirs(outputdir + "/Video/")
    pathHelper.mkdirs(outputdir + "/Favorite/")
    return
Exemplo n.º 18
0
def setting():
    cf = TidalConfig()
    print("----------------Settings----------------")
    print("Output directory                 :\t" + cf.outputdir)
    print("Sound Quality                    :\t" + cf.quality)
    print("Video Resolution                 :\t" + cf.resolution)
    print("Download Threads                 :\t" + cf.threadnum)
    print("Only M4a                         :\t" + cf.onlym4a)
    print("Show download progress           :\t" + cf.showprogress +
          "(enable when threadnum=1)")
    print("Use hyphens                      :\t" + cf.addhyphen +
          "(between number and title)")
    print("Add year                         :\t" + cf.addyear +
          "(in album title)")
    print("Add explicit tag                 :\t" + cf.addexplicit)
    print("Playlist songs in artist folders :\t" + cf.plfile2arfolder +
          "(organized with artist folder)")
    print("Include singles                  :\t" + cf.includesingle +
          "(download artist album)")
    print("Save covers                      :\t" + cf.savephoto)
    print("ArtistName Before Track-Title    :\t" + cf.artistbeforetitle)
    print("Add ID Before AlbumFolderName    :\t" + cf.addAlbumidbeforefolder)
    while True:
        outputdir = myinput("Output directory(Enter '0' Unchanged):".ljust(12))
        if outputdir == '0':
            outputdir = cf.outputdir
            break
        if os.path.isdir(outputdir) == False:
            printErr(0, "Path is Err!")
            continue
        break
    while True:
        index = myinputInt(
            "Download Quality(0-LOW,1-HIGH,2-LOSSLESS,3-HI_RES):".ljust(12),
            999)
        if index > 3 or index < 0:
            printErr(0, "Quality Err!")
            continue
        if index == 0:
            quality = 'LOW'
        if index == 1:
            quality = 'HIGH'
        if index == 2:
            quality = 'LOSSLESS'
        if index == 3:
            quality = 'HI_RES'
        break
    while True:
        index = myinputInt(
            "Video resolution(0-1080,1-720,2-480,3-360,4-240):".ljust(12), 99)
        if index > 4 or index < 0:
            printErr(0, "Resolution Err")
            continue
        if index == 0:
            resolution = '1080'
        if index == 1:
            resolution = '720'
        if index == 2:
            resolution = '480'
        if index == 3:
            resolution = '360'
        if index == 4:
            resolution = '240'
        break
    while True:
        threadnum = myinput("Number of download threads:".ljust(12))
        if cf.valid_threadnum(threadnum) == False:
            printErr(0, "ThreadNum Err")
            continue
        break

    status = myinputInt("Convert Mp4 to M4a(0-No, 1-Yes):".ljust(12), 0)
    status2 = myinputInt(
        "Show download progress (only available on single thread)(0-No, 1-Yes):"
        .ljust(12), 0)
    status3 = myinputInt(
        "Use hyphens instead of spaces in file names(0-No, 1-Yes):".ljust(12),
        0)

    while True:
        index = myinputInt(
            "Add year to album folder names(0-No, 1-Before, 2-After):".ljust(
                12), 99)
        if index > 2 or index < 0:
            printErr(0, "Addyear input Err")
            continue
        if index == 0:
            addyear = 'No'
        if index == 1:
            addyear = 'Before'
        if index == 2:
            addyear = 'After'
        break

    status5 = myinputInt(
        "Download playlist songs in artist folder structure? (0-No,1-Yes):".
        ljust(12), 0)
    status6 = myinputInt(
        "Add explicit tag to file names(0-No, 1-Yes):".ljust(12), 0)
    status7 = myinputInt(
        "Include singles and EPs when downloading an artist's albums (0-No, 1-Yes):"
        .ljust(12), 0)
    status8 = myinputInt("Save covers(0-No, 1-Yes):".ljust(12), 0)
    status9 = myinputInt(
        "Add artistName before trackTitle(0-No, 1-Yes):".ljust(12), 0)
    status10 = myinputInt(
        "Add ID Before AlbumFolderName(0-No, 1-Yes):".ljust(12), 0)

    cf.set_outputdir(outputdir)
    cf.set_quality(quality)
    cf.set_resolution(resolution)
    cf.set_threadnum(threadnum)
    cf.set_onlym4a(status)
    cf.set_showprogress(status2)
    cf.set_addhyphen(status3)
    cf.set_addyear(addyear)
    cf.set_plfile2arfolder(status5)
    cf.set_addexplicit(status6)
    cf.set_includesingle(status7)
    cf.set_savephoto(status8)
    cf.set_artistbeforetitle(status9)
    cf.set_addAlbumidbeforefolder(status10)

    pathHelper.mkdirs(outputdir + "/Album/")
    pathHelper.mkdirs(outputdir + "/Playlist/")
    pathHelper.mkdirs(outputdir + "/Video/")
    pathHelper.mkdirs(outputdir + "/Favorite/")
    return
Exemplo n.º 19
0
    def __thradfunc_dl(self, paraList):
        count = 1
        printRet = True
        pstr = paraList['title'] + "(Download Err!)"
        redownload = True
        needDl = True
        bIsSuccess = False
        albumInfo = None
        index = None
        coverpath = None

        if 'redownload' in paraList:
            redownload = paraList['redownload']
        if 'retry' in paraList:
            count = count + paraList['retry']
        if 'show' in paraList:
            printRet = paraList['show']
        if 'album' in paraList:
            albumInfo = paraList['album']
        if 'index' in paraList:
            index = paraList['index']
        if 'coverpath' in paraList:
            coverpath = paraList['coverpath']

        if redownload is False:
            needDl = self.__isNeedDownload(paraList['path'], paraList['url'])

        # DEBUG
        # self.tool.setTrackMetadata(paraList['trackinfo'], paraList['path'], albumInfo, index, coverpath)
        showprogress = False
        if int(self.config.threadnum) <= 1 and self.showpro:
            showprogress = True

        Contributors = self.tool.getTrackContributors(
            paraList['trackinfo']['id'])
        if needDl:
            try:
                while count > 0:
                    count = count - 1
                    check = netHelper.downloadFile(paraList['url'],
                                                   paraList['path'] + '.part',
                                                   showprogress=showprogress,
                                                   stimeout=20)
                    if check is True:
                        if paraList['key'] == '':
                            # unencrypted -> just move into place
                            os.replace(paraList['path'] + '.part',
                                       paraList['path'])
                            break
                        else:
                            # encrypted -> decrypt and remove encrypted file
                            key, nonce = decrypt_security_token(
                                paraList['key'])
                            decrypt_file(paraList['path'] + '.part',
                                         paraList['path'], key, nonce)
                            os.remove(paraList['path'] + '.part')
                        break
                if check:
                    bIsSuccess = True
                    paraList['path'] = self.tool.covertMp4toM4a(
                        paraList['path'])
                    self.tool.setTrackMetadata(paraList['trackinfo'],
                                               paraList['path'], albumInfo,
                                               index, coverpath, Contributors)
                    pstr = paraList['title']
            except Exception as e:
                printErr(14, str(e) + " while downloading " + paraList['url'])
        else:
            pstr = paraList['title']
            bIsSuccess = True

        if printRet:
            if (bIsSuccess):
                printSUCCESS(14, pstr)
            else:
                printErr(14, pstr)
        return
Exemplo n.º 20
0
    def downloadPlaylist(self, playlist_id=None):
        while True:
            targetDir = self.config.outputdir + "/Playlist/"
            if playlist_id is None:
                print("--------------PLAYLIST-----------------")
                sID = printChoice("Enter PlayListID(Enter '0' go back):")
                if sID == '0':
                    return
            else:
                sID = playlist_id

            aPlaylistInfo, aItemInfo = self.tool.getPlaylist(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get PlaylistInfo Err! " + self.tool.errmsg)
                return

            print("[Title]                %s" % (aPlaylistInfo['title']))
            print("[Type]                 %s" % (aPlaylistInfo['type']))
            print("[NumberOfTracks]       %s" %
                  (aPlaylistInfo['numberOfTracks']))
            print("[NumberOfVideos]       %s" %
                  (aPlaylistInfo['numberOfVideos']))
            print("[Duration]             %s\n" % (aPlaylistInfo['duration']))

            # Creat OutputDir
            targetDir = targetDir + pathHelper.replaceLimitChar(
                aPlaylistInfo['title'], '-')
            targetDir = os.path.abspath(targetDir).strip()
            pathHelper.mkdirs(targetDir)
            # write msg
            string = self.tool.convertPlaylistInfoToString(
                aPlaylistInfo, aItemInfo)
            with codecs.open(targetDir + "/PlaylistInfo.txt", 'w',
                             'utf-8') as fd:
                fd.write(string)
            # download cover
            coverPath = targetDir + '/' + pathHelper.replaceLimitChar(
                aPlaylistInfo['title'], '-') + '.jpg'
            coverUrl = self.tool.getPlaylistArtworkUrl(aPlaylistInfo['uuid'])
            check = netHelper.downloadFile(coverUrl, coverPath)

            # download track
            bBreakFlag = False
            bFirstTime = True
            errIndex = []
            index = 0

            while bBreakFlag is False:
                self.check.clear()
                index = 0
                tmpcoverpath = []
                for item in aItemInfo:
                    type = item['type']
                    item = item['item']
                    if type != 'track':
                        continue

                    index = index + 1
                    if bFirstTime is False:
                        if self.check.isInErr(index - 1, errIndex) == False:
                            continue

                    streamInfo = self.tool.getStreamUrl(
                        str(item['id']), self.config.quality)
                    # streamInfo = self.tool.getStreamUrl(str(item['id']), 'DOLBY_ATMOS')
                    if self.tool.errmsg != "" or not streamInfo:
                        printErr(
                            14, item['title'] + "(Get Stream Url Err!!" +
                            self.tool.errmsg + ")")
                        continue
                    aAlbumInfo = self.tool.getAlbum(item['album']['id'])
                    fileType = self._getSongExtension(streamInfo['url'])

                    # change targetDir
                    targetDir2 = targetDir
                    if self.config.plfile2arfolder == "True":
                        targetDir2 = self.__creatAlbumDir(aAlbumInfo)
                        filePath = self.__getAlbumSongSavePath(
                            targetDir2, aAlbumInfo, item, fileType)
                        paraList = {
                            'album': aAlbumInfo,
                            'title': item['title'],
                            'trackinfo': item,
                            'url': streamInfo['url'],
                            'path': filePath,
                            'retry': 3,
                            'key': streamInfo['encryptionKey']
                        }
                    else:
                        seq = self.tool.getIndexStr(index, len(aItemInfo))
                        filePath = targetDir2 + '/' + seq + " " + pathHelper.replaceLimitChar(
                            item['title'], '-') + fileType
                        paraList = {
                            'album': aAlbumInfo,
                            'index': index,
                            'title': item['title'],
                            'trackinfo': item,
                            'url': streamInfo['url'],
                            'path': filePath,
                            'retry': 3,
                            'key': streamInfo['encryptionKey']
                        }

                    try:
                        coverPath = targetDir2 + '/' + pathHelper.replaceLimitChar(
                            aAlbumInfo['title'], '-') + '.jpg'
                        coverUrl = self.tool.getAlbumArtworkUrl(
                            aAlbumInfo['cover'])
                        netHelper.downloadFile(coverUrl, coverPath)
                        paraList['coverpath'] = coverPath
                        tmpcoverpath.append(coverPath)
                    except:
                        cmdHelper.myprint(
                            "Could not download artwork for '{}'".format(
                                item['title']), cmdHelper.TextColor.Red, None)

                    if self.config.onlym4a == "True":
                        self.check.addPath(filePath.replace(".mp4", ".m4a"))
                    else:
                        self.check.addPath(filePath)
                    self.thread.start(self.__thradfunc_dl, paraList)
                self.thread.waitAll()
                self.tool.removeTmpFile(targetDir)

                # remove cover
                if self.config.savephoto != 'True':
                    for item in tmpcoverpath:
                        pathHelper.remove(item)

                bBreakFlag = True
                bFirstTime = False

                # check
                isErr, errIndex = self.check.checkPaths()
                if isErr:
                    check = printChoice(
                        "[Err]\t\t" + str(len(errIndex)) +
                        " Tracks Download Failed.Try Again?(y/n):")
                    if check == 'y' or check == 'Y':
                        bBreakFlag = False

            # download video
            for item in aItemInfo:
                type = item['type']
                item = item['item']
                if type != 'video':
                    continue

                filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                    item['title'], '-') + ".mp4"
                filePath = os.path.abspath(filePath)
                if os.access(filePath, 0):
                    os.remove(filePath)

                videoID = item['id']
                resolutionList, urlList = self.tool.getVideoResolutionList(
                    videoID)
                if urlList is None:
                    printErr(14, item['title'] + '(' + self.tool.errmsg + ')')
                else:
                    selectIndex = self.__getVideoResolutionIndex(
                        resolutionList)
                    if self.ffmpeg.mergerByM3u8_Multithreading2(
                            urlList[int(selectIndex)],
                            filePath,
                            showprogress=self.showpro):
                        printSUCCESS(14, item['title'])
                    else:
                        printErr(14,
                                 item['title'] + "(Download Or Merger Err!)")
            if playlist_id is not None:
                return
        return
Exemplo n.º 21
0
    def downloadPlaylist(self):
        while True:
            targetDir = self.config.outputdir + "/Playlist/"
            print("--------------PLAYLIST-----------------")
            sID = printChoice("Enter PlayListID(Enter '0' go back):")
            if sID == '0':
                return

            aPlaylistInfo, aItemInfo = self.tool.getPlaylist(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get PlaylistInfo Err! " + self.tool.errmsg)
                return

            print("[Title]                %s" % (aPlaylistInfo['title']))
            print("[Type]                 %s" % (aPlaylistInfo['type']))
            print("[NumberOfTracks]       %s" %
                  (aPlaylistInfo['numberOfTracks']))
            print("[NumberOfVideos]       %s" %
                  (aPlaylistInfo['numberOfVideos']))
            print("[Duration]             %s\n" % (aPlaylistInfo['duration']))

            # Creat OutputDir
            targetDir = targetDir + pathHelper.replaceLimitChar(
                aPlaylistInfo['title'], '-')
            targetDir = os.path.abspath(targetDir)
            pathHelper.mkdirs(targetDir)
            # write msg
            string = self.tool.convertPlaylistInfoToString(
                aPlaylistInfo, aItemInfo)
            with open(targetDir + "/PlaylistInfo.txt", 'w',
                      encoding='utf-8') as fd:
                fd.write(string)

            # download track
            bBreakFlag = False
            bFirstTime = True
            errIndex = []
            index = 0

            while bBreakFlag is False:
                self.check.clear()
                index = 0
                for item in aItemInfo:
                    type = item['type']
                    item = item['item']
                    if type != 'track':
                        continue

                    index = index + 1
                    if bFirstTime is False:
                        if self.check.isInErr(index - 1, errIndex) == False:
                            continue

                    streamInfo = self.tool.getStreamUrl(
                        str(item['id']), self.config.quality)
                    if self.tool.errmsg != "":
                        printErr(
                            14, item['title'] + "(Get Stream Url Err!!" +
                            self.tool.errmsg + ")")
                        continue

                    fileType = self._getSongExtension(streamInfo['url'])
                    filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                        item['title'], '-') + fileType
                    paraList = {
                        'index': index,
                        'title': item['title'],
                        'trackinfo': item,
                        'url': streamInfo['url'],
                        'path': filePath,
                        'retry': 3,
                        'key': streamInfo['encryptionKey']
                    }
                    self.check.addPath(filePath)
                    if not os.path.isfile(filePath):
                        self.thread.start(self.__thradfunc_dl, paraList)
                self.thread.waitAll()
                self.tool.removeTmpFile(targetDir)

                bBreakFlag = True
                bFirstTime = False

                # check
                isErr, errIndex = self.check.checkPaths()
                if isErr:
                    check = printChoice(
                        "[Err]\t\t" + len(errIndex) +
                        " Tracks Download Failed.Try Again?(y/n):")
                    if check == 'y' or check == 'Y':
                        bBreakFlag = False

            # download video
            for item in aItemInfo:
                type = item['type']
                item = item['item']
                if type != 'video':
                    continue

                filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                    item['title'], '-') + ".mp4"
                filePath = os.path.abspath(filePath)
                if os.access(filePath, 0):
                    os.remove(filePath)

                videoID = item['id']
                resolutionList, urlList = self.tool.getVideoResolutionList(
                    videoID)
                if urlList is None:
                    printErr(14, item['title'] + '(' + self.tool.errmsg + ')')
                else:
                    selectIndex = self.__getVideoResolutionIndex(
                        resolutionList)
                    if self.ffmpeg.mergerByM3u8_Multithreading(
                            urlList[selectIndex], filePath,
                            showprogress=False):
                        printSUCCESS(14, item['title'])
                    else:
                        printErr(14,
                                 item['title'] + "(Download Or Merger Err!)")
        return
Exemplo n.º 22
0
def setting():
    cf = TidalConfig()
    print("----------------Settings----------------")
    print("OutputDir    :\t" + cf.outputdir)
    print("SoundQuality :\t" + cf.quality)
    print("Resolution   :\t" + cf.resolution)
    print("ThreadNum    :\t" + cf.threadnum)
    print("OnlyM4a      :\t" + cf.onlym4a)
    print("ShowProgress :\t" + cf.showprogress + "(enable when threadnum=1)")
    print("AddHyphen    :\t" + cf.addhyphen + "(between number and title)")
    while True:
        outputdir = myinput("Outputdir(Enter '0' Unchanged):".ljust(12))
        if outputdir == '0':
            outputdir = cf.outputdir
            break
        if os.path.isdir(outputdir) == False:
            printErr(0, "Path is Err!")
            continue
        break
    while True:
        index = myinputInt(
            "Quality(0-LOW,1-HIGH,2-LOSSLESS,3-HI_RES):".ljust(12), 999)
        if index > 3 or index < 0:
            printErr(0, "Quality Err!")
            continue
        if index == 0:
            quality = 'LOW'
        if index == 1:
            quality = 'HIGH'
        if index == 2:
            quality = 'LOSSLESS'
        if index == 3:
            quality = 'HI_RES'
        break
    while True:
        index = myinputInt(
            "Resolution(0-1080,1-720,2-480,3-360,4-240):".ljust(12), 99)
        if index > 4 or index < 0:
            printErr(0, "Resolution Err")
            continue
        if index == 0:
            resolution = '1080'
        if index == 1:
            resolution = '720'
        if index == 2:
            resolution = '480'
        if index == 3:
            resolution = '360'
        if index == 4:
            resolution = '240'
        break
    while True:
        threadnum = myinput("ThreadNum:".ljust(12))
        if cf.valid_threadnum(threadnum) == False:
            printErr(0, "ThreadNum Err")
            continue
        break
    status = myinputInt("ConvertMp4toM4a(0-False,1-True):".ljust(12), 0)
    status2 = myinputInt("ShowProgress(0-False,1-True):".ljust(12), 0)
    status3 = myinputInt("AddHyphen(0-False,1-True):".ljust(12), 0)

    cf.set_outputdir(outputdir)
    cf.set_quality(quality)
    cf.set_resolution(resolution)
    cf.set_threadnum(threadnum)
    cf.set_onlym4a(status)
    cf.set_showprogress(status2)
    cf.set_addhyphen(status3)

    pathHelper.mkdirs(outputdir + "/Album/")
    pathHelper.mkdirs(outputdir + "/Playlist/")
    pathHelper.mkdirs(outputdir + "/Video/")
    pathHelper.mkdirs(outputdir + "/Favorite/")
    return
Exemplo n.º 23
0
    def downloadAlbum(self, album_id=None, redl_flag=None):
        while_count = 9999
        while while_count > 0:
            while_count -= 1

            if album_id is not None:
                while_count = 0
                sID = album_id
            else:
                print("----------------ALBUM------------------")
                sID = printChoice("Enter AlbumID(Enter '0' go back):", True, 0)
                if sID == 0:
                    return

            aAlbumInfo = self.tool.getAlbum(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get AlbumInfo Err! " + self.tool.errmsg)
                continue

            print("[Title]       %s" % (aAlbumInfo['title']))
            print("[SongNum]     %s\n" % (aAlbumInfo['numberOfTracks']))

            # Get Tracks
            aAlbumTracks = self.tool.getAlbumTracks(sID)
            if self.tool.errmsg != "":
                printErr(0, "Get AlbumTracks Err!" + self.tool.errmsg)
                continue
            aAlbumVideos = self.tool.getAlbumVideos(sID)

            # Creat OutputDir
            targetDir = self.__creatAlbumDir(aAlbumInfo)
            # write msg
            string = self.tool.convertAlbumInfoToString(
                aAlbumInfo, aAlbumTracks)
            with codecs.open(targetDir + "/AlbumInfo.txt", 'w', 'utf-8') as fd:
                fd.write(string)
            # download cover
            coverPath = targetDir + '/' + pathHelper.replaceLimitChar(
                aAlbumInfo['title'], '-') + '.jpg'
            if aAlbumInfo['cover'] is not None:
                coverUrl = self.tool.getAlbumArtworkUrl(aAlbumInfo['cover'])
                netHelper.downloadFile(coverUrl, coverPath)
            # check exist files
            redownload = True
            if redl_flag is None:
                existFiles = pathHelper.getDirFiles(targetDir)
                for item in existFiles:
                    if '.txt' in item:
                        continue
                    if '.jpg' in item:
                        continue
                    check = printChoice(
                        "Some tracks already exist. Redownload?(y/n):")
                    if not cmdHelper.isInputYes(check):
                        redownload = False
                    break
            else:
                redownload = redl_flag

            # download album tracks
            for item in aAlbumTracks['items']:
                streamInfo = self.tool.getStreamUrl(str(item['id']),
                                                    self.config.quality)
                if self.tool.errmsg != "" or not streamInfo:
                    printErr(
                        14, item['title'] + "(Get Stream Url Err!" +
                        self.tool.errmsg + ")")
                    continue

                fileType = self._getSongExtension(streamInfo['url'])
                filePath = self.__getAlbumSongSavePath(targetDir, aAlbumInfo,
                                                       item, fileType)
                paraList = {
                    'album': aAlbumInfo,
                    'redownload': redownload,
                    'title': item['title'],
                    'trackinfo': item,
                    'url': streamInfo['url'],
                    'path': filePath,
                    'retry': 3,
                    'key': streamInfo['encryptionKey'],
                    'coverpath': coverPath
                }
                self.thread.start(self.__thradfunc_dl, paraList)
            # wait all download thread
            self.thread.waitAll()
            self.tool.removeTmpFile(targetDir)

            # remove cover
            if self.config.savephoto != 'True':
                pathHelper.remove(coverPath)

            # download video

            for item in aAlbumVideos:
                item = item['item']
                filePath = targetDir + '/' + pathHelper.replaceLimitChar(
                    item['title'], '-') + ".mp4"
                filePath = os.path.abspath(filePath)
                if os.access(filePath, 0):
                    os.remove(filePath)

                try:
                    resolutionList, urlList = self.tool.getVideoResolutionList(
                        item['id'])
                    selectIndex = self.__getVideoResolutionIndex(
                        resolutionList)
                    if self.ffmpeg.mergerByM3u8_Multithreading2(
                            urlList[int(selectIndex)],
                            filePath,
                            showprogress=self.showpro):
                        printSUCCESS(14, item['title'])
                    else:
                        printErr(14, item['title'])
                except:
                    printErr(14, item['title'])
            # return

        return