From a7cacbca2b140f668785d57264914de5585ed699 Mon Sep 17 00:00:00 2001 From: mcd1992 Date: Fri, 22 Aug 2014 16:40:43 -0500 Subject: [PATCH 1/3] Implemented --exec option. --- README.md | 2 + youtube_dl/.__init__.py.swp | Bin 0 -> 16384 bytes youtube_dl/__init__.py | 15 +++++++- youtube_dl/postprocessor/__init__.py | 2 + youtube_dl/postprocessor/execafterdownload.py | 36 ++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 youtube_dl/.__init__.py.swp create mode 100644 youtube_dl/postprocessor/execafterdownload.py diff --git a/README.md b/README.md index ba9fec8a7..30bdac189 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,8 @@ ## Post-processing Options: postprocessors (default) --prefer-ffmpeg Prefer ffmpeg over avconv for running the postprocessors + --exec Execute a command after the file is finished downloading, similar to find's -exec format + Example: --exec 'adb push {} /sdcard/Music/ && rm {}' # CONFIGURATION diff --git a/youtube_dl/.__init__.py.swp b/youtube_dl/.__init__.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..0586277fd44037e92b86628697b8bfb898bfe32a GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index a96bf9b5c..189a8ff35 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -71,8 +71,12 @@ 'Sebastian Haas', 'Alexander Kirk', 'Erik Johnson', +<<<<<<< HEAD 'Keith Beckman', 'Ole Ernst', +======= + 'Aaron McDaniel (mcd1992)', +>>>>>>> Implemented --exec option. ) __license__ = 'Public Domain' @@ -119,6 +123,7 @@ FFmpegExtractAudioPP, FFmpegEmbedSubtitlePP, XAttrMetadataPP, + ExecAfterDownload, ) @@ -550,7 +555,8 @@ def _hide_login_info(opts): help='Prefer avconv over ffmpeg for running the postprocessors (default)') postproc.add_option('--prefer-ffmpeg', action='store_true', dest='prefer_ffmpeg', help='Prefer ffmpeg over avconv for running the postprocessors') - + postproc.add_option('--exec', metavar='', action='store', dest='execstring', + help='Execute a command on the file after downloading, similar to find\'s -exec syntax. Must be enclosed in quotes. Example: --exec \'adb push {} /sdcard/Music/ && rm {}\'' ) parser.add_option_group(general) parser.add_option_group(selection) @@ -831,6 +837,7 @@ def _real_main(argv=None): 'default_search': opts.default_search, 'youtube_include_dash_manifest': opts.youtube_include_dash_manifest, 'encoding': opts.encoding, + 'execstring': opts.execstring, } with YoutubeDL(ydl_opts) as ydl: @@ -854,6 +861,12 @@ def _real_main(argv=None): ydl.add_post_processor(FFmpegAudioFixPP()) ydl.add_post_processor(AtomicParsleyPP()) + + # Please keep ExecAfterDownload towards the bottom as it allows the user to modify the final file in any way. + # So if the user is able to remove the file before your postprocessor runs it might cause a few problems. + if opts.execstring: + ydl.add_post_processor(ExecAfterDownload(commandString=opts.execstring)) + # Update version if opts.update_self: update_self(ydl.to_screen, opts.verbose) diff --git a/youtube_dl/postprocessor/__init__.py b/youtube_dl/postprocessor/__init__.py index 08e6ddd00..59ab49e6d 100644 --- a/youtube_dl/postprocessor/__init__.py +++ b/youtube_dl/postprocessor/__init__.py @@ -9,6 +9,7 @@ FFmpegEmbedSubtitlePP, ) from .xattrpp import XAttrMetadataPP +from .execafterdownload import ExecAfterDownload __all__ = [ 'AtomicParsleyPP', @@ -19,4 +20,5 @@ 'FFmpegExtractAudioPP', 'FFmpegEmbedSubtitlePP', 'XAttrMetadataPP', + 'ExecAfterDownload', ] diff --git a/youtube_dl/postprocessor/execafterdownload.py b/youtube_dl/postprocessor/execafterdownload.py new file mode 100644 index 000000000..431ab7f08 --- /dev/null +++ b/youtube_dl/postprocessor/execafterdownload.py @@ -0,0 +1,36 @@ +# ExecAfterDownload written by AaronM / mcd1992. +# If there are any issues with this postprocessor please contact me via github or admin@fgthou.se + +import os, re, shlex +from ..utils import PostProcessingError + +class ExecAfterDownload( object ): + _downloader = None + + def __init__( self, downloader = None, commandString = None ): + self._downloader = downloader + self.commandString = commandString + + def set_downloader( self, downloader ): + """Sets the downloader for this PP.""" + self._downloader = downloader + + def run( self, information ): + self.targetFile = information["filepath"] + self.finalCommand = None; + + if( re.search( '{}', self.commandString ) ): # Find and replace all occurrences of {} with the file name. + self.finalCommand = re.sub( "{}", '\'' + self.targetFile + '\'', self.commandString ) + else: + self.finalCommand = self.commandString + ' \'' + self.targetFile + '\'' + + if( self.finalCommand ): + print( "[exec] Executing command: " + self.finalCommand ) + os.system( self.finalCommand ) + else: + raise PostProcessingExecError( "Invalid syntax for --exec post processor" ) + + return None, information # by default, keep file and do nothing + +class PostProcessingExecError( PostProcessingError ): + pass From a2360a4c80700824f4160505fcdb1ca14261c031 Mon Sep 17 00:00:00 2001 From: mcd1992 Date: Sat, 23 Aug 2014 14:30:13 -0500 Subject: [PATCH 2/3] Moved from os.system to subprocess.call --- .gitignore | 1 + youtube_dl/.__init__.py.swp | Bin 16384 -> 0 bytes youtube_dl/__init__.py | 4 +- youtube_dl/postprocessor/__init__.py | 4 +- youtube_dl/postprocessor/execafterdownload.py | 51 +++++++++--------- 5 files changed, 32 insertions(+), 28 deletions(-) delete mode 100644 youtube_dl/.__init__.py.swp diff --git a/.gitignore b/.gitignore index 37b2fa8d3..b8128fab1 100644 --- a/.gitignore +++ b/.gitignore @@ -26,5 +26,6 @@ updates_key.pem *.m4a *.m4v *.part +*.swp test/testdata .tox diff --git a/youtube_dl/.__init__.py.swp b/youtube_dl/.__init__.py.swp deleted file mode 100644 index 0586277fd44037e92b86628697b8bfb898bfe32a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 189a8ff35..4eae88d6c 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -123,7 +123,7 @@ FFmpegExtractAudioPP, FFmpegEmbedSubtitlePP, XAttrMetadataPP, - ExecAfterDownload, + ExecAfterDownloadPP, ) @@ -865,7 +865,7 @@ def _real_main(argv=None): # Please keep ExecAfterDownload towards the bottom as it allows the user to modify the final file in any way. # So if the user is able to remove the file before your postprocessor runs it might cause a few problems. if opts.execstring: - ydl.add_post_processor(ExecAfterDownload(commandString=opts.execstring)) + ydl.add_post_processor(ExecAfterDownloadPP(verboseOutput=opts.verbose,commandString=opts.execstring)) # Update version if opts.update_self: diff --git a/youtube_dl/postprocessor/__init__.py b/youtube_dl/postprocessor/__init__.py index 59ab49e6d..15aa0daa9 100644 --- a/youtube_dl/postprocessor/__init__.py +++ b/youtube_dl/postprocessor/__init__.py @@ -9,7 +9,7 @@ FFmpegEmbedSubtitlePP, ) from .xattrpp import XAttrMetadataPP -from .execafterdownload import ExecAfterDownload +from .execafterdownload import ExecAfterDownloadPP __all__ = [ 'AtomicParsleyPP', @@ -20,5 +20,5 @@ 'FFmpegExtractAudioPP', 'FFmpegEmbedSubtitlePP', 'XAttrMetadataPP', - 'ExecAfterDownload', + 'ExecAfterDownloadPP', ] diff --git a/youtube_dl/postprocessor/execafterdownload.py b/youtube_dl/postprocessor/execafterdownload.py index 431ab7f08..e6f3cdfd2 100644 --- a/youtube_dl/postprocessor/execafterdownload.py +++ b/youtube_dl/postprocessor/execafterdownload.py @@ -1,36 +1,39 @@ -# ExecAfterDownload written by AaronM / mcd1992. -# If there are any issues with this postprocessor please contact me via github or admin@fgthou.se - -import os, re, shlex +from __future__ import unicode_literals +from .common import PostProcessor from ..utils import PostProcessingError +import subprocess +import shlex -class ExecAfterDownload( object ): - _downloader = None - def __init__( self, downloader = None, commandString = None ): - self._downloader = downloader +class ExecAfterDownloadPP(PostProcessor): + def __init__(self, downloader=None, verboseOutput=None, commandString=None): + self.verboseOutput = verboseOutput self.commandString = commandString - def set_downloader( self, downloader ): - """Sets the downloader for this PP.""" - self._downloader = downloader + def run(self, information): + self.targetFile = information['filepath'].replace('\'', '\'\\\'\'') # Replace single quotes with '\'' + self.commandList = shlex.split(self.commandString) + self.commandString = '' - def run( self, information ): - self.targetFile = information["filepath"] - self.finalCommand = None; + # Replace all instances of '{}' with the file name and convert argument list to single string. + for index, arg in enumerate(self.commandList): + if(arg == '{}'): + self.commandString += '\'' + self.targetFile + '\' ' + else: + self.commandString += arg + ' ' - if( re.search( '{}', self.commandString ) ): # Find and replace all occurrences of {} with the file name. - self.finalCommand = re.sub( "{}", '\'' + self.targetFile + '\'', self.commandString ) - else: - self.finalCommand = self.commandString + ' \'' + self.targetFile + '\'' + if self.targetFile not in self.commandString: # Assume user wants the file appended to the end of the command if no {}'s were given. + self.commandString += '\'' + self.targetFile + '\'' - if( self.finalCommand ): - print( "[exec] Executing command: " + self.finalCommand ) - os.system( self.finalCommand ) - else: - raise PostProcessingExecError( "Invalid syntax for --exec post processor" ) + print("[exec] Executing command: " + self.commandString) + self.retCode = subprocess.call(self.commandString, shell=True) + if(self.retCode < 0): + print("[exec] WARNING: Command exited with a negative return code, the process was killed externally. Your command may not of completed succesfully!") + elif(self.verboseOutput): + print("[exec] Command exited with return code: " + str(self.retCode)) return None, information # by default, keep file and do nothing -class PostProcessingExecError( PostProcessingError ): + +class PostProcessingExecError(PostProcessingError): pass From 7833d941bb736a8dbd237f1c7bc268d671cabb68 Mon Sep 17 00:00:00 2001 From: mcd1992 Date: Sun, 24 Aug 2014 15:04:50 -0500 Subject: [PATCH 3/3] Rebased with upstream/master --- README.md | 2 -- youtube_dl/__init__.py | 3 --- 2 files changed, 5 deletions(-) diff --git a/README.md b/README.md index 30bdac189..ba9fec8a7 100644 --- a/README.md +++ b/README.md @@ -288,8 +288,6 @@ ## Post-processing Options: postprocessors (default) --prefer-ffmpeg Prefer ffmpeg over avconv for running the postprocessors - --exec Execute a command after the file is finished downloading, similar to find's -exec format - Example: --exec 'adb push {} /sdcard/Music/ && rm {}' # CONFIGURATION diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 4eae88d6c..7cf5de43f 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -71,12 +71,9 @@ 'Sebastian Haas', 'Alexander Kirk', 'Erik Johnson', -<<<<<<< HEAD 'Keith Beckman', 'Ole Ernst', -======= 'Aaron McDaniel (mcd1992)', ->>>>>>> Implemented --exec option. ) __license__ = 'Public Domain'