Ejemplo n.º 1
0
 def __init__(self):
     self.check = False
     self.url = None
     self.attempStartTimeStr = Easy.NowLocalStr()
     self.workDir = None
     self.dlFname = None
     self.fname = None
     self.txtFile = None
     self.resultEx = None  ## result obj from extracted info stage
     self.resultDl = None  ## result obj from dl stage
     self.resultEntries = []
Ejemplo n.º 2
0
def _ytDownload(url,
                location=None,
                checkFunc=None,
                resultsList=None,
                maxEntries=-1):
    """
    this is the lower level downloading func
    it shouldn't be used directly
    """
    dirAtFunStart = Easy.Cwd
    if location is None:
        location = Easy.Cwd
    nowStr = Easy.NowLocalStr()
    workDir = Easy.TmpDir(dir=location, prefix='01--working--' + nowStr)
    Easy.Cd(workDir)

    urlsExtarctedToDownload = []
    if resultsList is None:
        resultsList = []

    ret = YtResult()
    ret.attempStartTimeStr = nowStr
    ret.url = url
    ret.workDir = workDir

    try:

        ## Check for early skip
        if True:  ##'v=' in url:
            ## easiest checks are for id as parts after 'v='
            ## or just as part after last slash
            uEnd = url.split('/')[-1]
            uEnd = uEnd.split('?v=')[-1]
            uEnd = uEnd.split('&v=')[-1]
            ## if we've chopped off the end via slash or v=
            ## then if it's a simple video, it shouldn't have '?'
            ## in it
            if checkFunc is not None and not '?' in uEnd:
                if not checkFunc(uEnd):
                    #print( f'early skip: {url}' )
                    raise CheckerError('Early skip! check failed on id: ' +
                                       str(uEnd))
        tmpUrl = url
        if '&' in url:
            urlSplit = url.split('&')
            loopI = len(urlSplit) - 1
            while loopI >= 0:
                listPart = urlSplit[loopI]
                if loopI > 0 and urlSplit[loopI].startswith('list='):
                    del urlSplit[loopI]
                loopI -= 1
            tmpUrl = '&'.join(urlSplit)
        print(tmpUrl)

        ydl_opts = {
            #'merge_output_format':'mkv',
            #'extract_flat':True,
            'extractaudio': True,
            'noplaylist': True,
            #'audio_only':True,
            'restrict_filenames': True,
            #'no_overwrites':True,
            #'no_post_overwrites':True,
            'keepvideo': False,
            #'extract-audio' : True,
            'quiet': False,
            #'noplaylist':True,
            #'get_filename':True,
            #'progress_hooks': [my_hook],
            #def my_hook(d):
        }
        ydl = youtube_dl.YoutubeDL(ydl_opts)
        #pdb.set_trace()
        result = ydl.extract_info(
            tmpUrl, download=False)  ## tmpUrl to ensure not a list!
        #pdb.set_trace()
        ret.resultEx = result
        if 'entries' in result:
            raise "handling of playlists/channels is disabled currently"
            ## old playlist handling code was here, moved to end of this file for reference
        else:
            fname = ydl.prepare_filename(result)
            title = result['title']
            id = result['id']
            acodec = result['acodec']
            ext = result['acodec']
            if checkFunc is not None:
                if not checkFunc(id):
                    raise CheckerError('Check failed on id: ' + str(id))
            else:
                ret.check = True
            ## This is a hack to prevent youtube_dl from running sys.exit
            oldSysExit = sys.exit

            def fakeExit(arg):
                raise FakeExitError

            sys.exit = fakeExit
            try:
                youtube_dl.main([
                    url,
                    '--extract-audio',
                    '--no-playlis',
                ])
            except KeyboardInterrupt as err:
                oldSysExit(1)
                raise err
            except FakeExitError:
                'pass'
                #print( 'sys.exit was prevented' )
            sys.exit = oldSysExit

            ## if we were able to dl a file
            ## find name, fix name, move files
            files = Easy.Ls(Easy.Cwd)
            if not len(files):
                print(f'Error, unable to download url: {url}')
            else:
                dlFname = files[0]
                ret.dlFname = dlFname
                #print( f'dlFname: {dlFname}' )
                fixedName = Easy.Mods.re.sub(r'[^\x00-\x7f]', r'', dlFname)
                if dlFname != fixedName:
                    os.rename(dlFname, fixedName)  ## make Easy.Rename
                os.rename(fixedName, os.path.join(location, fixedName))
                ret.fname = fixedName
                ret.txtFile = os.path.join(
                    location, fixedName) + '.alreadyDownloaded.txt'
                if not os.path.exists(ret.txtFile):
                    with open(ret.txtFile, 'w') as txtFh:
                        import json
                        metadata = {}
                        metadata['date_of_dl'] = Easy.NowLocalStr()
                        metadata['title'] = title
                        json.dump(metadata, txtFh)
                        #txtFh.write( 'already downloaded' )
    ## This gets triggered if the checkFails,
    ## in which case most of the above code never runs
    ## since it would be after the CheckerError
    except CheckerError as err:
        pass
    ## Really important to handle keyboard errors! For quit with Ctrl-c
    except KeyboardInterrupt as err:
        raise err
    ## On most other errors we just continue after printing a warning
    except:
        Easy.PrintTraceback()
        print('continuing anyway...')
    finally:
        ## really important we go back to original directory!
        Easy.Cd(dirAtFunStart)
        try:
            os.rmdir(workDir)
        except:
            ## something is really wrong in this case, so we don't continue on
            print(f"Couldn't delete tmp dir: {workDir}")

        ## regardless of whether our result has much useful data in it, we add the result
        resultsList.append(ret)
        ## return the same list we were given, but modifed, with YtResult added
        return resultsList