diff options
Diffstat (limited to 'pyload/plugins/addon')
-rw-r--r-- | pyload/plugins/addon/Checksum.py | 32 | ||||
-rw-r--r-- | pyload/plugins/addon/ClickAndLoad.py | 55 | ||||
-rw-r--r-- | pyload/plugins/addon/DeleteFinished.py | 23 | ||||
-rw-r--r-- | pyload/plugins/addon/DownloadScheduler.py | 17 | ||||
-rw-r--r-- | pyload/plugins/addon/ExternalScripts.py | 13 | ||||
-rw-r--r-- | pyload/plugins/addon/ExtractArchive.py | 42 | ||||
-rw-r--r-- | pyload/plugins/addon/HotFolder.py | 60 | ||||
-rw-r--r-- | pyload/plugins/addon/IRCInterface.py | 82 | ||||
-rw-r--r-- | pyload/plugins/addon/MergeFiles.py | 21 | ||||
-rw-r--r-- | pyload/plugins/addon/MultiHome.py | 17 | ||||
-rw-r--r-- | pyload/plugins/addon/RestartFailed.py | 22 | ||||
-rw-r--r-- | pyload/plugins/addon/UnSkipOnFail.py | 9 | ||||
-rw-r--r-- | pyload/plugins/addon/WindowsPhoneToastNotify.py | 15 | ||||
-rw-r--r-- | pyload/plugins/addon/XMPPInterface.py | 32 |
14 files changed, 269 insertions, 171 deletions
diff --git a/pyload/plugins/addon/Checksum.py b/pyload/plugins/addon/Checksum.py index 551ce7bd9..00c3d9cfd 100644 --- a/pyload/plugins/addon/Checksum.py +++ b/pyload/plugins/addon/Checksum.py @@ -18,7 +18,7 @@ def computeChecksum(local_file, algorithm): h = getattr(hashlib, algorithm)() with open(local_file, 'rb') as f: - for chunk in iter(lambda: f.read(128 * h.block_size), b''): + for chunk in iter(lambda: f.read(128 * h.block_size), ''): h.update(chunk) return h.hexdigest() @@ -28,7 +28,7 @@ def computeChecksum(local_file, algorithm): last = 0 with open(local_file, 'rb') as f: - for chunk in iter(lambda: f.read(8192), b''): + for chunk in iter(lambda: f.read(8192), ''): last = hf(chunk, last) return "%x" % last @@ -38,21 +38,21 @@ def computeChecksum(local_file, algorithm): class Checksum(Addon): - __name__ = "Checksum" - __type__ = "addon" - __version__ = "0.13" + __name__ = "Checksum" + __type__ = "addon" + __version__ = "0.14" - __config__ = [("activated", "bool", "Activated", False), - ("check_checksum", "bool", "Check checksum? (If False only size will be verified)", True), + __config__ = [("check_checksum", "bool", "Check checksum? (If False only size will be verified)", True), ("check_action", "fail;retry;nothing", "What to do if check fails?", "retry"), ("max_tries", "int", "Number of retries", 2), ("retry_action", "fail;nothing", "What to do if all retries fail?", "fail"), ("wait_time", "int", "Time to wait before each retry (seconds)", 1)] __description__ = """Verify downloaded file size and checksum""" - __authors__ = [("zoidberg", "zoidberg@mujmail.cz"), - ("Walter Purcaro", "vuolter@gmail.com"), - ("stickell", "l.stickell@yahoo.it")] + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz"), + ("Walter Purcaro", "vuolter@gmail.com"), + ("stickell", "l.stickell@yahoo.it")] methods = {'sfv': 'crc32', 'crc': 'crc32', 'hash': 'md5'} @@ -66,12 +66,14 @@ class Checksum(Addon): if not self.getConfig("check_checksum"): self.logInfo(_("Checksum validation is disabled in plugin configuration")) + def setup(self): self.algorithms = sorted( getattr(hashlib, "algorithms", ("md5", "sha1", "sha224", "sha256", "sha384", "sha512")), reverse=True) self.algorithms.extend(["crc32", "adler32"]) self.formats = self.algorithms + ["sfv", "crc", "hash"] + def downloadFinished(self, pyfile): """ Compute checksum for the downloaded file and compare it with the hash provided by the hoster. @@ -117,7 +119,7 @@ class Checksum(Addon): checksum = computeChecksum(local_file, key.replace("-", "").lower()) if checksum: if checksum == data[key].lower(): - self.logInfo(_('File integrity of "%s" verified by %s checksum (%s).') % + self.logInfo(_('File integrity of "%s" verified by %s checksum (%s)') % (pyfile.name, key.upper(), checksum)) break else: @@ -127,7 +129,8 @@ class Checksum(Addon): else: self.logWarning(_("Unsupported hashing algorithm"), key.upper()) else: - self.logWarning(_("Unable to validate checksum for file"), pyfile.name) + self.logWarning(_("Unable to validate checksum for file: ") + pyfile.name) + def checkFailed(self, pyfile, local_file, msg): check_action = self.getConfig("check_action") @@ -137,13 +140,14 @@ class Checksum(Addon): if pyfile.plugin.retries < max_tries: if local_file: remove(local_file) - pyfile.plugin.retry(max_tries=max_tries, wait_time=self.getConfig("wait_time"), reason=msg) + pyfile.plugin.retry(max_tries, self.getConfig("wait_time"), msg) elif retry_action == "nothing": return elif check_action == "nothing": return pyfile.plugin.fail(reason=msg) + def packageFinished(self, pypack): download_folder = safe_join(self.config['general']['download_folder'], pypack.folder, "") @@ -169,7 +173,7 @@ class Checksum(Addon): algorithm = self.methods.get(file_type, file_type) checksum = computeChecksum(local_file, algorithm) if checksum == data['hash']: - self.logInfo(_('File integrity of "%s" verified by %s checksum (%s).') % + self.logInfo(_('File integrity of "%s" verified by %s checksum (%s)') % (data['name'], algorithm, checksum)) else: self.logWarning(_("%s checksum for file %s does not match (%s != %s)") % diff --git a/pyload/plugins/addon/ClickAndLoad.py b/pyload/plugins/addon/ClickAndLoad.py index 7a90b8f04..c45a1ef2d 100644 --- a/pyload/plugins/addon/ClickAndLoad.py +++ b/pyload/plugins/addon/ClickAndLoad.py @@ -6,33 +6,6 @@ import thread from pyload.plugins.base.Addon import Addon -class ClickAndLoad(Addon): - __name__ = "ClickAndLoad" - __type__ = "addon" - __version__ = "0.22" - - __config__ = [("activated", "bool", "Activated", True), - ("extern", "bool", "Allow external link adding", False)] - - __description__ = """Gives abillity to use jd's click and load. depends on webinterface""" - __authors__ = [("RaNaN", "RaNaN@pyload.de"), - ("mkaay", "mkaay@mkaay.de")] - - - def coreReady(self): - self.port = int(self.config['webinterface']['port']) - if self.config['webinterface']['activated']: - try: - if self.getConfig("extern"): - ip = "0.0.0.0" - else: - ip = "127.0.0.1" - - thread.start_new_thread(proxy, (self, ip, self.port, 9666)) - except: - self.logError(_("ClickAndLoad port already in use")) - - def proxy(self, *settings): thread.start_new_thread(server, (self,) + settings) lock = thread.allocate_lock() @@ -74,3 +47,31 @@ def forward(source, destination): else: #source.shutdown(socket.SHUT_RD) destination.shutdown(socket.SHUT_WR) + + +class ClickAndLoad(Addon): + __name__ = "ClickAndLoad" + __type__ = "addon" + __version__ = "0.22" + + __config__ = [("activated", "bool", "Activated", True), + ("extern", "bool", "Allow external link adding", False)] + + __description__ = """Click'N'Load hook plugin""" + __license__ = "GPLv3" + __authors__ = [("RaNaN", "RaNaN@pyload.de"), + ("mkaay", "mkaay@mkaay.de")] + + + def coreReady(self): + self.port = int(self.config['webinterface']['port']) + if self.config['webinterface']['activated']: + try: + if self.getConfig("extern"): + ip = "0.0.0.0" + else: + ip = "127.0.0.1" + + thread.start_new_thread(proxy, (self, ip, self.port, 9666)) + except: + self.logError(_("ClickAndLoad port already in use")) diff --git a/pyload/plugins/addon/DeleteFinished.py b/pyload/plugins/addon/DeleteFinished.py index 25e49dec5..719de143a 100644 --- a/pyload/plugins/addon/DeleteFinished.py +++ b/pyload/plugins/addon/DeleteFinished.py @@ -5,16 +5,20 @@ from pyload.plugins.base.Addon import Addon class DeleteFinished(Addon): - __name__ = "DeleteFinished" - __type__ = "addon" - __version__ = "1.09" + __name__ = "DeleteFinished" + __type__ = "addon" + __version__ = "1.11" __config__ = [('activated', 'bool', 'Activated', 'False'), ('interval', 'int', 'Delete every (hours)', '72'), ('deloffline', 'bool', 'Delete packages with offline links', 'False')] __description__ = """Automatically delete all finished packages from queue""" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + # event_list = ["pluginConfigChanged"] ## overwritten methods ## @@ -28,30 +32,36 @@ class DeleteFinished(Addon): self.info['sleep'] = True self.addEvent('packageFinished', self.wakeup) + def pluginConfigChanged(self, plugin, name, value): - if name == 'interval' and value != self.interval: + if name == "interval" and value != self.interval: self.interval = value * 3600 self.initPeriodical() + def unload(self): self.removeEvent('packageFinished', self.wakeup) + def coreReady(self): self.info = {'sleep': True} interval = self.getConfig('interval') - self.pluginConfigChanged('DeleteFinished', 'interval', interval) + self.pluginConfigChanged(self.__name__, 'interval', interval) self.addEvent('packageFinished', self.wakeup) + ## own methods ## @style.queue def deleteFinished(self, mode): self.c.execute('DELETE FROM packages WHERE NOT EXISTS(SELECT 1 FROM links WHERE package=packages.id AND status NOT IN (%s))' % mode) self.c.execute('DELETE FROM links WHERE NOT EXISTS(SELECT 1 FROM packages WHERE id=links.package)') + def wakeup(self, pypack): self.removeEvent('packageFinished', self.wakeup) self.info['sleep'] = False + ## event managing ## def addEvent(self, event, func): """Adds an event listener for event name""" @@ -63,6 +73,7 @@ class DeleteFinished(Addon): else: self.m.events[event] = [func] + def setup(self): self.m = self.manager self.removeEvent = self.m.removeEvent diff --git a/pyload/plugins/addon/DownloadScheduler.py b/pyload/plugins/addon/DownloadScheduler.py index 48bbeb3af..ef15a859f 100644 --- a/pyload/plugins/addon/DownloadScheduler.py +++ b/pyload/plugins/addon/DownloadScheduler.py @@ -8,26 +8,28 @@ from pyload.plugins.base.Addon import Addon class DownloadScheduler(Addon): - __name__ = "DownloadScheduler" - __type__ = "addon" + __name__ = "DownloadScheduler" + __type__ = "addon" __version__ = "0.21" - __config__ = [("activated", "bool", "Activated", False), - ("timetable", "str", "List time periods as hh:mm full or number(kB/s)", + __config__ = [("timetable", "str", "List time periods as hh:mm full or number(kB/s)", "0:00 full, 7:00 250, 10:00 0, 17:00 150"), ("abort", "bool", "Abort active downloads when start period with speed 0", False)] __description__ = """Download Scheduler""" - __authors__ = [("zoidberg", "zoidberg@mujmail.cz"), - ("stickell", "l.stickell@yahoo.it")] + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz"), + ("stickell", "l.stickell@yahoo.it")] def setup(self): - self.cb = None # callback to scheduler job; will be by removed AddonManager when addon unloaded + self.cb = None #: callback to scheduler job; will be by removed AddonManager when addon unloaded + def coreReady(self): self.updateSchedule() + def updateSchedule(self, schedule=None): if schedule is None: schedule = self.getConfig("timetable") @@ -55,6 +57,7 @@ class DownloadScheduler(Addon): self.core.scheduler.removeJob(self.cb) self.cb = self.core.scheduler.addJob(next_time, self.updateSchedule, threaded=False) + def setDownloadSpeed(self, speed): if speed == 0: abort = self.getConfig("abort") diff --git a/pyload/plugins/addon/ExternalScripts.py b/pyload/plugins/addon/ExternalScripts.py index 52d14c9d3..122de00c5 100644 --- a/pyload/plugins/addon/ExternalScripts.py +++ b/pyload/plugins/addon/ExternalScripts.py @@ -11,17 +11,18 @@ from pyload.utils import safe_join class ExternalScripts(Addon): - __name__ = "ExternalScripts" - __type__ = "addon" + __name__ = "ExternalScripts" + __type__ = "addon" __version__ = "0.24" __config__ = [("activated", "bool", "Activated", True)] __description__ = """Run external scripts""" - __authors__ = [("mkaay", "mkaay@mkaay.de"), - ("RaNaN", "ranan@pyload.org"), - ("spoob", "spoob@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com")] + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de"), + ("RaNaN", "ranan@pyload.org"), + ("spoob", "spoob@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com")] event_list = ["archive_extracted", "package_extracted", "all_archives_extracted", "all_archives_processed", diff --git a/pyload/plugins/addon/ExtractArchive.py b/pyload/plugins/addon/ExtractArchive.py index cdf2eecee..a53d2f951 100644 --- a/pyload/plugins/addon/ExtractArchive.py +++ b/pyload/plugins/addon/ExtractArchive.py @@ -14,6 +14,7 @@ if sys.version_info < (2, 7) and os.name != "nt": import errno from subprocess import Popen + def _eintr_retry_call(func, *args): while True: try: @@ -23,6 +24,7 @@ if sys.version_info < (2, 7) and os.name != "nt": continue raise + # unsued timeout option for older python version def wait(self, timeout=0): """Wait for child process to terminate. Returns returncode @@ -53,8 +55,8 @@ from pyload.utils import safe_join, fs_encode class ExtractArchive(Addon): - __name__ = "ExtractArchive" - __type__ = "addon" + __name__ = "ExtractArchive" + __type__ = "addon" __version__ = "0.17" __config__ = [("activated", "bool", "Activated", True), @@ -70,9 +72,10 @@ class ExtractArchive(Addon): ("renice", "int", "CPU Priority", 0)] __description__ = """Extract different kind of archives""" - __authors__ = [("RaNaN", "ranan@pyload.org"), - ("AndroKev", None), - ("Walter Purcaro", "vuolter@gmail.com")] + __license__ = "GPLv3" + __authors__ = [("RaNaN", "ranan@pyload.org"), + ("AndroKev", None), + ("Walter Purcaro", "vuolter@gmail.com")] event_list = ["allDownloadsProcessed"] @@ -307,16 +310,18 @@ class ExtractArchive(Addon): def reloadPasswords(self): passwordfile = self.getConfig("passwordfile") - if not exists(passwordfile): - open(passwordfile, "wb").close() - passwords = [] - f = open(passwordfile, "rb") - for pw in f.read().splitlines(): - passwords.append(pw) - f.close() + try: + passwords = [] + with open(passwordfile, "a+") as f: + for pw in f.read().splitlines(): + passwords.append(pw) - self.passwords = passwords + except IOError, e: + self.logError(e) + + else: + self.passwords = passwords @Expose @@ -326,12 +331,15 @@ class ExtractArchive(Addon): if pw in self.passwords: self.passwords.remove(pw) + self.passwords.insert(0, pw) - f = open(passwordfile, "wb") - for pw in self.passwords: - f.write(pw + "\n") - f.close() + try: + with open(passwordfile, "wb") as f: + for pw in self.passwords: + f.write(pw + "\n") + except IOError, e: + self.logError(e) def setPermissions(self, files): diff --git a/pyload/plugins/addon/HotFolder.py b/pyload/plugins/addon/HotFolder.py index cceb71ca7..0bce193ce 100644 --- a/pyload/plugins/addon/HotFolder.py +++ b/pyload/plugins/addon/HotFolder.py @@ -7,58 +7,58 @@ from os.path import exists, isfile, join from shutil import move from pyload.plugins.base.Addon import Addon +from module.utils import fs_encode, save_join class HotFolder(Addon): - __name__ = "HotFolder" - __type__ = "addon" + __name__ = "HotFolder" + __type__ = "addon" __version__ = "0.11" - __config__ = [("activated", "bool", "Activated", False), - ("folder", "str", "Folder to observe", "container"), + __config__ = [("folder", "str", "Folder to observe", "container"), ("watch_file", "bool", "Observe link file", False), ("keep", "bool", "Keep added containers", True), ("file", "str", "Link file", "links.txt")] __description__ = """Observe folder and file for changes and add container and links""" - __authors__ = [("RaNaN", "RaNaN@pyload.de")] + __license__ = "GPLv3" + __authors__ = [("RaNaN", "RaNaN@pyload.de")] def setup(self): self.interval = 10 + def periodical(self): - if not exists(join(self.getConfig("folder"), "finished")): - makedirs(join(self.getConfig("folder"), "finished")) + folder = fs_encode(self.getConfig("folder")) + + try: + if not exists(join(folder, "finished")): + makedirs(join(folder, "finished")) - if self.getConfig("watch_file"): + if self.getConfig("watch_file"): + with open(fs_encode(self.getConfig("file")), "a+") as f: + content = f.read().strip() - if not exists(self.getConfig("file")): - f = open(self.getConfig("file"), "wb") - f.close() + if content: + name = "%s_%s.txt" % (self.getConfig("file"), time.strftime("%H-%M-%S_%d%b%Y")) - f = open(self.getConfig("file"), "rb") - content = f.read().strip() - f.close() - f = open(self.getConfig("file"), "wb") - f.close() - if content: - name = "%s_%s.txt" % (self.getConfig("file"), time.strftime("%H-%M-%S_%d%b%Y")) + with open(save_join(folder, "finished", name), "wb") as f: + f.write(content) - f = open(join(self.getConfig("folder"), "finished", name), "wb") - f.write(content) - f.close() + self.core.api.addPackage(f.name, [f.name], 1) - self.core.api.addPackage(f.name, [f.name], 1) + for f in listdir(folder): + path = join(folder, f) - for f in listdir(self.getConfig("folder")): - path = join(self.getConfig("folder"), f) + if not isfile(path) or f.endswith("~") or f.startswith("#") or f.startswith("."): + continue - if not isfile(path) or f.endswith("~") or f.startswith("#") or f.startswith("."): - continue + newpath = join(folder, "finished", f if self.getConfig("keep") else "tmp_" + f) + move(path, newpath) - newpath = join(self.getConfig("folder"), "finished", f if self.getConfig("keep") else "tmp_" + f) - move(path, newpath) + self.logInfo(_("Added %s from HotFolder") % f) + self.core.api.addPackage(f, [newpath], 1) - self.logInfo(_("Added %s from HotFolder") % f) - self.core.api.addPackage(f, [newpath], 1) + except IOError, e: + self.logError(e) diff --git a/pyload/plugins/addon/IRCInterface.py b/pyload/plugins/addon/IRCInterface.py index 9f77bfc7e..041c8b07b 100644 --- a/pyload/plugins/addon/IRCInterface.py +++ b/pyload/plugins/addon/IRCInterface.py @@ -2,6 +2,7 @@ import re import socket +import ssl import time from pycurl import FORM_FILE @@ -17,15 +18,15 @@ from pyload.utils import formatSize class IRCInterface(Thread, Addon): - __name__ = "IRCInterface" - __type__ = "addon" - __version__ = "0.11" + __name__ = "IRCInterface" + __type__ = "addon" + __version__ = "0.12" - __config__ = [("activated", "bool", "Activated", False), - ("host", "str", "IRC-Server Address", "Enter your server here!"), + __config__ = [("host", "str", "IRC-Server Address", "Enter your server here!"), ("port", "int", "IRC-Server Port", 6667), ("ident", "str", "Clients ident", "pyload-irc"), ("realname", "str", "Realname", "pyload-irc"), + ("ssl", "bool", "Use SSL", False), ("nick", "str", "Nickname the Client will take", "pyLoad-IRC"), ("owner", "str", "Nickname the Client will accept commands from", "Enter your nick here!"), ("info_file", "bool", "Inform about every file finished", False), @@ -33,15 +34,15 @@ class IRCInterface(Thread, Addon): ("captcha", "bool", "Send captcha requests", True)] __description__ = """Connect to irc and let owner perform different tasks""" - __authors__ = [("Jeix", "Jeix@hasnomail.com")] + __license__ = "GPLv3" + __authors__ = [("Jeix", "Jeix@hasnomail.com")] def __init__(self, core, manager): Thread.__init__(self) Addon.__init__(self, core, manager) self.setDaemon(True) - # self.sm = core.server_methods - self.api = core.api # todo, only use api + def coreReady(self): self.abort = False @@ -50,6 +51,7 @@ class IRCInterface(Thread, Addon): self.start() + def packageFinished(self, pypack): try: if self.getConfig("info_pack"): @@ -57,6 +59,7 @@ class IRCInterface(Thread, Addon): except: pass + def downloadFinished(self, pyfile): try: if self.getConfig("info_file"): @@ -65,6 +68,7 @@ class IRCInterface(Thread, Addon): except: pass + def newCaptchaTask(self, task): if self.getConfig("captcha") and task.isTextual(): task.handler.append(self) @@ -77,11 +81,16 @@ class IRCInterface(Thread, Addon): self.response(_("New Captcha Request: %s") % url) self.response(_("Answer with 'c %s text on the captcha'") % task.id) + def run(self): # connect to IRC etc. self.sock = socket.socket() host = self.getConfig("host") self.sock.connect((host, self.getConfig("port"))) + + if self.getConfig("ssl"): + self.sock = ssl.wrap_socket(self.sock, cert_reqs=ssl.CERT_NONE) #@TODO: support certificate + nick = self.getConfig("nick") self.sock.send("NICK %s\r\n" % nick) self.sock.send("USER %s %s bla :%s\r\n" % (nick, host, nick)) @@ -98,6 +107,7 @@ class IRCInterface(Thread, Addon): print_exc() self.sock.close() + def main_loop(self): readbuffer = "" while True: @@ -136,6 +146,7 @@ class IRCInterface(Thread, Addon): self.handle_events(msg) + def handle_events(self, msg): if not msg['origin'].split("!", 1)[0] in self.getConfig("owner").split(): return @@ -148,15 +159,15 @@ class IRCInterface(Thread, Addon): # HANDLE CTCP ANTI FLOOD/BOT PROTECTION if msg['text'] == "\x01VERSION\x01": - self.logDebug("Sending CTCP VERSION.") + self.logDebug("Sending CTCP VERSION") self.sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) return elif msg['text'] == "\x01TIME\x01": - self.logDebug("Sending CTCP TIME.") + self.logDebug("Sending CTCP TIME") self.sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time())) return elif msg['text'] == "\x01LAG\x01": - self.logDebug("Received CTCP LAG.") # don't know how to answer + self.logDebug("Received CTCP LAG") #: don't know how to answer return trigger = "pass" @@ -176,7 +187,8 @@ class IRCInterface(Thread, Addon): for line in res: self.response(line, msg['origin']) except Exception, e: - self.logError(repr(e)) + self.logError(e) + def response(self, msg, origin=""): if origin == "": @@ -185,13 +197,15 @@ class IRCInterface(Thread, Addon): else: self.sock.send("PRIVMSG %s :%s\r\n" % (origin.split("!", 1)[0], msg)) + #### Events def event_pass(self, args): return [] + def event_status(self, args): - downloads = self.api.statusDownloads() + downloads = self.core.api.statusDownloads() if not downloads: return ["INFO: There are no active downloads currently."] @@ -215,8 +229,9 @@ class IRCInterface(Thread, Addon): )) return lines + def event_queue(self, args): - ps = self.api.getQueueData() + ps = self.core.api.getQueueData() if not ps: return ["INFO: There are no packages in queue."] @@ -227,8 +242,9 @@ class IRCInterface(Thread, Addon): return lines + def event_collector(self, args): - ps = self.api.getCollectorData() + ps = self.core.api.getCollectorData() if not ps: return ["INFO: No packages in collector!"] @@ -238,19 +254,21 @@ class IRCInterface(Thread, Addon): return lines + def event_info(self, args): if not args: return ["ERROR: Use info like this: info <id>"] info = None try: - info = self.api.getFileData(int(args[0])) + info = self.core.api.getFileData(int(args[0])) except FileDoesNotExists: return ["ERROR: Link doesn't exists."] return ['LINK #%s: %s (%s) [%s][%s]' % (info.fid, info.name, info.format_size, info.statusmsg, info.plugin)] + def event_packinfo(self, args): if not args: return ["ERROR: Use packinfo like this: packinfo <id>"] @@ -258,7 +276,7 @@ class IRCInterface(Thread, Addon): lines = [] pack = None try: - pack = self.api.getPackageData(int(args[0])) + pack = self.core.api.getPackageData(int(args[0])) except PackageDoesNotExists: return ["ERROR: Package doesn't exists."] @@ -282,6 +300,7 @@ class IRCInterface(Thread, Addon): return lines + def event_more(self, args): if not self.more: return ["No more information to display."] @@ -292,14 +311,17 @@ class IRCInterface(Thread, Addon): return lines + def event_start(self, args): - self.api.unpauseServer() + self.core.api.unpauseServer() return ["INFO: Starting downloads."] + def event_stop(self, args): - self.api.pauseServer() + self.core.api.pauseServer() return ["INFO: No new downloads will be started."] + def event_add(self, args): if len(args) < 2: return ['ERROR: Add links like this: "add <packagename|id> links". ', @@ -312,7 +334,7 @@ class IRCInterface(Thread, Addon): count_failed = 0 try: id = int(pack) - pack = self.api.getPackageData(id) + pack = self.core.api.getPackageData(id) if not pack: return ["ERROR: Package doesn't exists."] @@ -322,48 +344,52 @@ class IRCInterface(Thread, Addon): except: # create new package - id = self.api.addPackage(pack, links, 1) + id = self.core.api.addPackage(pack, links, 1) return ["INFO: Created new Package %s [#%d] with %d links." % (pack, id, len(links))] + def event_del(self, args): if len(args) < 2: return ["ERROR: Use del command like this: del -p|-l <id> [...] (-p indicates that the ids are from packages, -l indicates that the ids are from links)"] if args[0] == "-p": - ret = self.api.deletePackages(map(int, args[1:])) + ret = self.core.api.deletePackages(map(int, args[1:])) return ["INFO: Deleted %d packages!" % len(args[1:])] elif args[0] == "-l": - ret = self.api.delLinks(map(int, args[1:])) + ret = self.core.api.delLinks(map(int, args[1:])) return ["INFO: Deleted %d links!" % len(args[1:])] else: return ["ERROR: Use del command like this: del <-p|-l> <id> [...] (-p indicates that the ids are from packages, -l indicates that the ids are from links)"] + def event_push(self, args): if not args: return ["ERROR: Push package to queue like this: push <package id>"] id = int(args[0]) try: - info = self.api.getPackageInfo(id) + info = self.core.api.getPackageInfo(id) except PackageDoesNotExists: return ["ERROR: Package #%d does not exist." % id] - self.api.pushToQueue(id) + self.core.api.pushToQueue(id) return ["INFO: Pushed package #%d to queue." % id] + def event_pull(self, args): if not args: return ["ERROR: Pull package from queue like this: pull <package id>."] id = int(args[0]) - if not self.api.getPackageData(id): + if not self.core.api.getPackageData(id): return ["ERROR: Package #%d does not exist." % id] - self.api.pullFromQueue(id) + self.core.api.pullFromQueue(id) return ["INFO: Pulled package #%d from queue to collector." % id] + def event_c(self, args): """ captcha answer """ if not args: @@ -376,6 +402,7 @@ class IRCInterface(Thread, Addon): task.setResult(" ".join(args[1:])) return ["INFO: Result %s saved." % " ".join(args[1:])] + def event_help(self, args): lines = ["The following commands are available:", "add <package|packid> <links> [...] Adds link to package. (creates new package if it does not exist)", @@ -399,5 +426,6 @@ class IRCError(Exception): def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) diff --git a/pyload/plugins/addon/MergeFiles.py b/pyload/plugins/addon/MergeFiles.py index 1edbf119a..e67f87f56 100644 --- a/pyload/plugins/addon/MergeFiles.py +++ b/pyload/plugins/addon/MergeFiles.py @@ -2,21 +2,23 @@ import os import re -import traceback + +from traceback import print_exc from pyload.plugins.base.Addon import Addon, threaded from pyload.utils import safe_join, fs_encode class MergeFiles(Addon): - __name__ = "MergeFiles" - __type__ = "addon" + __name__ = "MergeFiles" + __type__ = "addon" __version__ = "0.12" - __config__ = [("activated", "bool", "Activated", False)] + __config__ = [("activated", "bool", "Activated", True)] __description__ = """Merges parts splitted with hjsplit""" - __authors__ = [("and9000", "me@has-no-mail.com")] + __license__ = "GPLv3" + __authors__ = [("and9000", "me@has-no-mail.com")] BUFFER_SIZE = 4096 @@ -26,12 +28,13 @@ class MergeFiles(Addon): # nothing to do pass + @threaded def packageFinished(self, pack): files = {} fid_dict = {} for fid, data in pack.getChildren().iteritems(): - if re.search("\.[0-9]{3}$", data['name']): + if re.search("\.\d{3}$", data['name']): if data['name'][:-4] not in files: files[data['name'][:-4]] = [] files[data['name'][:-4]].append(data['name']) @@ -55,6 +58,7 @@ class MergeFiles(Addon): s_file = open(os.path.join(download_folder, splitted_file), "rb") size_written = 0 s_file_size = int(os.path.getsize(os.path.join(download_folder, splitted_file))) + while True: f_buffer = s_file.read(self.BUFFER_SIZE) if f_buffer: @@ -63,10 +67,13 @@ class MergeFiles(Addon): pyfile.setProgress((size_written * 100) / s_file_size) else: break + s_file.close() self.logDebug("Finished merging part", splitted_file) + except Exception, e: - print traceback.print_exc() + print_exc() + finally: pyfile.setProgress(100) pyfile.setStatus("finished") diff --git a/pyload/plugins/addon/MultiHome.py b/pyload/plugins/addon/MultiHome.py index f7bca4843..a808802ba 100644 --- a/pyload/plugins/addon/MultiHome.py +++ b/pyload/plugins/addon/MultiHome.py @@ -6,15 +6,15 @@ from pyload.plugins.base.Addon import Addon class MultiHome(Addon): - __name__ = "MultiHome" - __type__ = "addon" + __name__ = "MultiHome" + __type__ = "addon" __version__ = "0.11" - __config__ = [("activated", "bool", "Activated", False), - ("interfaces", "str", "Interfaces", "None")] + __config__ = [("interfaces", "str", "Interfaces", "None")] __description__ = """Ip address changer""" - __authors__ = [("mkaay", "mkaay@mkaay.de")] + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] def setup(self): @@ -25,15 +25,18 @@ class MultiHome(Addon): self.parseInterfaces([self.config['download']['interface']]) self.setConfig("interfaces", self.toConfig()) + def toConfig(self): return ";".join([i.adress for i in self.interfaces]) + def parseInterfaces(self, interfaces): for interface in interfaces: if not interface or str(interface).lower() == "none": continue self.interfaces.append(Interface(interface)) + def coreReady(self): requestFactory = self.core.requestFactory oldGetRequest = requestFactory.getRequest @@ -48,6 +51,7 @@ class MultiHome(Addon): requestFactory.getRequest = getRequest + def bestInterface(self, pluginName, account): best = None for interface in self.interfaces: @@ -62,13 +66,16 @@ class Interface(object): self.adress = adress self.history = {} + def lastPluginAccess(self, pluginName, account): if (pluginName, account) in self.history: return self.history[(pluginName, account)] return 0 + def useFor(self, pluginName, account): self.history[(pluginName, account)] = time() + def __repr__(self): return "<Interface - %s>" % self.adress diff --git a/pyload/plugins/addon/RestartFailed.py b/pyload/plugins/addon/RestartFailed.py index 7d736db46..879836bcf 100644 --- a/pyload/plugins/addon/RestartFailed.py +++ b/pyload/plugins/addon/RestartFailed.py @@ -4,18 +4,18 @@ from pyload.plugins.base.Addon import Addon class RestartFailed(Addon): - __name__ = "RestartFailed" - __type__ = "addon" - __version__ = "1.55" + __name__ = "RestartFailed" + __type__ = "addon" + __version__ = "1.57" - __config__ = [("activated", "bool", "Activated", False), - ("interval", "int", "Check interval in minutes", 90)] + __config__ = [("interval", "int", "Check interval in minutes", 90)] __description__ = """Periodically restart all failed downloads in queue""" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - event_list = ["pluginConfigChanged"] + # event_list = ["pluginConfigChanged"] MIN_INTERVAL = 15 * 60 #: 15m minimum check interval (value is in seconds) @@ -30,13 +30,15 @@ class RestartFailed(Addon): else: self.logDebug("Invalid interval value, kept current") + def periodical(self): - self.logInfo(_("Restart failed downloads")) - self.api.restartFailed() + self.logDebug(_("Restart failed downloads")) + self.core.api.restartFailed() + def setup(self): - self.api = self.core.api self.interval = self.MIN_INTERVAL + def coreReady(self): self.pluginConfigChanged(self.__name__, "interval", self.getConfig("interval")) diff --git a/pyload/plugins/addon/UnSkipOnFail.py b/pyload/plugins/addon/UnSkipOnFail.py index 7ab069e93..5122e21eb 100644 --- a/pyload/plugins/addon/UnSkipOnFail.py +++ b/pyload/plugins/addon/UnSkipOnFail.py @@ -8,14 +8,15 @@ from pyload.utils import fs_encode class UnSkipOnFail(Addon): - __name__ = "UnSkipOnFail" - __type__ = "addon" + __name__ = "UnSkipOnFail" + __type__ = "addon" __version__ = "0.01" __config__ = [("activated", "bool", "Activated", True)] __description__ = """When a download fails, restart skipped duplicates""" - __authors__ = [("hagg", None)] + __license__ = "GPLv3" + __authors__ = [("hagg", None)] def downloadFailed(self, pyfile): @@ -31,6 +32,7 @@ class UnSkipOnFail(Addon): self.logInfo(_('restart "%s" (pid:%s)') % (pyfile_name, lpid)) self.setLinkStatus(link, "queued") + def findDuplicates(self, pyfile): """ Search all packages for duplicate links to "pyfile". Duplicates are links that would overwrite "pyfile". @@ -60,6 +62,7 @@ class UnSkipOnFail(Addon): dups.append(link) return dups + def setLinkStatus(self, link, new_status): """ Change status of "link" to "new_status". "link" has to be a valid FileData object, diff --git a/pyload/plugins/addon/WindowsPhoneToastNotify.py b/pyload/plugins/addon/WindowsPhoneToastNotify.py index e6605dfb2..e35f74e84 100644 --- a/pyload/plugins/addon/WindowsPhoneToastNotify.py +++ b/pyload/plugins/addon/WindowsPhoneToastNotify.py @@ -7,22 +7,23 @@ from pyload.plugins.base.Addon import Addon class WindowsPhoneToastNotify(Addon): - __name__ = "WindowsPhoneToastNotify" - __type__ = "addon" + __name__ = "WindowsPhoneToastNotify" + __type__ = "addon" __version__ = "0.02" - __config__ = [("activated", "bool", "Activated", False), - ("force", "bool", "Force even if client is connected", False), + __config__ = [("force", "bool", "Force even if client is connected", False), ("pushId", "str", "pushId", ""), ("pushUrl", "str", "pushUrl", ""), ("pushTimeout", "int", "Timeout between notifications in seconds", 0)] __description__ = """Send push notifications to Windows Phone""" - __authors__ = [("Andy Voigt", "phone-support@hotmail.de")] + __license__ = "GPLv3" + __authors__ = [("Andy Voigt", "phone-support@hotmail.de")] def setup(self): - self.info = {} + self.info = {} #@TODO: Remove in 0.4.10 + def getXmlData(self): myxml = ("<?xml version='1.0' encoding='utf-8'?> <wp:Notification xmlns:wp='WPNotification'> " @@ -30,6 +31,7 @@ class WindowsPhoneToastNotify(Addon): "</wp:Toast> </wp:Notification>") return myxml + def doRequest(self): URL = self.getConfig("pushUrl") request = self.getXmlData() @@ -45,6 +47,7 @@ class WindowsPhoneToastNotify(Addon): webservice.close() self.setStorage("LAST_NOTIFY", time.time()) + def newCaptchaTask(self, task): if not self.getConfig("pushId") or not self.getConfig("pushUrl"): return False diff --git a/pyload/plugins/addon/XMPPInterface.py b/pyload/plugins/addon/XMPPInterface.py index de04f05fb..07db5c66a 100644 --- a/pyload/plugins/addon/XMPPInterface.py +++ b/pyload/plugins/addon/XMPPInterface.py @@ -10,12 +10,11 @@ from pyload.plugins.addon.IRCInterface import IRCInterface class XMPPInterface(IRCInterface, JabberClient): - __name__ = "XMPPInterface" - __type__ = "addon" + __name__ = "XMPPInterface" + __type__ = "addon" __version__ = "0.11" - __config__ = [("activated", "bool", "Activated", False), - ("jid", "str", "Jabber ID", "user@exmaple-jabber-server.org"), + __config__ = [("jid", "str", "Jabber ID", "user@exmaple-jabber-server.org"), ("pw", "str", "Password", ""), ("tls", "bool", "Use TLS", False), ("owners", "str", "List of JIDs accepting commands from", "me@icq-gateway.org;some@msn-gateway.org"), @@ -24,11 +23,13 @@ class XMPPInterface(IRCInterface, JabberClient): ("captcha", "bool", "Send captcha requests", True)] __description__ = """Connect to jabber and let owner perform different tasks""" - __authors__ = [("RaNaN", "RaNaN@pyload.org")] + __license__ = "GPLv3" + __authors__ = [("RaNaN", "RaNaN@pyload.org")] implements(IMessageHandlersProvider) + def __init__(self, core, manager): IRCInterface.__init__(self, core, manager) @@ -57,11 +58,13 @@ class XMPPInterface(IRCInterface, JabberClient): self, ] + def coreReady(self): self.new_package = {} self.start() + def packageFinished(self, pypack): try: if self.getConfig("info_pack"): @@ -69,6 +72,7 @@ class XMPPInterface(IRCInterface, JabberClient): except: pass + def downloadFinished(self, pyfile): try: if self.getConfig("info_file"): @@ -77,6 +81,7 @@ class XMPPInterface(IRCInterface, JabberClient): except: pass + def run(self): # connect to IRC etc. self.connect() @@ -85,21 +90,26 @@ class XMPPInterface(IRCInterface, JabberClient): except Exception, ex: self.logError(ex) + def stream_state_changed(self, state, arg): """This one is called when the state of stream connecting the component to a server changes. This will usually be used to let the user know what is going on.""" self.logDebug("*** State changed: %s %r ***" % (state, arg)) + def disconnected(self): self.logDebug("Client was disconnected") + def stream_closed(self, stream): self.logDebug("Stream was closed", stream) + def stream_error(self, err): self.logDebug("Stream Error", err) + def get_message_handlers(self): """Return list of (message_type, message_handler) tuples. @@ -107,6 +117,7 @@ class XMPPInterface(IRCInterface, JabberClient): in a client session.""" return [("normal", self.message)] + def message(self, stanza): """Message handler for the component.""" subject = stanza.get_subject() @@ -157,16 +168,18 @@ class XMPPInterface(IRCInterface, JabberClient): messages.append(m) except Exception, e: - self.logError(repr(e)) + self.logError(e) return messages else: return True + def response(self, msg, origin=""): return self.announce(msg) + def announce(self, message): """ send message to all owners""" for user in self.getConfig("owners").split(";"): @@ -186,9 +199,11 @@ class XMPPInterface(IRCInterface, JabberClient): stream.send(m) + def beforeReconnecting(self, ip): self.disconnect() + def afterReconnecting(self, ip): self.connect() @@ -201,24 +216,29 @@ class VersionHandler(object): implements(IIqHandlersProvider, IFeaturesProvider) + def __init__(self, client): """Just remember who created this.""" self.client = client + def get_features(self): """Return namespace which should the client include in its reply to a disco#info query.""" return ["jabber:iq:version"] + def get_iq_get_handlers(self): """Return list of tuples (element_name, namespace, handler) describing handlers of <iq type='get'/> stanzas""" return [("query", "jabber:iq:version", self.get_version)] + def get_iq_set_handlers(self): """Return empty list, as this class provides no <iq type='set'/> stanza handler.""" return [] + def get_version(self, iq): """Handler for jabber:iq:version queries. |