diff options
author | Walter Purcaro <vuolter@gmail.com> | 2014-09-25 20:59:30 +0200 |
---|---|---|
committer | Walter Purcaro <vuolter@gmail.com> | 2014-09-25 20:59:30 +0200 |
commit | 31ea85f97571cc191fe205f6b4d85b3777818240 (patch) | |
tree | 13182fa43a82a32e833acf231a340b06a3571cd7 /module | |
parent | [ZippyshareCom] Improve __pattern__ a bit (diff) | |
download | pyload-31ea85f97571cc191fe205f6b4d85b3777818240.tar.xz |
Extend ExtractArchive events + code optimizations
https://github.com/pyload/pyload/pull/622
https://github.com/pyload/pyload/pull/726
Diffstat (limited to 'module')
-rw-r--r-- | module/plugins/hooks/ExternalScripts.py | 69 | ||||
-rw-r--r-- | module/plugins/hooks/ExtractArchive.py | 124 | ||||
-rw-r--r-- | module/plugins/internal/UnRar.py | 31 |
3 files changed, 148 insertions, 76 deletions
diff --git a/module/plugins/hooks/ExternalScripts.py b/module/plugins/hooks/ExternalScripts.py index 8d03d27d4..bdde9cd62 100644 --- a/module/plugins/hooks/ExternalScripts.py +++ b/module/plugins/hooks/ExternalScripts.py @@ -2,6 +2,7 @@ import subprocess +from itertools import chain from os import listdir, access, X_OK, makedirs from os.path import join, exists, basename, abspath @@ -12,23 +13,27 @@ from module.utils import save_join class ExternalScripts(Hook): __name__ = "ExternalScripts" __type__ = "hook" - __version__ = "0.23" + __version__ = "0.24" __config__ = [("activated", "bool", "Activated", True)] __description__ = """Run external scripts""" - __author_name__ = ("mkaay", "RaNaN", "spoob") - __author_mail__ = ("mkaay@mkaay.de", "ranan@pyload.org", "spoob@pyload.org") + __author_name__ = ("mkaay", "RaNaN", "spoob", "Walter Purcaro") + __author_mail__ = ("mkaay@mkaay.de", "ranan@pyload.org", "spoob@pyload.org", "vuolter@gmail.com") - event_list = ["unrarFinished", "allDownloadsFinished", "allDownloadsProcessed"] + event_list = ["archive_extracted", "package_extracted", "all_archives_extracted", "all_archives_processed", + "allDownloadsFinished", "allDownloadsProcessed"] def setup(self): self.scripts = {} - folders = ["download_preparing", "download_finished", "package_finished", - "before_reconnect", "after_reconnect", "unrar_finished", - "all_dls_finished", "all_dls_processed"] + folders = ["download_preparing", "download_finished", "all_downloads_finished", "all_downloads_processed", + "before_reconnect", "after_reconnect", + "package_finished", "package_extracted", + "archive_extracted", "all_archives_extracted", "all_archives_processed", + # deprecated folders + "unrar_finished", "all_dls_finished", "all_dls_processed"] for folder in folders: self.scripts[folder] = [] @@ -40,6 +45,7 @@ class ExternalScripts(Hook): if names: self.logInfo((_("Installed scripts for %s: ") % script_type) + ", ".join([basename(x) for x in names])) + def initPluginType(self, folder, path): if not exists(path): try: @@ -57,6 +63,7 @@ class ExternalScripts(Hook): self.scripts[folder].append(join(path, f)) + def callScript(self, script, *args): try: cmd = [script] + [str(x) if not isinstance(x, basestring) else x for x in args] @@ -66,39 +73,65 @@ class ExternalScripts(Hook): except Exception, e: self.logError(_("Error in %(script)s: %(error)s") % {"script": basename(script), "error": str(e)}) + def downloadPreparing(self, pyfile): for script in self.scripts['download_preparing']: self.callScript(script, pyfile.pluginname, pyfile.url, pyfile.id) + def downloadFinished(self, pyfile): + download_folder = self.config['general']['download_folder'] for script in self.scripts['download_finished']: - self.callScript(script, pyfile.pluginname, pyfile.url, pyfile.name, - save_join(self.config['general']['download_folder'], - pyfile.package().folder, pyfile.name), pyfile.id) + filename = save_join(download_folder, pyfile.package().folder, pyfile.name) + self.callScript(script, pyfile.pluginname, pyfile.url, pyfile.name, filename, pyfile.id) + def packageFinished(self, pypack): + download_folder = self.config['general']['download_folder'] for script in self.scripts['package_finished']: - folder = self.config['general']['download_folder'] - folder = save_join(folder, pypack.folder) - + folder = save_join(download_folder, pypack.folder) self.callScript(script, pypack.name, folder, pypack.password, pypack.id) + def beforeReconnecting(self, ip): for script in self.scripts['before_reconnect']: self.callScript(script, ip) + def afterReconnecting(self, ip): for script in self.scripts['after_reconnect']: self.callScript(script, ip) - def unrarFinished(self, folder, fname): - for script in self.scripts['unrar_finished']: - self.callScript(script, folder, fname) + + def archive_extracted(self, pyfile, folder, filename, files): + for script in self.scripts['archive_extracted']: + self.callScript(script, folder, filename, files) + for script in self.scripts['unrar_finished']: #: deprecated + self.callScript(script, folder, filename) + + + def package_extracted(self, pypack): + download_folder = self.config['general']['download_folder'] + for script in self.scripts['package_extracted']: + folder = save_join(download_folder, pypack.folder) + self.callScript(script, pypack.name, folder, pypack.password, pypack.id) + + + def all_archives_extracted(self): + for script in self.scripts['all_archives_extracted']: + self.callScript(script) + + + def all_archives_processed(self): + for script in self.scripts['all_archives_processed']: + self.callScript(script) + def allDownloadsFinished(self): - for script in self.scripts['all_dls_finished']: + for script in chain(self.scripts['all_downloads_finished'], self.scripts['all_dls_finished']): self.callScript(script) + def allDownloadsProcessed(self): - for script in self.scripts['all_dls_processed']: + for script in chain(self.scripts['all_downloads_processed'], self.scripts['all_dls_processed']): self.callScript(script) diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py index 144829459..84f6eab25 100644 --- a/module/plugins/hooks/ExtractArchive.py +++ b/module/plugins/hooks/ExtractArchive.py @@ -53,17 +53,14 @@ from module.utils import save_join, fs_encode class ExtractArchive(Hook): - """ - Provides: unrarFinished (folder, filename) - """ __name__ = "ExtractArchive" __type__ = "hook" - __version__ = "0.16" + __version__ = "0.17" __config__ = [("activated", "bool", "Activated", True), ("fullpath", "bool", "Extract full path", True), ("overwrite", "bool", "Overwrite files", True), - ("passwordfile", "file", "password file", "unrar_passwords.txt"), + ("passwordfile", "file", "password file", "archive_password.txt"), ("deletearchive", "bool", "Delete archives when done", False), ("subfolder", "bool", "Create subfolder for each package", False), ("destination", "folder", "Extract files to", ""), @@ -73,8 +70,8 @@ class ExtractArchive(Hook): ("renice", "int", "CPU Priority", 0)] __description__ = """Extract different kind of archives""" - __author_name__ = ("pyLoad Team", "AndroKev") - __author_mail__ = ("admin@pyload.org", "@pyloadforum") + __author_name__ = ("RaNaN", "AndroKev", "Walter Purcaro") + __author_mail__ = ("ranan@pyload.org", "@pyloadforum", "vuolter@gmail.com") event_list = ["allDownloadsProcessed"] @@ -113,33 +110,50 @@ class ExtractArchive(Hook): # queue with package ids self.queue = [] + @Expose def extractPackage(self, id): """ Extract package with given id""" self.manager.startThread(self.extract, [id]) + def packageFinished(self, pypack): + pid = pypack.id if self.getConfig("queue"): self.logInfo(_("Package %s queued for later extracting") % pypack.name) - self.queue.append(pypack.id) + self.queue.append(pid) else: - self.manager.startThread(self.extract, [pypack.id]) + self.manager.startThread(self.extract, [pid]) + @threaded def allDownloadsProcessed(self, thread): local = copy(self.queue) del self.queue[:] - self.extract(local, thread) + if self.extract(local, thread): #: check only if all gone fine, no failed reporting for now + self.manager.dispatchEvent("all_archives_extracted") + self.manager.dispatchEvent("all_archives_processed") + def extract(self, ids, thread=None): + processed = [] + extracted = [] + failed = [] + + destination = self.getConfig("destination") + subfolder = self.getConfig("subfolder") + fullpath = self.getConfig("fullpath") + overwrite = self.getConfig("overwrite") + excludefiles = self.getConfig("excludefiles") + renice = self.getConfig("renice") + recursive = self.getConfig("recursive") + # reload from txt file self.reloadPasswords() # dl folder dl = self.config['general']['download_folder'] - extracted = [] - #iterate packages -> plugins -> targets for pid in ids: p = self.core.files.getPackage(pid) @@ -148,22 +162,17 @@ class ExtractArchive(Hook): continue # determine output folder - out = save_join(dl, p.folder, "") - # force trailing slash - - if self.getConfig("destination") and self.getConfig("destination").lower() != "none": - - out = save_join(dl, p.folder, self.getConfig("destination"), "") - #relative to package folder if destination is relative, otherwise absolute path overwrites them + out = save_join(dl, p.folder, destination, "") #: force trailing slash - if self.getConfig("subfolder"): - out = save_join(out, fs_encode(p.folder)) + if subfolder: + out = save_join(out, fs_encode(p.folder)) - if not exists(out): - makedirs(out) + if not exists(out): + makedirs(out) files_ids = [(save_join(dl, p.folder, x['name']), x['id']) for x in p.getChildren().itervalues()] matched = False + success = True # check as long there are unseen files while files_ids: @@ -175,17 +184,23 @@ class ExtractArchive(Hook): self.logDebug("Targets for %s: %s" % (plugin.__name__, targets)) matched = True for target, fid in targets: - if target in extracted: + if target in processed: self.logDebug(basename(target), "skipped") continue - extracted.append(target) # prevent extracting same file twice - klass = plugin(self, target, out, self.getConfig("fullpath"), self.getConfig("overwrite"), self.getConfig("excludefiles"), - self.getConfig("renice")) - klass.init() + processed.append(target) # prevent extracting same file twice self.logInfo(basename(target), _("Extract to %s") % out) - new_files = self.startExtracting(klass, fid, p.password.strip().splitlines(), thread) + try: + klass = plugin(self, target, out, fullpath, overwrite, excludefiles, renice) + klass.init() + password = p.password.strip().splitlines() + new_files = self._extract(klass, fid, password, thread) + except Exception, e: + self.logError(basename(target), str(e)) + success = False + continue + self.logDebug("Extracted: %s" % new_files) self.setPermissions(new_files) @@ -193,18 +208,27 @@ class ExtractArchive(Hook): if not exists(file): self.logDebug("new file %s does not exists" % file) continue - if self.getConfig("recursive") and isfile(file): + if recursive and isfile(file): new_files_ids.append((file, fid)) # append as new target files_ids = new_files_ids # also check extracted files - if not matched: + if matched: + if success: + extracted.append(pid) + self.manager.dispatchEvent("package_extracted", p) + else: + failed.append(pid) + self.manager.dispatchEvent("package_extract_failed", p) + else: self.logInfo(_("No files found to extract")) - def startExtracting(self, plugin, fid, passwords, thread): + return True if not failed else False + + + def _extract(self, plugin, fid, passwords, thread): pyfile = self.core.files.getFile(fid) - if not pyfile: - return [] + deletearchive = self.getConfig("deletearchive") pyfile.setCustomStatus(_("extracting")) thread.addActive(pyfile) # keep this file until everything is done @@ -221,7 +245,7 @@ class ExtractArchive(Hook): self.logDebug("Passwords: %s" % str(passwords)) pwlist = copy(self.getPasswords()) - #remove already supplied pws from list (only local) + # remove already supplied pws from list (only local) for pw in passwords: if pw in pwlist: pwlist.remove(pw) @@ -238,13 +262,12 @@ class ExtractArchive(Hook): self.logDebug("Password was wrong") if not success: - self.logError(basename(plugin.file), _("Wrong password")) - return [] + raise Exception(_("Wrong password")) if self.core.debug: self.logDebug("Would delete: %s" % ", ".join(plugin.getDeleteFiles())) - if self.getConfig("deletearchive"): + if deletearchive: files = plugin.getDeleteFiles() self.logInfo(_("Deleting %s files") % len(files)) for f in files: @@ -254,9 +277,11 @@ class ExtractArchive(Hook): self.logDebug("%s does not exists" % f) self.logInfo(basename(plugin.file), _("Extracting finished")) - self.manager.dispatchEvent("unrarFinished", plugin.out, plugin.file) - return plugin.getExtractedFiles() + extracted_files = plugin.getExtractedFiles() + self.manager.dispatchEvent("archive_extracted", pyfile, plugin.out, plugin.file, extracted_files) + + return extracted_files except ArchiveError, e: self.logError(basename(plugin.file), _("Archive Error"), str(e)) @@ -267,40 +292,45 @@ class ExtractArchive(Hook): print_exc() self.logError(basename(plugin.file), _("Unknown Error"), str(e)) - return [] + self.manager.dispatchEvent("archive_extract_failed", pyfile) + raise Exception(_("Extract failed")) + @Expose def getPasswords(self): """ List of saved passwords """ return self.passwords + def reloadPasswords(self): - pwfile = self.getConfig("passwordfile") - if not exists(pwfile): - open(pwfile, "wb").close() + passwordfile = self.getConfig("passwordfile") + if not exists(passwordfile): + open(passwordfile, "wb").close() passwords = [] - f = open(pwfile, "rb") + f = open(passwordfile, "rb") for pw in f.read().splitlines(): passwords.append(pw) f.close() self.passwords = passwords + @Expose def addPassword(self, pw): """ Adds a password to saved list""" - pwfile = self.getConfig("passwordfile") + passwordfile = self.getConfig("passwordfile") if pw in self.passwords: self.passwords.remove(pw) self.passwords.insert(0, pw) - f = open(pwfile, "wb") + f = open(passwordfile, "wb") for pw in self.passwords: f.write(pw + "\n") f.close() + def setPermissions(self, files): for f in files: if not exists(f): diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index 19c278735..91be69433 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -4,7 +4,7 @@ import os import re from glob import glob -from os.path import join +from os import basename, join from string import digits from subprocess import Popen, PIPE @@ -12,14 +12,23 @@ from module.plugins.internal.AbstractExtractor import AbtractExtractor, WrongPas from module.utils import save_join, decode +def renice(pid, value): + if os.name != "nt" and value: + try: + Popen(["renice", str(value), str(pid)], stdout=PIPE, stderr=PIPE, bufsize=-1) + except: + print "Renice failed" + + class UnRar(AbtractExtractor): __name__ = "UnRar" - __version__ = "0.16" + __version__ = "0.17" __description__ = """Rar extractor plugin""" __author_name__ = "RaNaN" __author_mail__ = "RaNaN@pyload.org" + CMD = "unrar" # there are some more uncovered rar formats @@ -50,6 +59,7 @@ class UnRar(AbtractExtractor): return True + @staticmethod def getTargets(files_ids): result = [] @@ -68,12 +78,14 @@ class UnRar(AbtractExtractor): return result + def init(self): self.passwordProtected = False self.headerProtected = False #: list files will not work without password self.smallestFile = None #: small file to test passwords self.password = "" #: save the correct password + def checkArchive(self): p = self.call_unrar("l", "-v", self.file) out, err = p.communicate() @@ -100,6 +112,7 @@ class UnRar(AbtractExtractor): return False + def checkPassword(self, password): # at this point we can only verify header protected files if self.headerProtected: @@ -110,6 +123,7 @@ class UnRar(AbtractExtractor): return True + def extract(self, progress, password=None): command = "x" if self.fullpath else "e" @@ -151,13 +165,15 @@ class UnRar(AbtractExtractor): self.password = password self.listContent() + def getDeleteFiles(self): - if ".part" in self.file: + if ".part" in basename(self.file): return glob(re.sub("(?<=\.part)([01]+)", "*", self.file, re.IGNORECASE)) # get files which matches .r* and filter unsuited files out parts = glob(re.sub(r"(?<=\.r)ar$", "*", self.file, re.IGNORECASE)) return filter(lambda x: self.re_partfiles.match(x), parts) + def listContent(self): command = "vb" if self.fullpath else "lb" p = self.call_unrar(command, "-v", self.file, password=self.password) @@ -177,6 +193,7 @@ class UnRar(AbtractExtractor): self.files = result + def call_unrar(self, command, *xargs, **kwargs): args = [] # overwrite flag @@ -202,11 +219,3 @@ class UnRar(AbtractExtractor): p = Popen(call, stdout=PIPE, stderr=PIPE) return p - - -def renice(pid, value): - if os.name != "nt" and value: - try: - Popen(["renice", str(value), str(pid)], stdout=PIPE, stderr=PIPE, bufsize=-1) - except: - print "Renice failed" |