diff options
Diffstat (limited to 'module/plugins/hooks')
53 files changed, 0 insertions, 5165 deletions
diff --git a/module/plugins/hooks/AlldebridComHook.py b/module/plugins/hooks/AlldebridComHook.py deleted file mode 100644 index 092921134..000000000 --- a/module/plugins/hooks/AlldebridComHook.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class AlldebridComHook(MultiHook): - __name__ = "AlldebridComHook" - __type__ = "hook" - __version__ = "0.16" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 ), - ("ssl" , "bool" , "Use HTTPS" , True )] - - __description__ = """Alldebrid.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Andy Voigt", "spamsales@online.de")] - - - def getHosters(self): - https = "https" if self.getConfig('ssl') else "http" - html = self.getURL(https + "://www.alldebrid.com/api.php", get={'action': "get_host"}).replace("\"", "").strip() - - return [x.strip() for x in html.split(",") if x.strip()] diff --git a/module/plugins/hooks/AndroidPhoneNotify.py b/module/plugins/hooks/AndroidPhoneNotify.py deleted file mode 100644 index 67a0ea4f0..000000000 --- a/module/plugins/hooks/AndroidPhoneNotify.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- - -import time - -from module.network.RequestFactory import getURL -from module.plugins.Hook import Hook, Expose - - -class AndroidPhoneNotify(Hook): - __name__ = "AndroidPhoneNotify" - __type__ = "hook" - __version__ = "0.07" - - __config__ = [("apikey" , "str" , "API key" , "" ), - ("notifycaptcha" , "bool", "Notify captcha request" , True ), - ("notifypackage" , "bool", "Notify package finished" , True ), - ("notifyprocessed", "bool", "Notify packages processed" , True ), - ("notifyupdate" , "bool", "Notify plugin updates" , True ), - ("notifyexit" , "bool", "Notify pyLoad shutdown" , True ), - ("sendtimewait" , "int" , "Timewait in seconds between notifications", 5 ), - ("sendpermin" , "int" , "Max notifications per minute" , 12 ), - ("ignoreclient" , "bool", "Send notifications if client is connected", False)] - - __description__ = """Send push notifications to your Android Phone (using notifymyandroid.com)""" - __license__ = "GPLv3" - __authors__ = [("Steven Kosyra" , "steven.kosyra@gmail.com"), - ("Walter Purcaro", "vuolter@gmail.com" )] - - - event_list = ["allDownloadsProcessed", "plugin_updated"] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.last_notify = 0 - self.notifications = 0 - - - def plugin_updated(self, type_plugins): - if not self.getConfig('notifyupdate'): - return - - self.notify(_("Plugins updated"), str(type_plugins)) - - - def coreExiting(self): - if not self.getConfig('notifyexit'): - return - - if self.core.do_restart: - self.notify(_("Restarting pyLoad")) - else: - self.notify(_("Exiting pyLoad")) - - - def newCaptchaTask(self, task): - if not self.getConfig('notifycaptcha'): - return - - self.notify(_("Captcha"), _("New request waiting user input")) - - - def packageFinished(self, pypack): - if self.getConfig('notifypackage'): - self.notify(_("Package finished"), pypack.name) - - - def allDownloadsProcessed(self): - if not self.getConfig('notifyprocessed'): - return - - if any(True for pdata in self.core.api.getQueue() if pdata.linksdone < pdata.linkstotal): - self.notify(_("Package failed"), _("One or more packages was not completed successfully")) - else: - self.notify(_("All packages finished")) - - - @Expose - def notify(self, - event, - msg="", - key=self.getConfig('apikey')): - - if not key: - return - - if self.core.isClientConnected() and not self.getConfig('ignoreclient'): - return - - elapsed_time = time.time() - self.last_notify - - if elapsed_time < self.getConf("sendtimewait"): - return - - if elapsed_time > 60: - self.notifications = 0 - - elif self.notifications >= self.getConf("sendpermin"): - return - - - getURL("http://www.notifymyandroid.com/publicapi/notify", - get={'apikey' : key, - 'application': "pyLoad", - 'event' : event, - 'description': msg}) - - self.last_notify = time.time() - self.notifications += 1 diff --git a/module/plugins/hooks/AntiVirus.py b/module/plugins/hooks/AntiVirus.py deleted file mode 100644 index c620f556d..000000000 --- a/module/plugins/hooks/AntiVirus.py +++ /dev/null @@ -1,119 +0,0 @@ -# -*- coding: utf-8 -*- - -import os -import shutil -import subprocess - -try: - import send2trash -except ImportError: - pass - -from module.plugins.Hook import Hook, Expose, threaded -from module.utils import fs_encode, save_join - - -class AntiVirus(Hook): - __name__ = "AntiVirus" - __type__ = "hook" - __version__ = "0.09" - - #@TODO: add trash option (use Send2Trash lib) - __config__ = [("action" , "Antivirus default;Delete;Quarantine", "Manage infected files" , "Antivirus default"), - ("quardir" , "folder" , "Quarantine folder" , "" ), - ("deltotrash", "bool" , "Move to trash (recycle bin) instead delete", True ), - ("scanfailed", "bool" , "Scan incompleted files (failed downloads)" , False ), - ("cmdfile" , "file" , "Antivirus executable" , "" ), - ("cmdargs" , "str" , "Scan options" , "" ), - ("ignore-err", "bool" , "Ignore scan errors" , False )] - - __description__ = """Scan downloaded files with antivirus program""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - @Expose - @threaded - def scan(self, pyfile, thread): - file = fs_encode(pyfile.plugin.lastDownload) - filename = os.path.basename(pyfile.plugin.lastDownload) - cmdfile = fs_encode(self.getConfig('cmdfile')) - cmdargs = fs_encode(self.getConfig('cmdargs').strip()) - - if not os.path.isfile(file) or not os.path.isfile(cmdfile): - return - - thread.addActive(pyfile) - pyfile.setCustomStatus(_("virus scanning")) - pyfile.setProgress(0) - - try: - p = subprocess.Popen([cmdfile, cmdargs, file], bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - out, err = map(str.strip, p.communicate()) - - if out: - self.logInfo(filename, out) - - if err: - self.logWarning(filename, err) - if not self.getConfig('ignore-err'): - self.logDebug("Delete/Quarantine task is aborted") - return - - if p.returncode: - pyfile.error = _("infected file") - action = self.getConfig('action') - try: - if action == "Delete": - if not self.getConfig('deltotrash'): - os.remove(file) - - else: - try: - send2trash.send2trash(file) - - except NameError: - self.logWarning(_("Send2Trash lib not found, moving to quarantine instead")) - pyfile.setCustomStatus(_("file moving")) - shutil.move(file, self.getConfig('quardir')) - - except Exception, e: - self.logWarning(_("Unable to move file to trash: %s, moving to quarantine instead") % e.message) - pyfile.setCustomStatus(_("file moving")) - shutil.move(file, self.getConfig('quardir')) - - else: - self.logDebug(_("Successfully moved file to trash")) - - elif action == "Quarantine": - pyfile.setCustomStatus(_("file moving")) - shutil.move(file, self.getConfig('quardir')) - - except (IOError, shutil.Error), e: - self.logError(filename, action + " action failed!", e) - - elif not out and not err: - self.logDebug(filename, "No infected file found") - - finally: - pyfile.setProgress(100) - thread.finishFile(pyfile) - - - def downloadFinished(self, pyfile): - return self.scan(pyfile) - - - def downloadFailed(self, pyfile): - #: Check if pyfile is still "failed", - # maybe might has been restarted in meantime - if pyfile.status == 8 and self.getConfig('scanfailed'): - return self.scan(pyfile) diff --git a/module/plugins/hooks/BypassCaptcha.py b/module/plugins/hooks/BypassCaptcha.py deleted file mode 100644 index 9e01edfa2..000000000 --- a/module/plugins/hooks/BypassCaptcha.py +++ /dev/null @@ -1,141 +0,0 @@ -# -*- coding: utf-8 -*- - -import pycurl - -from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getURL, getRequest -from module.plugins.Hook import Hook, threaded - - -class BypassCaptchaException(Exception): - - def __init__(self, err): - self.err = err - - - def getCode(self): - return self.err - - - def __str__(self): - return "<BypassCaptchaException %s>" % self.err - - - def __repr__(self): - return "<BypassCaptchaException %s>" % self.err - - -class BypassCaptcha(Hook): - __name__ = "BypassCaptcha" - __type__ = "hook" - __version__ = "0.06" - - __config__ = [("force", "bool", "Force BC even if client is connected", False), - ("passkey", "password", "Passkey", "")] - - __description__ = """Send captchas to BypassCaptcha.com""" - __license__ = "GPLv3" - __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), - ("Godofdream", "soilfcition@gmail.com"), - ("zoidberg" , "zoidberg@mujmail.cz" )] - - - interval = 0 #@TODO: Remove in 0.4.10 - - PYLOAD_KEY = "4f771155b640970d5607f919a615bdefc67e7d32" - - SUBMIT_URL = "http://bypasscaptcha.com/upload.php" - RESPOND_URL = "http://bypasscaptcha.com/check_value.php" - GETCREDITS_URL = "http://bypasscaptcha.com/ex_left.php" - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def getCredits(self): - res = getURL(self.GETCREDITS_URL, post={"key": self.getConfig('passkey')}) - - data = dict(x.split(' ', 1) for x in res.splitlines()) - return int(data['Left']) - - - def submit(self, captcha, captchaType="file", match=None): - req = getRequest() - - #raise timeout threshold - req.c.setopt(pycurl.LOW_SPEED_TIME, 80) - - try: - res = req.load(self.SUBMIT_URL, - post={'vendor_key': self.PYLOAD_KEY, - 'key': self.getConfig('passkey'), - 'gen_task_id': "1", - 'file': (pycurl.FORM_FILE, captcha)}, - multipart=True) - finally: - req.close() - - data = dict(x.split(' ', 1) for x in res.splitlines()) - if not data or "Value" not in data: - raise BypassCaptchaException(res) - - result = data['Value'] - ticket = data['TaskId'] - self.logDebug("Result %s : %s" % (ticket, result)) - - return ticket, result - - - def respond(self, ticket, success): - try: - res = getURL(self.RESPOND_URL, post={"task_id": ticket, "key": self.getConfig('passkey'), - "cv": 1 if success else 0}) - except BadHeader, e: - self.logError(_("Could not send response"), e) - - - def newCaptchaTask(self, task): - if "service" in task.data: - return False - - if not task.isTextual(): - return False - - if not self.getConfig('passkey'): - return False - - if self.core.isClientConnected() and not self.getConfig('force'): - return False - - if self.getCredits() > 0: - task.handler.append(self) - task.data['service'] = self.__name__ - task.setWaiting(100) - self._processCaptcha(task) - - else: - self.logInfo(_("Your %s account has not enough credits") % self.__name__) - - - def captchaCorrect(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: - self.respond(task.data['ticket'], True) - - - def captchaInvalid(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: - self.respond(task.data['ticket'], False) - - - @threaded - def _processCaptcha(self, task): - c = task.captchaFile - try: - ticket, result = self.submit(c) - except BypassCaptchaException, e: - task.error = e.getCode() - return - - task.data['ticket'] = ticket - task.setResult(result) diff --git a/module/plugins/hooks/Captcha9Kw.py b/module/plugins/hooks/Captcha9Kw.py deleted file mode 100644 index 60482b8fc..000000000 --- a/module/plugins/hooks/Captcha9Kw.py +++ /dev/null @@ -1,254 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import re -import time - -from base64 import b64encode - -from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getURL - -from module.plugins.Hook import Hook, threaded - - -class Captcha9Kw(Hook): - __name__ = "Captcha9Kw" - __type__ = "hook" - __version__ = "0.28" - - __config__ = [("ssl" , "bool" , "Use HTTPS" , True ), - ("force" , "bool" , "Force captcha resolving even if client is connected" , True ), - ("confirm" , "bool" , "Confirm Captcha (cost +6 credits)" , False ), - ("captchaperhour", "int" , "Captcha per hour" , "9999" ), - ("captchapermin" , "int" , "Captcha per minute" , "9999" ), - ("prio" , "int" , "Priority (max 10)(cost +0 -> +10 credits)" , "0" ), - ("queue" , "int" , "Max. Queue (max 999)" , "50" ), - ("hoster_options", "string" , "Hoster options (format: pluginname:prio=1:selfsolfe=1:confirm=1:timeout=900|...)", "ShareonlineBiz:prio=0:timeout=999 | UploadedTo:prio=0:timeout=999"), - ("selfsolve" , "bool" , "Selfsolve (manually solve your captcha in your 9kw client if active)" , "0" ), - ("passkey" , "password", "API key" , "" ), - ("timeout" , "int" , "Timeout in seconds (min 60, max 3999)" , "900" )] - - __description__ = """Send captchas to 9kw.eu""" - __license__ = "GPLv3" - __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), - ("Walter Purcaro", "vuolter@gmail.com")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - API_URL = "http://www.9kw.eu/index.cgi" - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - if self.getConfig('ssl'): - self.API_URL = self.API_URL.replace("http://", "https://") - - - def getCredits(self): - res = getURL(self.API_URL, - get={'apikey': self.getConfig('passkey'), - 'pyload': "1", - 'source': "pyload", - 'action': "usercaptchaguthaben"}) - - if res.isdigit(): - self.logInfo(_("%s credits left") % res) - credits = self.info['credits'] = int(res) - return credits - else: - self.logError(res) - return 0 - - - @threaded - def _processCaptcha(self, task): - try: - with open(task.captchaFile, 'rb') as f: - data = f.read() - - except IOError, e: - self.logError(e) - return - - pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1) - option = {'min' : 2, - 'max' : 50, - 'phrase' : 0, - 'numeric' : 0, - 'case_sensitive': 0, - 'math' : 0, - 'prio' : min(max(self.getConfig('prio'), 0), 10), - 'confirm' : self.getConfig('confirm'), - 'timeout' : min(max(self.getConfig('timeout'), 300), 3999), - 'selfsolve' : self.getConfig('selfsolve'), - 'cph' : self.getConfig('captchaperhour'), - 'cpm' : self.getConfig('captchapermin')} - - for opt in str(self.getConfig('hoster_options').split('|')): - - details = map(str.strip, opt.split(':')) - - if not details or details[0].lower() != pluginname.lower(): - continue - - for d in details: - hosteroption = d.split("=") - - if len(hosteroption) < 2 or not hosteroption[1].isdigit(): - continue - - o = hosteroption[0].lower() - if o in option: - option[o] = hosteroption[1] - - break - - post_data = {'apikey' : self.getConfig('passkey'), - 'prio' : option['prio'], - 'confirm' : option['confirm'], - 'maxtimeout' : option['timeout'], - 'selfsolve' : option['selfsolve'], - 'captchaperhour': option['cph'], - 'captchapermin' : option['cpm'], - 'case-sensitive': option['case_sensitive'], - 'min_len' : option['min'], - 'max_len' : option['max'], - 'phrase' : option['phrase'], - 'numeric' : option['numeric'], - 'math' : option['math'], - 'oldsource' : pluginname, - 'pyload' : "1", - 'source' : "pyload", - 'base64' : "1", - 'mouse' : 1 if task.isPositional() else 0, - 'file-upload-01': b64encode(data), - 'action' : "usercaptchaupload"} - - for _i in xrange(5): - try: - res = getURL(self.API_URL, post=post_data) - except BadHeader, e: - time.sleep(3) - else: - if res and res.isdigit(): - break - else: - self.logError(_("Bad upload: %s") % res) - return - - self.logDebug(_("NewCaptchaID ticket: %s") % res, task.captchaFile) - - task.data["ticket"] = res - - for _i in xrange(int(self.getConfig('timeout') / 5)): - result = getURL(self.API_URL, - get={'apikey': self.getConfig('passkey'), - 'id' : res, - 'pyload': "1", - 'info' : "1", - 'source': "pyload", - 'action': "usercaptchacorrectdata"}) - - if not result or result == "NO DATA": - time.sleep(5) - else: - break - else: - self.logDebug("Could not send request: %s" % res) - result = None - - self.logInfo(_("Captcha result for ticket %s: %s") % (res, result)) - - task.setResult(result) - - - def newCaptchaTask(self, task): - if not task.isTextual() and not task.isPositional(): - return - - if not self.getConfig('passkey'): - return - - if self.core.isClientConnected() and not self.getConfig('force'): - return - - credits = self.getCredits() - - if not credits: - self.logError(_("Your captcha 9kw.eu account has not enough credits")) - return - - queue = min(self.getConfig('queue'), 999) - timeout = min(max(self.getConfig('timeout'), 300), 3999) - pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1) - - for _i in xrange(5): - servercheck = getURL("http://www.9kw.eu/grafik/servercheck.txt") - if queue < re.search(r'queue=(\d+)', servercheck).group(1): - break - - time.sleep(10) - else: - self.fail(_("Too many captchas in queue")) - - for opt in str(self.getConfig('hoster_options').split('|')): - details = map(str.strip, opt.split(':')) - - if not details or details[0].lower() != pluginname.lower(): - continue - - for d in details: - hosteroption = d.split("=") - - if len(hosteroption) > 1 \ - and hosteroption[0].lower() == 'timeout' \ - and hosteroption[1].isdigit(): - timeout = int(hosteroption[1]) - - break - - task.handler.append(self) - - task.setWaiting(timeout) - - self._processCaptcha(task) - - - def _captchaResponse(self, task, correct): - type = "correct" if correct else "refund" - - if 'ticket' not in task.data: - self.logDebug("No CaptchaID for %s request (task: %s)" % (type, task)) - return - - passkey = self.getConfig('passkey') - - for _i in xrange(3): - res = getURL(self.API_URL, - get={'action' : "usercaptchacorrectback", - 'apikey' : passkey, - 'api_key': passkey, - 'correct': "1" if correct else "2", - 'pyload' : "1", - 'source' : "pyload", - 'id' : task.data["ticket"]}) - - self.logDebug("Request %s: %s" % (type, res)) - - if res == "OK": - break - - time.sleep(5) - else: - self.logDebug("Could not send %s request: %s" % (type, res)) - - - def captchaCorrect(self, task): - self._captchaResponse(task, True) - - - def captchaInvalid(self, task): - self._captchaResponse(task, False) diff --git a/module/plugins/hooks/CaptchaBrotherhood.py b/module/plugins/hooks/CaptchaBrotherhood.py deleted file mode 100644 index bda080037..000000000 --- a/module/plugins/hooks/CaptchaBrotherhood.py +++ /dev/null @@ -1,172 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import StringIO -import pycurl -import time -import urllib - -try: - from PIL import Image -except ImportError: - import Image - -from module.network.RequestFactory import getURL, getRequest -from module.plugins.Hook import Hook, threaded - - -class CaptchaBrotherhoodException(Exception): - - def __init__(self, err): - self.err = err - - - def getCode(self): - return self.err - - - def __str__(self): - return "<CaptchaBrotherhoodException %s>" % self.err - - - def __repr__(self): - return "<CaptchaBrotherhoodException %s>" % self.err - - -class CaptchaBrotherhood(Hook): - __name__ = "CaptchaBrotherhood" - __type__ = "hook" - __version__ = "0.08" - - __config__ = [("username", "str", "Username", ""), - ("force", "bool", "Force CT even if client is connected", False), - ("passkey", "password", "Password", "")] - - __description__ = """Send captchas to CaptchaBrotherhood.com""" - __license__ = "GPLv3" - __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), - ("zoidberg", "zoidberg@mujmail.cz")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - API_URL = "http://www.captchabrotherhood.com/" - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def getCredits(self): - res = getURL(self.API_URL + "askCredits.aspx", - get={"username": self.getConfig('username'), "password": self.getConfig('passkey')}) - if not res.startswith("OK"): - raise CaptchaBrotherhoodException(res) - else: - credits = int(res[3:]) - self.logInfo(_("%d credits left") % credits) - self.info['credits'] = credits - return credits - - - def submit(self, captcha, captchaType="file", match=None): - try: - img = Image.open(captcha) - output = StringIO.StringIO() - self.logDebug("CAPTCHA IMAGE", img, img.format, img.mode) - if img.format in ("GIF", "JPEG"): - img.save(output, img.format) - else: - if img.mode != "RGB": - img = img.convert("RGB") - img.save(output, "JPEG") - data = output.getvalue() - output.close() - except Exception, e: - raise CaptchaBrotherhoodException("Reading or converting captcha image failed: %s" % e) - - req = getRequest() - - url = "%ssendNewCaptcha.aspx?%s" % (self.API_URL, - urllib.urlencode({'username' : self.getConfig('username'), - 'password' : self.getConfig('passkey'), - 'captchaSource': "pyLoad", - 'timeout' : "80"})) - - req.c.setopt(pycurl.URL, url) - req.c.setopt(pycurl.POST, 1) - req.c.setopt(pycurl.POSTFIELDS, data) - req.c.setopt(pycurl.HTTPHEADER, ["Content-Type: text/html"]) - - try: - req.c.perform() - res = req.getResponse() - except Exception, e: - raise CaptchaBrotherhoodException("Submit captcha image failed") - - req.close() - - if not res.startswith("OK"): - raise CaptchaBrotherhoodException(res[1]) - - ticket = res[3:] - - for _i in xrange(15): - time.sleep(5) - res = self.api_response("askCaptchaResult", ticket) - if res.startswith("OK-answered"): - return ticket, res[12:] - - raise CaptchaBrotherhoodException("No solution received in time") - - - def api_response(self, api, ticket): - res = getURL("%s%s.aspx" % (self.API_URL, api), - get={"username": self.getConfig('username'), - "password": self.getConfig('passkey'), - "captchaID": ticket}) - if not res.startswith("OK"): - raise CaptchaBrotherhoodException("Unknown response: %s" % res) - - return res - - - def newCaptchaTask(self, task): - if "service" in task.data: - return False - - if not task.isTextual(): - return False - - if not self.getConfig('username') or not self.getConfig('passkey'): - return False - - if self.core.isClientConnected() and not self.getConfig('force'): - return False - - if self.getCredits() > 10: - task.handler.append(self) - task.data['service'] = self.__name__ - task.setWaiting(100) - self._processCaptcha(task) - else: - self.logInfo(_("Your CaptchaBrotherhood Account has not enough credits")) - - - def captchaInvalid(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: - res = self.api_response("complainCaptcha", task.data['ticket']) - - - @threaded - def _processCaptcha(self, task): - c = task.captchaFile - try: - ticket, result = self.submit(c) - except CaptchaBrotherhoodException, e: - task.error = e.getCode() - return - - task.data['ticket'] = ticket - task.setResult(result) diff --git a/module/plugins/hooks/Checksum.py b/module/plugins/hooks/Checksum.py deleted file mode 100644 index ab7daf701..000000000 --- a/module/plugins/hooks/Checksum.py +++ /dev/null @@ -1,196 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import hashlib -import os -import re -import zlib - -from module.plugins.Hook import Hook -from module.utils import save_join, fs_encode - - -def computeChecksum(local_file, algorithm): - if algorithm in getattr(hashlib, "algorithms", ("md5", "sha1", "sha224", "sha256", "sha384", "sha512")): - h = getattr(hashlib, algorithm)() - - with open(local_file, 'rb') as f: - for chunk in iter(lambda: f.read(128 * h.block_size), ''): - h.update(chunk) - - return h.hexdigest() - - elif algorithm in ("adler32", "crc32"): - hf = getattr(zlib, algorithm) - last = 0 - - with open(local_file, 'rb') as f: - for chunk in iter(lambda: f.read(8192), ''): - last = hf(chunk, last) - - return "%x" % last - - else: - return None - - -class Checksum(Hook): - __name__ = "Checksum" - __type__ = "hook" - __version__ = "0.16" - - __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""" - __license__ = "GPLv3" - __authors__ = [("zoidberg" , "zoidberg@mujmail.cz"), - ("Walter Purcaro", "vuolter@gmail.com" ), - ("stickell" , "l.stickell@yahoo.it")] - - - interval = 0 #@TODO: Remove in 0.4.10 - methods = {'sfv' : 'crc32', - 'crc' : 'crc32', - 'hash': 'md5'} - regexps = {'sfv' : r'^(?P<NAME>[^;].+)\s+(?P<HASH>[0-9A-Fa-f]{8})$', - 'md5' : r'^(?P<NAME>[0-9A-Fa-f]{32}) (?P<FILE>.+)$', - 'crc' : r'filename=(?P<NAME>.+)\nsize=(?P<SIZE>\d+)\ncrc32=(?P<HASH>[0-9A-Fa-f]{8})$', - 'default': r'^(?P<HASH>[0-9A-Fa-f]+)\s+\*?(?P<NAME>.+)$'} - - - def coreReady(self): - if not self.getConfig('check_checksum'): - self.logInfo(_("Checksum validation is disabled in plugin configuration")) - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - 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. - pyfile.plugin.check_data should be a dictionary which can contain: - a) if known, the exact filesize in bytes (e.g. "size": 123456789) - b) hexadecimal hash string with algorithm name as key (e.g. "md5": "d76505d0869f9f928a17d42d66326307") - """ - if hasattr(pyfile.plugin, "check_data") and isinstance(pyfile.plugin.check_data, dict): - data = pyfile.plugin.check_data.copy() - - elif hasattr(pyfile.plugin, "api_data") and isinstance(pyfile.plugin.api_data, dict): - data = pyfile.plugin.api_data.copy() - - elif hasattr(pyfile.plugin, "info") and isinstance(pyfile.plugin.info, dict): - data = pyfile.plugin.info.copy() - data.pop('size', None) #@NOTE: Don't check file size until a similary matcher will be implemented - - else: - return - - self.logDebug(data) - - if not pyfile.plugin.lastDownload: - self.checkFailed(pyfile, None, "No file downloaded") - - local_file = fs_encode(pyfile.plugin.lastDownload) - #download_folder = self.config['general']['download_folder'] - #local_file = fs_encode(save_join(download_folder, pyfile.package().folder, pyfile.name)) - - if not os.path.isfile(local_file): - self.checkFailed(pyfile, None, "File does not exist") - - # validate file size - if "size" in data: - api_size = int(data['size']) - file_size = os.path.getsize(local_file) - - if api_size != file_size: - self.logWarning(_("File %s has incorrect size: %d B (%d expected)") % (pyfile.name, file_size, api_size)) - self.checkFailed(pyfile, local_file, "Incorrect file size") - - data.pop('size', None) - - # validate checksum - if data and self.getConfig('check_checksum'): - - if not 'md5' in data: - for type in ("checksum", "hashsum", "hash"): - if type in data: - data['md5'] = data[type] #@NOTE: What happens if it's not an md5 hash? - break - - for key in self.algorithms: - if key in data: - 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)') % - (pyfile.name, key.upper(), checksum)) - break - else: - self.logWarning(_("%s checksum for file %s does not match (%s != %s)") % - (key.upper(), pyfile.name, checksum, data[key])) - self.checkFailed(pyfile, local_file, "Checksums do not match") - else: - self.logWarning(_("Unsupported hashing algorithm"), key.upper()) - else: - self.logWarning(_("Unable to validate checksum for file: ") + pyfile.name) - - - def checkFailed(self, pyfile, local_file, msg): - check_action = self.getConfig('check_action') - if check_action == "retry": - max_tries = self.getConfig('max_tries') - retry_action = self.getConfig('retry_action') - if pyfile.plugin.retries < max_tries: - if local_file: - os.remove(local_file) - 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 = save_join(self.config['general']['download_folder'], pypack.folder, "") - - for link in pypack.getChildren().itervalues(): - file_type = os.path.splitext(link['name'])[1][1:].lower() - - if file_type not in self.formats: - continue - - hash_file = fs_encode(save_join(download_folder, link['name'])) - if not os.path.isfile(hash_file): - self.logWarning(_("File not found"), link['name']) - continue - - with open(hash_file) as f: - text = f.read() - - for m in re.finditer(self.regexps.get(file_type, self.regexps['default']), text): - data = m.groupdict() - self.logDebug(link['name'], data) - - local_file = fs_encode(save_join(download_folder, data['NAME'])) - 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)') % - (data['NAME'], algorithm, checksum)) - else: - self.logWarning(_("%s checksum for file %s does not match (%s != %s)") % - (algorithm, data['NAME'], checksum, data['HASH'])) diff --git a/module/plugins/hooks/ClickAndLoad.py b/module/plugins/hooks/ClickAndLoad.py deleted file mode 100644 index a7862045e..000000000 --- a/module/plugins/hooks/ClickAndLoad.py +++ /dev/null @@ -1,114 +0,0 @@ -# -*- coding: utf-8 -*- - -import socket -import time - -try: - import ssl -except ImportError: - pass - -from threading import Lock - -from module.plugins.Hook import Hook, threaded - - -def forward(source, destination): - try: - bufsize = 1024 - bufdata = source.recv(bufsize) - while bufdata: - destination.sendall(bufdata) - bufdata = source.recv(bufsize) - finally: - destination.shutdown(socket.SHUT_WR) - # destination.close() - - -#@TODO: IPv6 support -class ClickAndLoad(Hook): - __name__ = "ClickAndLoad" - __type__ = "hook" - __version__ = "0.43" - - __config__ = [("activated", "bool", "Activated" , True), - ("port" , "int" , "Port" , 9666), - ("extern" , "bool", "Listen on the public network interface", True)] - - __description__ = """Click'n'Load hook plugin""" - __license__ = "GPLv3" - __authors__ = [("RaNaN" , "RaNaN@pyload.de" ), - ("Walter Purcaro", "vuolter@gmail.com")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def coreReady(self): - if not self.config['webinterface']['activated']: - return - - ip = "" if self.getConfig('extern') else "127.0.0.1" - webport = self.config['webinterface']['port'] - cnlport = self.getConfig('port') - - self.proxy(ip, webport, cnlport) - - - @threaded - def proxy(self, ip, webport, cnlport): - time.sleep(10) #@TODO: Remove in 0.4.10 (implement addon delay on startup) - - self.logInfo(_("Proxy listening on %s:%s") % (ip or "0.0.0.0", cnlport)) - - self._server(ip, webport, cnlport) - - lock = Lock() - lock.acquire() - lock.acquire() - - - @threaded - def _server(self, ip, webport, cnlport): - try: - dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - dock_socket.bind((ip, cnlport)) - dock_socket.listen(5) - - while True: - client_socket, client_addr = dock_socket.accept() - self.logDebug("Connection from %s:%s" % client_addr) - - server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - if self.config['webinterface']['https']: - try: - server_socket = ssl.wrap_socket(server_socket) - - except NameError: - self.logError(_("pyLoad's webinterface is configured to use HTTPS, Please install python's ssl lib or disable HTTPS")) - client_socket.close() #: reset the connection. - continue - - except Exception, e: - self.logError(_("SSL error: %s") % e.message) - client_socket.close() #: reset the connection. - continue - - server_socket.connect(("127.0.0.1", webport)) - - self.manager.startThread(forward, client_socket, server_socket) - self.manager.startThread(forward, server_socket, client_socket) - - except socket.timeout: - self.logDebug("Connection timed out, retrying...") - return self._server(ip, webport, cnlport) - - except socket.error, e: - self.logError(e) - time.sleep(240) - return self._server(ip, webport, cnlport) diff --git a/module/plugins/hooks/DeathByCaptcha.py b/module/plugins/hooks/DeathByCaptcha.py deleted file mode 100644 index f9618f011..000000000 --- a/module/plugins/hooks/DeathByCaptcha.py +++ /dev/null @@ -1,220 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import pycurl -import re -import time - -from base64 import b64encode - -from module.common.json_layer import json_loads -from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getRequest -from module.plugins.Hook import Hook, threaded - - -class DeathByCaptchaException(Exception): - DBC_ERRORS = {'not-logged-in': 'Access denied, check your credentials', - 'invalid-credentials': 'Access denied, check your credentials', - 'banned': 'Access denied, account is suspended', - 'insufficient-funds': 'Insufficient account balance to decrypt CAPTCHA', - 'invalid-captcha': 'CAPTCHA is not a valid image', - 'service-overload': 'CAPTCHA was rejected due to service overload, try again later', - 'invalid-request': 'Invalid request', - 'timed-out': 'No CAPTCHA solution received in time'} - - - def __init__(self, err): - self.err = err - - - def getCode(self): - return self.err - - - def getDesc(self): - if self.err in self.DBC_ERRORS.keys(): - return self.DBC_ERRORS[self.err] - else: - return self.err - - - def __str__(self): - return "<DeathByCaptchaException %s>" % self.err - - - def __repr__(self): - return "<DeathByCaptchaException %s>" % self.err - - -class DeathByCaptcha(Hook): - __name__ = "DeathByCaptcha" - __type__ = "hook" - __version__ = "0.06" - - __config__ = [("username", "str", "Username", ""), - ("passkey", "password", "Password", ""), - ("force", "bool", "Force DBC even if client is connected", False)] - - __description__ = """Send captchas to DeathByCaptcha.com""" - __license__ = "GPLv3" - __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), - ("zoidberg", "zoidberg@mujmail.cz")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - API_URL = "http://api.dbcapi.me/api/" - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def api_response(self, api="captcha", post=False, multipart=False): - req = getRequest() - req.c.setopt(pycurl.HTTPHEADER, ["Accept: application/json", "User-Agent: pyLoad %s" % self.core.version]) - - if post: - if not isinstance(post, dict): - post = {} - post.update({"username": self.getConfig('username'), - "password": self.getConfig('passkey')}) - - res = None - try: - json = req.load("%s%s" % (self.API_URL, api), - post=post, - multipart=multipart) - self.logDebug(json) - res = json_loads(json) - - if "error" in res: - raise DeathByCaptchaException(res['error']) - elif "status" not in res: - raise DeathByCaptchaException(str(res)) - - except BadHeader, e: - if 403 == e.code: - raise DeathByCaptchaException('not-logged-in') - elif 413 == e.code: - raise DeathByCaptchaException('invalid-captcha') - elif 503 == e.code: - raise DeathByCaptchaException('service-overload') - elif e.code in (400, 405): - raise DeathByCaptchaException('invalid-request') - else: - raise - - finally: - req.close() - - return res - - - def getCredits(self): - res = self.api_response("user", True) - - if 'is_banned' in res and res['is_banned']: - raise DeathByCaptchaException('banned') - elif 'balance' in res and 'rate' in res: - self.info.update(res) - else: - raise DeathByCaptchaException(res) - - - def getStatus(self): - res = self.api_response("status", False) - - if 'is_service_overloaded' in res and res['is_service_overloaded']: - raise DeathByCaptchaException('service-overload') - - - def submit(self, captcha, captchaType="file", match=None): - #@NOTE: Workaround multipart-post bug in HTTPRequest.py - if re.match("^\w*$", self.getConfig('passkey')): - multipart = True - data = (pycurl.FORM_FILE, captcha) - else: - multipart = False - with open(captcha, 'rb') as f: - data = f.read() - data = "base64:" + b64encode(data) - - res = self.api_response("captcha", {"captchafile": data}, multipart) - - if "captcha" not in res: - raise DeathByCaptchaException(res) - ticket = res['captcha'] - - for _i in xrange(24): - time.sleep(5) - res = self.api_response("captcha/%d" % ticket, False) - if res['text'] and res['is_correct']: - break - else: - raise DeathByCaptchaException('timed-out') - - result = res['text'] - self.logDebug("Result %s : %s" % (ticket, result)) - - return ticket, result - - - def newCaptchaTask(self, task): - if "service" in task.data: - return False - - if not task.isTextual(): - return False - - if not self.getConfig('username') or not self.getConfig('passkey'): - return False - - if self.core.isClientConnected() and not self.getConfig('force'): - return False - - try: - self.getStatus() - self.getCredits() - except DeathByCaptchaException, e: - self.logError(e.getDesc()) - return False - - balance, rate = self.info['balance'], self.info['rate'] - self.logInfo(_("Account balance"), - _("US$%.3f (%d captchas left at %.2f cents each)") % (balance / 100, - balance // rate, rate)) - - if balance > rate: - task.handler.append(self) - task.data['service'] = self.__name__ - task.setWaiting(180) - self._processCaptcha(task) - - - def captchaInvalid(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: - try: - res = self.api_response("captcha/%d/report" % task.data['ticket'], True) - - except DeathByCaptchaException, e: - self.logError(e.getDesc()) - - except Exception, e: - self.logError(e) - - - @threaded - def _processCaptcha(self, task): - c = task.captchaFile - try: - ticket, result = self.submit(c) - except DeathByCaptchaException, e: - task.error = e.getCode() - self.logError(e.getDesc()) - return - - task.data['ticket'] = ticket - task.setResult(result) diff --git a/module/plugins/hooks/DebridItaliaComHook.py b/module/plugins/hooks/DebridItaliaComHook.py deleted file mode 100644 index 36b307696..000000000 --- a/module/plugins/hooks/DebridItaliaComHook.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.internal.MultiHook import MultiHook - - -class DebridItaliaComHook(MultiHook): - __name__ = "DebridItaliaComHook" - __type__ = "hook" - __version__ = "0.12" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Debriditalia.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("stickell" , "l.stickell@yahoo.it"), - ("Walter Purcaro", "vuolter@gmail.com" )] - - - def getHosters(self): - return self.getURL("http://debriditalia.com/api.php", get={'hosts': ""}).replace('"', '').split(',') diff --git a/module/plugins/hooks/DeleteFinished.py b/module/plugins/hooks/DeleteFinished.py deleted file mode 100644 index bde4ca259..000000000 --- a/module/plugins/hooks/DeleteFinished.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.database import style -from module.plugins.Hook import Hook - - -class DeleteFinished(Hook): - __name__ = "DeleteFinished" - __type__ = "hook" - __version__ = "1.12" - - __config__ = [("interval" , "int" , "Check interval in hours" , 72 ), - ("deloffline", "bool", "Delete package with offline links", False)] - - __description__ = """Automatically delete all finished packages from queue""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - # event_list = ["pluginConfigChanged"] - - MIN_CHECK_INTERVAL = 1 * 60 * 60 #: 1 hour - - - ## overwritten methods ## - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.interval = self.MIN_CHECK_INTERVAL - - - def periodical(self): - if not self.info['sleep']: - deloffline = self.getConfig('deloffline') - mode = '0,1,4' if deloffline else '0,4' - msg = _('delete all finished packages in queue list (%s packages with offline links)') - self.logInfo(msg % (_('including') if deloffline else _('excluding'))) - self.deleteFinished(mode) - self.info['sleep'] = True - self.addEvent('packageFinished', self.wakeup) - - - # def pluginConfigChanged(self, plugin, name, value): - # if name == "interval" and value != self.interval: - # self.interval = value * 3600 - # self.initPeriodical() - - - def unload(self): - self.manager.removeEvent('packageFinished', self.wakeup) - - - def coreReady(self): - self.info['sleep'] = True - # interval = self.getConfig('interval') - # self.pluginConfigChanged(self.__name__, 'interval', interval) - self.interval = max(self.MIN_CHECK_INTERVAL, self.getConfig('interval') * 60 * 60) - 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.manager.removeEvent('packageFinished', self.wakeup) - self.info['sleep'] = False - - - ## event managing ## - def addEvent(self, event, func): - """Adds an event listener for event name""" - if event in self.manager.events: - if func in self.manager.events[event]: - self.logDebug("Function already registered", func) - else: - self.manager.events[event].append(func) - else: - self.manager.events[event] = [func] diff --git a/module/plugins/hooks/DownloadScheduler.py b/module/plugins/hooks/DownloadScheduler.py deleted file mode 100644 index 9c74ac1d4..000000000 --- a/module/plugins/hooks/DownloadScheduler.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -import time - -from module.plugins.Hook import Hook - - -class DownloadScheduler(Hook): - __name__ = "DownloadScheduler" - __type__ = "hook" - __version__ = "0.22" - - __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""" - __license__ = "GPLv3" - __authors__ = [("zoidberg", "zoidberg@mujmail.cz"), - ("stickell", "l.stickell@yahoo.it")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.cb = None # callback to scheduler job; will be by removed hookmanager when hook unloaded - - - def coreReady(self): - self.updateSchedule() - - - def updateSchedule(self, schedule=None): - if schedule is None: - schedule = self.getConfig('timetable') - - schedule = re.findall("(\d{1,2}):(\d{2})[\s]*(-?\d+)", - schedule.lower().replace("full", "-1").replace("none", "0")) - if not schedule: - self.logError(_("Invalid schedule")) - return - - t0 = time.localtime() - now = (t0.tm_hour, t0.tm_min, t0.tm_sec, "X") - schedule = sorted([(int(x[0]), int(x[1]), 0, int(x[2])) for x in schedule] + [now]) - - self.logDebug("Schedule", schedule) - - for i, v in enumerate(schedule): - if v[3] == "X": - last, next = schedule[i - 1], schedule[(i + 1) % len(schedule)] - self.logDebug("Now/Last/Next", now, last, next) - - self.setDownloadSpeed(last[3]) - - next_time = (((24 + next[0] - now[0]) * 60 + next[1] - now[1]) * 60 + next[2] - now[2]) % 86400 - 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') - self.logInfo(_("Stopping download server. (Running downloads will %sbe aborted.)") % '' if abort else _('not ')) - self.core.api.pauseServer() - if abort: - self.core.api.stopAllDownloads() - else: - self.core.api.unpauseServer() - - if speed > 0: - self.logInfo(_("Setting download speed to %d kB/s") % speed) - self.core.api.setConfigValue("download", "limit_speed", 1) - self.core.api.setConfigValue("download", "max_speed", speed) - else: - self.logInfo(_("Setting download speed to FULL")) - self.core.api.setConfigValue("download", "limit_speed", 0) - self.core.api.setConfigValue("download", "max_speed", -1) diff --git a/module/plugins/hooks/EasybytezComHook.py b/module/plugins/hooks/EasybytezComHook.py deleted file mode 100644 index 43efb5048..000000000 --- a/module/plugins/hooks/EasybytezComHook.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.internal.MultiHook import MultiHook - - -class EasybytezComHook(MultiHook): - __name__ = "EasybytezComHook" - __type__ = "hook" - __version__ = "0.07" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """EasyBytez.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - - - def getHosters(self): - user, data = self.account.selectAccount() - - req = self.account.getAccountRequest(user) - html = req.load("http://www.easybytez.com") - - return re.search(r'</textarea>\s*Supported sites:(.*)', html).group(1).split(',') diff --git a/module/plugins/hooks/ExpertDecoders.py b/module/plugins/hooks/ExpertDecoders.py deleted file mode 100644 index ccd48f664..000000000 --- a/module/plugins/hooks/ExpertDecoders.py +++ /dev/null @@ -1,103 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import pycurl -import uuid - -from base64 import b64encode - -from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getURL, getRequest -from module.plugins.Hook import Hook, threaded - - -class ExpertDecoders(Hook): - __name__ = "ExpertDecoders" - __type__ = "hook" - __version__ = "0.04" - - __config__ = [("force", "bool", "Force CT even if client is connected", False), - ("passkey", "password", "Access key", "")] - - __description__ = """Send captchas to expertdecoders.com""" - __license__ = "GPLv3" - __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), - ("zoidberg", "zoidberg@mujmail.cz")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - API_URL = "http://www.fasttypers.org/imagepost.ashx" - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def getCredits(self): - res = getURL(self.API_URL, post={"key": self.getConfig('passkey'), "action": "balance"}) - - if res.isdigit(): - self.logInfo(_("%s credits left") % res) - self.info['credits'] = credits = int(res) - return credits - else: - self.logError(res) - return 0 - - - @threaded - def _processCaptcha(self, task): - task.data['ticket'] = ticket = uuid.uuid4() - result = None - - with open(task.captchaFile, 'rb') as f: - data = f.read() - - req = getRequest() - #raise timeout threshold - req.c.setopt(pycurl.LOW_SPEED_TIME, 80) - - try: - result = req.load(self.API_URL, - post={'action' : "upload", - 'key' : self.getConfig('passkey'), - 'file' : b64encode(data), - 'gen_task_id': ticket}) - finally: - req.close() - - self.logDebug("Result %s : %s" % (ticket, result)) - task.setResult(result) - - - def newCaptchaTask(self, task): - if not task.isTextual(): - return False - - if not self.getConfig('passkey'): - return False - - if self.core.isClientConnected() and not self.getConfig('force'): - return False - - if self.getCredits() > 0: - task.handler.append(self) - task.setWaiting(100) - self._processCaptcha(task) - - else: - self.logInfo(_("Your ExpertDecoders Account has not enough credits")) - - - def captchaInvalid(self, task): - if "ticket" in task.data: - - try: - res = getURL(self.API_URL, - post={'action': "refund", 'key': self.getConfig('passkey'), 'gen_task_id': task.data['ticket']}) - self.logInfo(_("Request refund"), res) - - except BadHeader, e: - self.logError(_("Could not send refund request"), e) diff --git a/module/plugins/hooks/ExternalScripts.py b/module/plugins/hooks/ExternalScripts.py deleted file mode 100644 index be0857009..000000000 --- a/module/plugins/hooks/ExternalScripts.py +++ /dev/null @@ -1,217 +0,0 @@ -# -*- coding: utf-8 -*- - -import os -import subprocess - -from module.plugins.Hook import Hook -from module.utils import fs_encode, save_join - - -class ExternalScripts(Hook): - __name__ = "ExternalScripts" - __type__ = "hook" - __version__ = "0.39" - - __config__ = [("activated", "bool", "Activated" , True ), - ("waitend" , "bool", "Wait script ending", False)] - - __description__ = """Run external scripts""" - __license__ = "GPLv3" - __authors__ = [("mkaay" , "mkaay@mkaay.de" ), - ("RaNaN" , "ranan@pyload.org" ), - ("spoob" , "spoob@pyload.org" ), - ("Walter Purcaro", "vuolter@gmail.com")] - - - event_list = ["archive_extract_failed", "archive_extracted" , - "package_extract_failed", "package_extracted" , - "all_archives_extracted", "all_archives_processed", - "allDownloadsFinished" , "allDownloadsProcessed" , - "packageDeleted"] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {'oldip': None} - self.scripts = {} - - folders = ["pyload_start", "pyload_restart", "pyload_stop", - "before_reconnect", "after_reconnect", - "download_preparing", "download_failed", "download_finished", - "archive_extract_failed", "archive_extracted", - "package_finished", "package_deleted", "package_extract_failed", "package_extracted", - "all_downloads_processed", "all_downloads_finished", #@TODO: Invert `all_downloads_processed`, `all_downloads_finished` order in 0.4.10 - "all_archives_extracted", "all_archives_processed"] - - for folder in folders: - self.scripts[folder] = [] - for dir in (pypath, ''): - self.initPluginType(folder, os.path.join(dir, 'scripts', folder)) - - for script_type, names in self.scripts.iteritems(): - if names: - self.logInfo(_("Installed scripts for: ") + script_type, ", ".join(map(os.path.basename, names))) - - self.pyload_start() - - - def initPluginType(self, name, dir): - if not os.path.isdir(dir): - try: - os.makedirs(dir) - - except OSError, e: - self.logDebug(e) - return - - for filename in os.listdir(dir): - file = save_join(dir, filename) - - if not os.path.isfile(file): - continue - - if filename[0] in ("#", "_") or filename.endswith("~") or filename.endswith(".swp"): - continue - - if not os.access(file, os.X_OK): - self.logWarning(_("Script not executable:") + " %s/%s" % (name, filename)) - - self.scripts[name].append(file) - - - def callScript(self, script, *args): - try: - cmd_args = [fs_encode(str(x) if not isinstance(x, basestring) else x) for x in args] - cmd = [script] + cmd_args - - self.logDebug("Executing: %s" % os.path.abspath(script), "Args: " + ' '.join(cmd_args)) - - p = subprocess.Popen(cmd, bufsize=-1) #@NOTE: output goes to pyload - if self.getConfig('waitend'): - p.communicate() - - except Exception, e: - try: - self.logError(_("Runtime error: %s") % os.path.abspath(script), e) - except Exception: - self.logError(_("Runtime error: %s") % os.path.abspath(script), _("Unknown error")) - - - def pyload_start(self): - for script in self.scripts['pyload_start']: - self.callScript(script) - - - def coreExiting(self): - for script in self.scripts['pyload_restart' if self.core.do_restart else 'pyload_stop']: - self.callScript(script) - - - def beforeReconnecting(self, ip): - for script in self.scripts['before_reconnect']: - self.callScript(script, ip) - self.info['oldip'] = ip - - - def afterReconnecting(self, ip): - for script in self.scripts['after_reconnect']: - self.callScript(script, ip, self.info['oldip']) #@TODO: Use built-in oldip in 0.4.10 - - - def downloadPreparing(self, pyfile): - for script in self.scripts['download_preparing']: - self.callScript(script, pyfile.id, pyfile.name, None, pyfile.pluginname, pyfile.url) - - - def downloadFailed(self, pyfile): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pyfile.package().folder) - else: - download_folder = self.config['general']['download_folder'] - - for script in self.scripts['download_failed']: - file = save_join(download_folder, pyfile.name) - self.callScript(script, pyfile.id, pyfile.name, file, pyfile.pluginname, pyfile.url) - - - def downloadFinished(self, pyfile): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pyfile.package().folder) - else: - download_folder = self.config['general']['download_folder'] - - for script in self.scripts['download_finished']: - file = save_join(download_folder, pyfile.name) - self.callScript(script, pyfile.id, pyfile.name, file, pyfile.pluginname, pyfile.url) - - - def archive_extract_failed(self, pyfile, archive): - for script in self.scripts['archive_extract_failed']: - self.callScript(script, pyfile.id, pyfile.name, archive.filename, archive.out, archive.files) - - - def archive_extracted(self, pyfile, archive): - for script in self.scripts['archive_extracted']: - self.callScript(script, pyfile.id, pyfile.name, archive.filename, archive.out, archive.files) - - - def packageFinished(self, pypack): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pypack.folder) - else: - download_folder = self.config['general']['download_folder'] - - for script in self.scripts['package_finished']: - self.callScript(script, pypack.id, pypack.name, download_folder, pypack.password) - - - def packageDeleted(self, pid): - pack = self.core.api.getPackageInfo(pid) - - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pack.folder) - else: - download_folder = self.config['general']['download_folder'] - - for script in self.scripts['package_deleted']: - self.callScript(script, pack.id, pack.name, download_folder, pack.password) - - - def package_extract_failed(self, pypack): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pypack.folder) - else: - download_folder = self.config['general']['download_folder'] - - for script in self.scripts['package_extract_failed']: - self.callScript(script, pypack.id, pypack.name, download_folder, pypack.password) - - - def package_extracted(self, pypack): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pypack.folder) - else: - download_folder = self.config['general']['download_folder'] - - for script in self.scripts['package_extracted']: - self.callScript(script, pypack.id, pypack.name, download_folder) - - - def allDownloadsFinished(self): - for script in self.scripts['all_downloads_finished']: - self.callScript(script) - - - def allDownloadsProcessed(self): - for script in self.scripts['all_downloads_processed']: - self.callScript(script) - - - 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) diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py deleted file mode 100644 index 5b9e3f30b..000000000 --- a/module/plugins/hooks/ExtractArchive.py +++ /dev/null @@ -1,571 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import os -import sys -import traceback - -# monkey patch bug in python 2.6 and lower -# http://bugs.python.org/issue6122 , http://bugs.python.org/issue1236 , http://bugs.python.org/issue1731717 -if sys.version_info < (2, 7) and os.name != "nt": - import errno - import subprocess - - def _eintr_retry_call(func, *args): - while True: - try: - return func(*args) - - except OSError, e: - if e.errno == errno.EINTR: - continue - raise - - - # unsued timeout option for older python version - def wait(self, timeout=0): - """Wait for child process to terminate. Returns returncode - attribute.""" - if self.returncode is None: - try: - pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0) - - except OSError, e: - if e.errno != errno.ECHILD: - raise - # This happens if SIGCLD is set to be ignored or waiting - # for child processes has otherwise been disabled for our - # process. This child is dead, we can't get the status. - sts = 0 - self._handle_exitstatus(sts) - return self.returncode - - subprocess.Popen.wait = wait - -try: - import send2trash -except ImportError: - pass - -from copy import copy -if os.name != "nt": - from grp import getgrnam - from pwd import getpwnam - -from module.plugins.Hook import Hook, Expose, threaded -from module.plugins.internal.Extractor import ArchiveError, CRCError, PasswordError -from module.plugins.internal.SimpleHoster import replace_patterns -from module.utils import fs_encode, save_join, uniqify - - -class ArchiveQueue(object): - - def __init__(self, plugin, storage): - self.plugin = plugin - self.storage = storage - - - def get(self): - try: - return [int(pid) for pid in self.plugin.getStorage("ExtractArchive:%s" % self.storage, "").decode('base64').split()] - except Exception: - return [] - - - def set(self, value): - if isinstance(value, list): - item = str(value)[1:-1].replace(' ', '').replace(',', ' ') - else: - item = str(value).strip() - return self.plugin.setStorage("ExtractArchive:%s" % self.storage, item.encode('base64')[:-1]) - - - def delete(self): - return self.plugin.delStorage("ExtractArchive:%s" % self.storage) - - - def add(self, item): - queue = self.get() - if item not in queue: - return self.set(queue + [item]) - else: - return True - - - def remove(self, item): - queue = self.get() - try: - queue.remove(item) - - except ValueError: - pass - - if queue == []: - return self.delete() - - return self.set(queue) - - -class ExtractArchive(Hook): - __name__ = "ExtractArchive" - __type__ = "hook" - __version__ = "1.44" - - __config__ = [("activated" , "bool" , "Activated" , True ), - ("fullpath" , "bool" , "Extract with full paths" , True ), - ("overwrite" , "bool" , "Overwrite files" , False ), - ("keepbroken" , "bool" , "Try to extract broken archives" , False ), - ("repair" , "bool" , "Repair broken archives (RAR required)" , False ), - ("test" , "bool" , "Test archive before extracting" , False ), - ("usepasswordfile", "bool" , "Use password file" , True ), - ("passwordfile" , "file" , "Password file" , "archive_password.txt" ), - ("delete" , "bool" , "Delete archive after extraction" , True ), - ("deltotrash" , "bool" , "Move to trash (recycle bin) instead delete", True ), - ("subfolder" , "bool" , "Create subfolder for each package" , False ), - ("destination" , "folder" , "Extract files to folder" , "" ), - ("extensions" , "str" , "Extract archives ending with extension" , "7z,bz2,bzip2,gz,gzip,lha,lzh,lzma,rar,tar,taz,tbz,tbz2,tgz,xar,xz,z,zip"), - ("excludefiles" , "str" , "Don't extract the following files" , "*.nfo,*.DS_Store,index.dat,thumb.db" ), - ("recursive" , "bool" , "Extract archives in archives" , True ), - ("waitall" , "bool" , "Run after all downloads was processed" , False ), - ("renice" , "int" , "CPU priority" , 0 )] - - __description__ = """Extract different kind of archives""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com"), - ("Immenz" , "immenz@gmx.net" )] - - - event_list = ["allDownloadsProcessed","packageDeleted"] - - NAME_REPLACEMENTS = [(r'\.part\d+\.rar$', ".part.rar")] - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - self.queue = ArchiveQueue(self, "Queue") - self.failed = ArchiveQueue(self, "Failed") - - self.interval = 60 - self.extracting = False - self.lastPackage = False - self.extractors = [] - self.passwords = [] - self.repair = False - - - def coreReady(self): - for p in ("UnRar", "SevenZip", "UnZip"): - try: - module = self.core.pluginManager.loadModule("internal", p) - klass = getattr(module, p) - if klass.isUsable(): - self.extractors.append(klass) - if klass.REPAIR: - self.repair = self.getConfig('repair') - - except OSError, e: - if e.errno == 2: - self.logWarning(_("No %s installed") % p) - else: - self.logWarning(_("Could not activate: %s") % p, e) - if self.core.debug: - traceback.print_exc() - - except Exception, e: - self.logWarning(_("Could not activate: %s") % p, e) - if self.core.debug: - traceback.print_exc() - - if self.extractors: - self.logDebug(*["Found %s %s" % (Extractor.__name__, Extractor.VERSION) for Extractor in self.extractors]) - self.extractQueued() #: Resume unfinished extractions - else: - self.logInfo(_("No Extract plugins activated")) - - - @threaded - def extractQueued(self, thread): - if self.extracting: #@NOTE: doing the check here for safty (called by coreReady) - return - - self.extracting = True - - packages = self.queue.get() - while packages: - if self.lastPackage: #: called from allDownloadsProcessed - self.lastPackage = False - if self.extract(packages, thread): #@NOTE: check only if all gone fine, no failed reporting for now - self.manager.dispatchEvent("all_archives_extracted") - self.manager.dispatchEvent("all_archives_processed") - else: - if self.extract(packages, thread): #@NOTE: check only if all gone fine, no failed reporting for now - pass - - packages = self.queue.get() #: check for packages added during extraction - - self.extracting = False - - - @Expose - def extractPackage(self, *ids): - """ Extract packages with given id""" - for id in ids: - self.queue.add(id) - if not self.getConfig('waitall') and not self.extracting: - self.extractQueued() - - - def packageDeleted(self, pid): - self.queue.remove(pid) - - - def packageFinished(self, pypack): - self.queue.add(pypack.id) - if not self.getConfig('waitall') and not self.extracting: - self.extractQueued() - - - def allDownloadsProcessed(self): - self.lastPackage = True - if self.getConfig('waitall') and not self.extracting: - self.extractQueued() - - - @Expose - def extract(self, ids, thread=None): #@TODO: Use pypack, not pid to improve method usability - if not ids: - return False - - processed = [] - extracted = [] - failed = [] - - toList = lambda string: string.replace(' ', '').replace(',', '|').replace(';', '|').split('|') - - destination = self.getConfig('destination') - subfolder = self.getConfig('subfolder') - fullpath = self.getConfig('fullpath') - overwrite = self.getConfig('overwrite') - renice = self.getConfig('renice') - recursive = self.getConfig('recursive') - delete = self.getConfig('delete') - keepbroken = self.getConfig('keepbroken') - - extensions = [x.lstrip('.').lower() for x in toList(self.getConfig('extensions'))] - excludefiles = toList(self.getConfig('excludefiles')) - - if extensions: - self.logDebug("Use for extensions: %s" % "|.".join(extensions)) - - # reload from txt file - self.reloadPasswords() - - download_folder = self.config['general']['download_folder'] - - # iterate packages -> extractors -> targets - for pid in ids: - pypack = self.core.files.getPackage(pid) - - if not pypack: - self.queue.remove(pid) - continue - - self.logInfo(_("Check package: %s") % pypack.name) - - # determine output folder - out = save_join(download_folder, pypack.folder, destination, "") #: force trailing slash - - if subfolder: - out = save_join(out, pypack.folder) - - if not os.path.exists(out): - os.makedirs(out) - - matched = False - success = True - files_ids = dict((pylink['name'],((save_join(download_folder, pypack.folder, pylink['name'])), pylink['id'], out)) for pylink \ - in sorted(pypack.getChildren().itervalues(), key=lambda k: k['name'])).values() #: remove duplicates - - # check as long there are unseen files - while files_ids: - new_files_ids = [] - - if extensions: - files_ids = [(fname, fid, fout) for fname, fid, fout in files_ids \ - if filter(lambda ext: fname.lower().endswith(ext), extensions)] - - for Extractor in self.extractors: - targets = Extractor.getTargets(files_ids) - if targets: - self.logDebug("Targets for %s: %s" % (Extractor.__name__, targets)) - matched = True - - for fname, fid, fout in targets: - name = os.path.basename(fname) - - if not os.path.exists(fname): - self.logDebug(name, "File not found") - continue - - self.logInfo(name, _("Extract to: %s") % fout) - try: - pyfile = self.core.files.getFile(fid) - archive = Extractor(self, - fname, - fout, - fullpath, - overwrite, - excludefiles, - renice, - delete, - keepbroken, - fid) - - thread.addActive(pyfile) - archive.init() - - try: - new_files = self._extract(pyfile, archive, pypack.password) - - finally: - pyfile.setProgress(100) - thread.finishFile(pyfile) - - except Exception, e: - self.logError(name, e) - success = False - continue - - # remove processed file and related multiparts from list - files_ids = [(fname, fid, fout) for fname, fid, fout in files_ids \ - if fname not in archive.getDeleteFiles()] - self.logDebug("Extracted files: %s" % new_files) - self.setPermissions(new_files) - - for filename in new_files: - file = fs_encode(save_join(os.path.dirname(archive.filename), filename)) - if not os.path.exists(file): - self.logDebug("New file %s does not exists" % filename) - continue - - if recursive and os.path.isfile(file): - new_files_ids.append((filename, fid, os.path.dirname(filename))) #: append as new target - - self.manager.dispatchEvent("archive_extracted", pyfile, archive) - - files_ids = new_files_ids #: also check extracted files - - if matched: - if success: - extracted.append(pid) - self.manager.dispatchEvent("package_extracted", pypack) - - else: - failed.append(pid) - self.manager.dispatchEvent("package_extract_failed", pypack) - - self.failed.add(pid) - else: - self.logInfo(_("No files found to extract")) - - if not matched or not success and subfolder: - try: - os.rmdir(out) - - except OSError: - pass - - self.queue.remove(pid) - - return True if not failed else False - - - def _extract(self, pyfile, archive, password): - name = os.path.basename(archive.filename) - - pyfile.setStatus("processing") - - encrypted = False - try: - self.logDebug("Password: %s" % (password or "None provided")) - passwords = uniqify([password] + self.getPasswords(False)) if self.getConfig('usepasswordfile') else [password] - for pw in passwords: - try: - if self.getConfig('test') or self.repair: - pyfile.setCustomStatus(_("archive testing")) - if pw: - self.logDebug("Testing with password: %s" % pw) - pyfile.setProgress(0) - archive.verify(pw) - pyfile.setProgress(100) - else: - archive.check(pw) - - self.addPassword(pw) - break - - except PasswordError: - if not encrypted: - self.logInfo(name, _("Password protected")) - encrypted = True - - except CRCError, e: - self.logDebug(name, e) - self.logInfo(name, _("CRC Error")) - - if self.repair: - self.logWarning(name, _("Repairing...")) - - pyfile.setCustomStatus(_("archive repairing")) - pyfile.setProgress(0) - repaired = archive.repair() - pyfile.setProgress(100) - - if not repaired and not self.getConfig('keepbroken'): - raise CRCError("Archive damaged") - - self.addPassword(pw) - break - - raise CRCError("Archive damaged") - - except ArchiveError, e: - raise ArchiveError(e) - - pyfile.setCustomStatus(_("extracting")) - pyfile.setProgress(0) - - if not encrypted or not self.getConfig('usepasswordfile'): - self.logDebug("Extracting using password: %s" % (password or "None")) - archive.extract(password) - else: - for pw in filter(None, uniqify([password] + self.getPasswords(False))): - try: - self.logDebug("Extracting using password: %s" % pw) - - archive.extract(pw) - self.addPassword(pw) - break - - except PasswordError: - self.logDebug("Password was wrong") - else: - raise PasswordError - - pyfile.setProgress(100) - pyfile.setStatus("processing") - - delfiles = archive.getDeleteFiles() - self.logDebug("Would delete: " + ", ".join(delfiles)) - - if self.getConfig('delete'): - self.logInfo(_("Deleting %s files") % len(delfiles)) - - deltotrash = self.getConfig('deltotrash') - for f in delfiles: - file = fs_encode(f) - if not os.path.exists(file): - continue - - if not deltotrash: - os.remove(file) - - else: - try: - send2trash.send2trash(file) - - except NameError: - self.logWarning(_("Unable to move %s to trash: Send2Trash lib not found") % os.path.basename(f)) - - except Exception, e: - self.logWarning(_("Unable to move %s to trash: %s") % (os.path.basename(f), e.message)) - - else: - self.logDebug(_("Successfully moved %s to trash") % os.path.basename(f)) - - self.logInfo(name, _("Extracting finished")) - extracted_files = archive.files or archive.list() - - return extracted_files - - except PasswordError: - self.logError(name, _("Wrong password" if password else "No password found")) - - except CRCError, e: - self.logError(name, _("CRC mismatch"), e) - - except ArchiveError, e: - self.logError(name, _("Archive error"), e) - - except Exception, e: - self.logError(name, _("Unknown error"), e) - if self.core.debug: - traceback.print_exc() - - self.manager.dispatchEvent("archive_extract_failed", pyfile, archive) - - raise Exception(_("Extract failed")) - - - @Expose - def getPasswords(self, reload=True): - """ List of saved passwords """ - if reload: - self.reloadPasswords() - - return self.passwords - - - def reloadPasswords(self): - try: - passwords = [] - - file = fs_encode(self.getConfig('passwordfile')) - with open(file) as f: - for pw in f.read().splitlines(): - passwords.append(pw) - - except IOError, e: - self.logError(e) - - else: - self.passwords = passwords - - - @Expose - def addPassword(self, password): - """ Adds a password to saved list""" - try: - self.passwords = uniqify([password] + self.passwords) - - file = fs_encode(self.getConfig('passwordfile')) - with open(file, "wb") as f: - for pw in self.passwords: - f.write(pw + '\n') - - except IOError, e: - self.logError(e) - - - def setPermissions(self, files): - for f in files: - if not os.path.exists(f): - continue - - try: - if self.config['permission']['change_file']: - if os.path.isfile(f): - os.chmod(f, int(self.config['permission']['file'], 8)) - - elif os.path.isdir(f): - os.chmod(f, int(self.config['permission']['folder'], 8)) - - if self.config['permission']['change_dl'] and os.name != "nt": - uid = getpwnam(self.config['permission']['user'])[2] - gid = getgrnam(self.config['permission']['group'])[2] - os.chown(f, uid, gid) - - except Exception, e: - self.logWarning(_("Setting User and Group failed"), e) diff --git a/module/plugins/hooks/FastixRuHook.py b/module/plugins/hooks/FastixRuHook.py deleted file mode 100644 index 16e30e93a..000000000 --- a/module/plugins/hooks/FastixRuHook.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class FastixRuHook(MultiHook): - __name__ = "FastixRuHook" - __type__ = "hook" - __version__ = "0.05" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Fastix.ru hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Massimo Rosamilia", "max@spiritix.eu")] - - - def getHosters(self): - html = self.getURL("http://fastix.ru/api_v2", - get={'apikey': "5182964c3f8f9a7f0b00000a_kelmFB4n1IrnCDYuIFn2y", - 'sub' : "allowed_sources"}) - host_list = json_loads(html) - host_list = host_list['allow'] - return host_list diff --git a/module/plugins/hooks/FreeWayMeHook.py b/module/plugins/hooks/FreeWayMeHook.py deleted file mode 100644 index baea44540..000000000 --- a/module/plugins/hooks/FreeWayMeHook.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class FreeWayMeHook(MultiHook): - __name__ = "FreeWayMeHook" - __type__ = "hook" - __version__ = "0.15" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """FreeWay.me hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Nicolas Giese", "james@free-way.me")] - - - def getHosters(self): - # Get account data - if not self.account or not self.account.canUse(): - hostis = self.getURL("https://www.free-way.me/ajax/jd.php", get={"id": 3}).replace("\"", "").strip() - else: - self.logDebug("AccountInfo available - Get HosterList with User Pass") - (user, data) = self.account.selectAccount() - hostis = self.getURL("https://www.free-way.me/ajax/jd.php", get={"id": 3, "user": user, "pass": data['password']}).replace("\"", "").strip() - - self.logDebug("hosters: %s" % hostis) - return [x.strip() for x in hostis.split(",") if x.strip()] diff --git a/module/plugins/hooks/HotFolder.py b/module/plugins/hooks/HotFolder.py deleted file mode 100644 index f771cf232..000000000 --- a/module/plugins/hooks/HotFolder.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import os -import time - -from shutil import move - -from module.plugins.Hook import Hook -from module.utils import fs_encode, save_join - - -class HotFolder(Hook): - __name__ = "HotFolder" - __type__ = "hook" - __version__ = "0.14" - - __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""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.de")] - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.interval = 30 - - - def periodical(self): - folder = fs_encode(self.getConfig('folder')) - file = fs_encode(self.getConfig('file')) - - try: - if not os.path.isdir(os.path.join(folder, "finished")): - os.makedirs(os.path.join(folder, "finished")) - - if self.getConfig('watch_file'): - with open(file, "a+") as f: - f.seek(0) - content = f.read().strip() - - if content: - f = open(file, "wb") - f.close() - - name = "%s_%s.txt" % (file, time.strftime("%H-%M-%S_%d%b%Y")) - - with open(save_join(folder, "finished", name), "wb") as f: - f.write(content) - - self.core.api.addPackage(f.name, [f.name], 1) - - for f in os.listdir(folder): - path = os.path.join(folder, f) - - if not os.path.isfile(path) or f.endswith("~") or f.startswith("#") or f.startswith("."): - continue - - newpath = os.path.join(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) - - except (IOError, OSError), e: - self.logError(e) diff --git a/module/plugins/hooks/IRCInterface.py b/module/plugins/hooks/IRCInterface.py deleted file mode 100644 index 33fde3d20..000000000 --- a/module/plugins/hooks/IRCInterface.py +++ /dev/null @@ -1,433 +0,0 @@ -# -*- coding: utf-8 -*- - -import pycurl -import re -import socket -import ssl -import time -import traceback - -from select import select -from threading import Thread - -from module.Api import PackageDoesNotExists, FileDoesNotExists -from module.network.RequestFactory import getURL -from module.plugins.Hook import Hook -from module.utils import formatSize - - -class IRCInterface(Thread, Hook): - __name__ = "IRCInterface" - __type__ = "hook" - __version__ = "0.13" - - __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), - ("info_pack", "bool", "Inform about every package finished", True), - ("captcha", "bool", "Send captcha requests", True)] - - __description__ = """Connect to irc and let owner perform different tasks""" - __license__ = "GPLv3" - __authors__ = [("Jeix", "Jeix@hasnomail.com")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - - def __init__(self, core, manager): - Thread.__init__(self) - Hook.__init__(self, core, manager) - self.setDaemon(True) - - - def coreReady(self): - self.abort = False - self.more = [] - self.new_package = {} - - self.start() - - - def packageFinished(self, pypack): - try: - if self.getConfig('info_pack'): - self.response(_("Package finished: %s") % pypack.name) - except Exception: - pass - - - def downloadFinished(self, pyfile): - try: - if self.getConfig('info_file'): - self.response( - _("Download finished: %(name)s @ %(plugin)s ") % {"name": pyfile.name, "plugin": pyfile.pluginname}) - except Exception: - pass - - - def newCaptchaTask(self, task): - if self.getConfig('captcha') and task.isTextual(): - task.handler.append(self) - task.setWaiting(60) - - html = getURL("http://www.freeimagehosting.net/upload.php", - post={"attached": (pycurl.FORM_FILE, task.captchaFile)}, multipart=True) - - url = re.search(r"\[img\]([^\[]+)\[/img\]\[/url\]", html).group(1) - 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)) - for t in self.getConfig('owner').split(): - if t.strip().startswith("#"): - self.sock.send("JOIN %s\r\n" % t.strip()) - self.logInfo(_("Connected to"), host) - self.logInfo(_("Switching to listening mode!")) - try: - self.main_loop() - - except IRCError, ex: - self.sock.send("QUIT :byebye\r\n") - traceback.print_exc() - self.sock.close() - - - def main_loop(self): - readbuffer = "" - while True: - time.sleep(1) - fdset = select([self.sock], [], [], 0) - if self.sock not in fdset[0]: - continue - - if self.abort: - raise IRCError("quit") - - readbuffer += self.sock.recv(1024) - temp = readbuffer.split("\n") - readbuffer = temp.pop() - - for line in temp: - line = line.rstrip() - first = line.split() - - if first[0] == "PING": - self.sock.send("PONG %s\r\n" % first[1]) - - if first[0] == "ERROR": - raise IRCError(line) - - msg = line.split(None, 3) - if len(msg) < 4: - continue - - msg = { - "origin": msg[0][1:], - "action": msg[1], - "target": msg[2], - "text": msg[3][1:] - } - - self.handle_events(msg) - - - def handle_events(self, msg): - if not msg['origin'].split("!", 1)[0] in self.getConfig('owner').split(): - return - - if msg['target'].split("!", 1)[0] != self.getConfig('nick'): - return - - if msg['action'] != "PRIVMSG": - return - - # HANDLE CTCP ANTI FLOOD/BOT PROTECTION - if msg['text'] == "\x01VERSION\x01": - 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.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 - return - - trigger = "pass" - args = None - - try: - temp = msg['text'].split() - trigger = temp[0] - if len(temp) > 1: - args = temp[1:] - except Exception: - pass - - handler = getattr(self, "event_%s" % trigger, self.event_pass) - try: - res = handler(args) - for line in res: - self.response(line, msg['origin']) - except Exception, e: - self.logError(e) - - - def response(self, msg, origin=""): - if origin == "": - for t in self.getConfig('owner').split(): - self.sock.send("PRIVMSG %s :%s\r\n" % (t.strip(), msg)) - 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.core.api.statusDownloads() - if not downloads: - return ["INFO: There are no active downloads currently."] - - temp_progress = "" - lines = ["ID - Name - Status - Speed - ETA - Progress"] - for data in downloads: - - if data.status == 5: - temp_progress = data.format_wait - else: - temp_progress = "%d%% (%s)" % (data.percent, data.format_size) - - lines.append("#%d - %s - %s - %s - %s - %s" % - ( - data.fid, - data.name, - data.statusmsg, - "%s/s" % formatSize(data.speed), - "%s" % data.format_eta, - temp_progress - )) - return lines - - - def event_queue(self, args): - ps = self.core.api.getQueueData() - - if not ps: - return ["INFO: There are no packages in queue."] - - lines = [] - for pack in ps: - lines.append('PACKAGE #%s: "%s" with %d links.' % (pack.pid, pack.name, len(pack.links))) - - return lines - - - def event_collector(self, args): - ps = self.core.api.getCollectorData() - if not ps: - return ["INFO: No packages in collector!"] - - lines = [] - for pack in ps: - lines.append('PACKAGE #%s: "%s" with %d links.' % (pack.pid, pack.name, len(pack.links))) - - return lines - - - def event_info(self, args): - if not args: - return ["ERROR: Use info like this: info <id>"] - - info = None - try: - 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>"] - - lines = [] - pack = None - try: - pack = self.core.api.getPackageData(int(args[0])) - - except PackageDoesNotExists: - return ["ERROR: Package doesn't exists."] - - id = args[0] - - self.more = [] - - lines.append('PACKAGE #%s: "%s" with %d links' % (id, pack.name, len(pack.links))) - for pyfile in pack.links: - self.more.append('LINK #%s: %s (%s) [%s][%s]' % (pyfile.fid, pyfile.name, pyfile.format_size, - pyfile.statusmsg, pyfile.plugin)) - - if len(self.more) < 6: - lines.extend(self.more) - self.more = [] - else: - lines.extend(self.more[:6]) - self.more = self.more[6:] - lines.append("%d more links do display." % len(self.more)) - - return lines - - - def event_more(self, args): - if not self.more: - return ["No more information to display."] - - lines = self.more[:6] - self.more = self.more[6:] - lines.append("%d more links do display." % len(self.more)) - - return lines - - - def event_start(self, args): - self.core.api.unpauseServer() - return ["INFO: Starting downloads."] - - - def event_stop(self, args): - 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". ', - "This will add the link <link> to to the package <package> / the package with id <id>!"] - - pack = args[0].strip() - links = [x.strip() for x in args[1:]] - - count_added = 0 - count_failed = 0 - try: - id = int(pack) - pack = self.core.api.getPackageData(id) - if not pack: - return ["ERROR: Package doesn't exists."] - - #TODO add links - - return ["INFO: Added %d links to Package %s [#%d]" % (len(links), pack['name'], id)] - - except Exception: - # create new package - 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.core.api.deletePackages(map(int, args[1:])) - return ["INFO: Deleted %d packages!" % len(args[1:])] - - elif args[0] == "-l": - 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.core.api.getPackageInfo(id) - except PackageDoesNotExists: - return ["ERROR: Package #%d does not exist." % 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.core.api.getPackageData(id): - return ["ERROR: Package #%d does not exist." % 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: - return ["ERROR: Captcha ID missing."] - - task = self.core.captchaManager.getTaskByID(args[0]) - if not task: - return ["ERROR: Captcha Task with ID %s does not exists." % args[0]] - - 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)", - "queue Shows all packages in the queue", - "collector Shows all packages in collector", - "del -p|-l <id> [...] Deletes all packages|links with the ids specified", - "info <id> Shows info of the link with id <id>", - "packinfo <id> Shows info of the package with id <id>", - "more Shows more info when the result was truncated", - "start Starts all downloads", - "stop Stops the download (but not abort active downloads)", - "push <id> Push package to queue", - "pull <id> Pull package from queue", - "status Show general download status", - "help Shows this help message"] - return lines - - -class IRCError(Exception): - - def __init__(self, value): - self.value = value - - - def __str__(self): - return repr(self.value) diff --git a/module/plugins/hooks/ImageTyperz.py b/module/plugins/hooks/ImageTyperz.py deleted file mode 100644 index f1fcacb71..000000000 --- a/module/plugins/hooks/ImageTyperz.py +++ /dev/null @@ -1,159 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import pycurl -import re - -from base64 import b64encode - -from module.network.RequestFactory import getURL, getRequest -from module.plugins.Hook import Hook, threaded - - -class ImageTyperzException(Exception): - - def __init__(self, err): - self.err = err - - - def getCode(self): - return self.err - - - def __str__(self): - return "<ImageTyperzException %s>" % self.err - - - def __repr__(self): - return "<ImageTyperzException %s>" % self.err - - -class ImageTyperz(Hook): - __name__ = "ImageTyperz" - __type__ = "hook" - __version__ = "0.06" - - __config__ = [("username", "str", "Username", ""), - ("passkey", "password", "Password", ""), - ("force", "bool", "Force IT even if client is connected", False)] - - __description__ = """Send captchas to ImageTyperz.com""" - __license__ = "GPLv3" - __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), - ("zoidberg", "zoidberg@mujmail.cz")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - SUBMIT_URL = "http://captchatypers.com/Forms/UploadFileAndGetTextNEW.ashx" - RESPOND_URL = "http://captchatypers.com/Forms/SetBadImage.ashx" - GETCREDITS_URL = "http://captchatypers.com/Forms/RequestBalance.ashx" - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def getCredits(self): - res = getURL(self.GETCREDITS_URL, - post={'action': "REQUESTBALANCE", - 'username': self.getConfig('username'), - 'password': self.getConfig('passkey')}) - - if res.startswith('ERROR'): - raise ImageTyperzException(res) - - try: - balance = float(res) - except Exception: - raise ImageTyperzException("Invalid response") - - self.logInfo(_("Account balance: $%s left") % res) - return balance - - - def submit(self, captcha, captchaType="file", match=None): - req = getRequest() - #raise timeout threshold - req.c.setopt(pycurl.LOW_SPEED_TIME, 80) - - try: - #@NOTE: Workaround multipart-post bug in HTTPRequest.py - if re.match("^\w*$", self.getConfig('passkey')): - multipart = True - data = (pycurl.FORM_FILE, captcha) - else: - multipart = False - with open(captcha, 'rb') as f: - data = f.read() - data = b64encode(data) - - res = req.load(self.SUBMIT_URL, - post={'action': "UPLOADCAPTCHA", - 'username': self.getConfig('username'), - 'password': self.getConfig('passkey'), "file": data}, - multipart=multipart) - finally: - req.close() - - if res.startswith("ERROR"): - raise ImageTyperzException(res) - else: - data = res.split('|') - if len(data) == 2: - ticket, result = data - else: - raise ImageTyperzException("Unknown response: %s" % res) - - return ticket, result - - - def newCaptchaTask(self, task): - if "service" in task.data: - return False - - if not task.isTextual(): - return False - - if not self.getConfig('username') or not self.getConfig('passkey'): - return False - - if self.core.isClientConnected() and not self.getConfig('force'): - return False - - if self.getCredits() > 0: - task.handler.append(self) - task.data['service'] = self.__name__ - task.setWaiting(100) - self._processCaptcha(task) - - else: - self.logInfo(_("Your %s account has not enough credits") % self.__name__) - - - def captchaInvalid(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: - res = getURL(self.RESPOND_URL, - post={'action': "SETBADIMAGE", - 'username': self.getConfig('username'), - 'password': self.getConfig('passkey'), - 'imageid': task.data['ticket']}) - - if res == "SUCCESS": - self.logInfo(_("Bad captcha solution received, requested refund")) - else: - self.logError(_("Bad captcha solution received, refund request failed"), res) - - - @threaded - def _processCaptcha(self, task): - c = task.captchaFile - try: - ticket, result = self.submit(c) - except ImageTyperzException, e: - task.error = e.getCode() - return - - task.data['ticket'] = ticket - task.setResult(result) diff --git a/module/plugins/hooks/JustPremium.py b/module/plugins/hooks/JustPremium.py deleted file mode 100644 index d18afc524..000000000 --- a/module/plugins/hooks/JustPremium.py +++ /dev/null @@ -1,56 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.Hook import Hook - - -class JustPremium(Hook): - __name__ = "JustPremium" - __type__ = "hook" - __version__ = "0.22" - - __config__ = [("excluded", "str", "Exclude hosters (comma separated)", ""), - ("included", "str", "Include hosters (comma separated)", "")] - - __description__ = """Remove not-premium links from added urls""" - __license__ = "GPLv3" - __authors__ = [("mazleu" , "mazleica@gmail.com"), - ("Walter Purcaro", "vuolter@gmail.com" ), - ("immenz" , "immenz@gmx.net" )] - - - event_list = ["linksAdded"] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def linksAdded(self, links, pid): - hosterdict = self.core.pluginManager.hosterPlugins - linkdict = self.core.api.checkURLs(links) - - premiumplugins = set(account.type for account in self.core.api.getAccounts(False) \ - if account.valid and account.premium) - multihosters = set(hoster for hoster in self.core.pluginManager.hosterPlugins \ - if 'new_name' in hosterdict[hoster] \ - and hosterdict[hoster]['new_name'] in premiumplugins) - - excluded = map(lambda domain: "".join(part.capitalize() for part in re.split(r'(\.|\d+)', domain) if part != '.'), - self.getConfig('excluded').replace(' ', '').replace(',', '|').replace(';', '|').split('|')) - included = map(lambda domain: "".join(part.capitalize() for part in re.split(r'(\.|\d+)', domain) if part != '.'), - self.getConfig('included').replace(' ', '').replace(',', '|').replace(';', '|').split('|')) - - hosterlist = (premiumplugins | multihosters).union(excluded).difference(included) - - #: Found at least one hoster with account or multihoster - if not any( True for pluginname in linkdict if pluginname in hosterlist ): - return - - for pluginname in set(linkdict.keys()) - hosterlist: - self.logInfo(_("Remove links of plugin: %s") % pluginname) - for link in linkdict[pluginname]: - self.logDebug("Remove link: %s" % link) - links.remove(link) diff --git a/module/plugins/hooks/LinkdecrypterComHook.py b/module/plugins/hooks/LinkdecrypterComHook.py deleted file mode 100644 index b2eaece62..000000000 --- a/module/plugins/hooks/LinkdecrypterComHook.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.internal.MultiHook import MultiHook - - -class LinkdecrypterComHook(MultiHook): - __name__ = "LinkdecrypterComHook" - __type__ = "hook" - __version__ = "1.06" - - __config__ = [("activated" , "bool" , "Activated" , True ), - ("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Linkdecrypter.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - def getHosters(self): - list = re.search(r'>Supported\(\d+\)</b>: <i>(.[\w.\-, ]+)', - self.getURL("http://linkdecrypter.com/", decode=True).replace("(g)", "")).group(1).split(', ') - try: - list.remove("download.serienjunkies.org") - except ValueError: - pass - - return list diff --git a/module/plugins/hooks/LinksnappyComHook.py b/module/plugins/hooks/LinksnappyComHook.py deleted file mode 100644 index 72282575b..000000000 --- a/module/plugins/hooks/LinksnappyComHook.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class LinksnappyComHook(MultiHook): - __name__ = "LinksnappyComHook" - __type__ = "hook" - __version__ = "0.04" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Linksnappy.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("stickell", "l.stickell@yahoo.it")] - - - def getHosters(self): - json_data = self.getURL("http://gen.linksnappy.com/lseAPI.php", get={'act': "FILEHOSTS"}) - json_data = json_loads(json_data) - - return json_data['return'].keys() diff --git a/module/plugins/hooks/MegaDebridEuHook.py b/module/plugins/hooks/MegaDebridEuHook.py deleted file mode 100644 index 0de7b4dcf..000000000 --- a/module/plugins/hooks/MegaDebridEuHook.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class MegaDebridEuHook(MultiHook): - __name__ = "MegaDebridEuHook" - __type__ = "hook" - __version__ = "0.05" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Mega-debrid.eu hook plugin""" - __license__ = "GPLv3" - __authors__ = [("D.Ducatel", "dducatel@je-geek.fr")] - - - def getHosters(self): - reponse = self.getURL("http://www.mega-debrid.eu/api.php", get={'action': "getHosters"}) - json_data = json_loads(reponse) - - if json_data['response_code'] == "ok": - host_list = [element[0] for element in json_data['hosters']] - else: - self.logError(_("Unable to retrieve hoster list")) - host_list = list() - - return host_list diff --git a/module/plugins/hooks/MegaRapidoNetHook.py b/module/plugins/hooks/MegaRapidoNetHook.py deleted file mode 100644 index e113b305e..000000000 --- a/module/plugins/hooks/MegaRapidoNetHook.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.internal.MultiHook import MultiHook - - -class MegaRapidoNetHook(MultiHook): - __name__ = "MegaRapidoNetHook" - __type__ = "hook" - __version__ = "0.02" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """MegaRapido.net hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")] - - - def getHosters(self): - hosters = {'1fichier' : [],#leave it there are so many possible addresses? - '1st-files' : ['1st-files.com'], - '2shared' : ['2shared.com'], - '4shared' : ['4shared.com', '4shared-china.com'], - 'asfile' : ['http://asfile.com/'], - 'bitshare' : ['bitshare.com'], - 'brupload' : ['brupload.net'], - 'crocko' : ['crocko.com','easy-share.com'], - 'dailymotion' : ['dailymotion.com'], - 'depfile' : ['depfile.com'], - 'depositfiles': ['depositfiles.com', 'dfiles.eu'], - 'dizzcloud' : ['dizzcloud.com'], - 'dl.dropbox' : [], - 'extabit' : ['extabit.com'], - 'extmatrix' : ['extmatrix.com'], - 'facebook' : [], - 'file4go' : ['file4go.com'], - 'filecloud' : ['filecloud.io','ifile.it','mihd.net'], - 'filefactory' : ['filefactory.com'], - 'fileom' : ['fileom.com'], - 'fileparadox' : ['fileparadox.in'], - 'filepost' : ['filepost.com', 'fp.io'], - 'filerio' : ['filerio.in','filerio.com','filekeen.com'], - 'filesflash' : ['filesflash.com'], - 'firedrive' : ['firedrive.com', 'putlocker.com'], - 'flashx' : [], - 'freakshare' : ['freakshare.net', 'freakshare.com'], - 'gigasize' : ['gigasize.com'], - 'hipfile' : ['hipfile.com'], - 'junocloud' : ['junocloud.me'], - 'letitbit' : ['letitbit.net','shareflare.net'], - 'mediafire' : ['mediafire.com'], - 'mega' : ['mega.co.nz'], - 'megashares' : ['megashares.com'], - 'metacafe' : ['metacafe.com'], - 'netload' : ['netload.in'], - 'oboom' : ['oboom.com'], - 'rapidgator' : ['rapidgator.net'], - 'rapidshare' : ['rapidshare.com'], - 'rarefile' : ['rarefile.net'], - 'ryushare' : ['ryushare.com'], - 'sendspace' : ['sendspace.com'], - 'turbobit' : ['turbobit.net', 'unextfiles.com'], - 'uploadable' : ['uploadable.ch'], - 'uploadbaz' : ['uploadbaz.com'], - 'uploaded' : ['uploaded.to', 'uploaded.net', 'ul.to'], - 'uploadhero' : ['uploadhero.com'], - 'uploading' : ['uploading.com'], - 'uptobox' : ['uptobox.com'], - 'xvideos' : ['xvideos.com'], - 'youtube' : ['youtube.com']} - - hoster_list = [] - - for item in hosters.itervalues(): - hoster_list.extend(item) - - return hoster_list diff --git a/module/plugins/hooks/MergeFiles.py b/module/plugins/hooks/MergeFiles.py deleted file mode 100644 index 941938920..000000000 --- a/module/plugins/hooks/MergeFiles.py +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import os -import re -import traceback - -from module.plugins.Hook import Hook, threaded -from module.utils import save_join - - -class MergeFiles(Hook): - __name__ = "MergeFiles" - __type__ = "hook" - __version__ = "0.14" - - __config__ = [("activated", "bool", "Activated", True)] - - __description__ = """Merges parts splitted with hjsplit""" - __license__ = "GPLv3" - __authors__ = [("and9000", "me@has-no-mail.com")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - BUFFER_SIZE = 4096 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - @threaded - def packageFinished(self, pack): - files = {} - fid_dict = {} - for fid, data in pack.getChildren().iteritems(): - 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']) - files[data['name'][:-4]].sort() - fid_dict[data['name']] = fid - - download_folder = self.config['general']['download_folder'] - - if self.config['general']['folder_per_package']: - download_folder = save_join(download_folder, pack.folder) - - for name, file_list in files.iteritems(): - self.logInfo(_("Starting merging of"), name) - - with open(save_join(download_folder, name), "wb") as final_file: - for splitted_file in file_list: - self.logDebug("Merging part", splitted_file) - - pyfile = self.core.files.getFile(fid_dict[splitted_file]) - - pyfile.setStatus("processing") - - try: - with open(save_join(download_folder, splitted_file), "rb") as s_file: - 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: - final_file.write(f_buffer) - size_written += self.BUFFER_SIZE - pyfile.setProgress((size_written * 100) / s_file_size) - else: - break - self.logDebug("Finished merging part", splitted_file) - - except Exception, e: - traceback.print_exc() - - finally: - pyfile.setProgress(100) - pyfile.setStatus("finished") - pyfile.release() - - self.logInfo(_("Finished merging of"), name) diff --git a/module/plugins/hooks/MultiHome.py b/module/plugins/hooks/MultiHome.py deleted file mode 100644 index a26d139c0..000000000 --- a/module/plugins/hooks/MultiHome.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- - -import time - -from module.plugins.Hook import Hook - - -class MultiHome(Hook): - __name__ = "MultiHome" - __type__ = "hook" - __version__ = "0.12" - - __config__ = [("interfaces", "str", "Interfaces", "None")] - - __description__ = """Ip address changer""" - __license__ = "GPLv3" - __authors__ = [("mkaay", "mkaay@mkaay.de")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.register = {} - self.interfaces = [] - - self.parseInterfaces(self.getConfig('interfaces').split(";")) - - if not self.interfaces: - 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 - - - def getRequest(pluginName, account=None): - iface = self.bestInterface(pluginName, account) - if iface: - iface.useFor(pluginName, account) - requestFactory.iface = lambda: iface.adress - self.logDebug("Using address", iface.adress) - return oldGetRequest(pluginName, account) - - requestFactory.getRequest = getRequest - - - def bestInterface(self, pluginName, account): - best = None - for interface in self.interfaces: - if not best or interface.lastPluginAccess(pluginName, account) < best.lastPluginAccess(pluginName, account): - best = interface - return best - - -class Interface(object): - - def __init__(self, adress): - 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.time() - - - def __repr__(self): - return "<Interface - %s>" % self.adress diff --git a/module/plugins/hooks/MultihostersComHook.py b/module/plugins/hooks/MultihostersComHook.py deleted file mode 100644 index 7b5e49c49..000000000 --- a/module/plugins/hooks/MultihostersComHook.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.hooks.ZeveraComHook import ZeveraComHook - - -class MultihostersComHook(ZeveraComHook): - __name__ = "MultihostersComHook" - __type__ = "hook" - __version__ = "0.02" - - __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed", "bool" , "Revert to standard download if download fails", False), - ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )] - - __description__ = """Multihosters.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("tjeh", "tjeh@gmx.net")] diff --git a/module/plugins/hooks/MultishareCzHook.py b/module/plugins/hooks/MultishareCzHook.py deleted file mode 100644 index 6052b7673..000000000 --- a/module/plugins/hooks/MultishareCzHook.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.internal.MultiHook import MultiHook - - -class MultishareCzHook(MultiHook): - __name__ = "MultishareCzHook" - __type__ = "hook" - __version__ = "0.07" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """MultiShare.cz hook plugin""" - __license__ = "GPLv3" - __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - - - HOSTER_PATTERN = r'<img class="logo-shareserveru"[^>]*?alt="(.+?)"></td>\s*<td class="stav">[^>]*?alt="OK"' - - - def getHosters(self): - html = self.getURL("http://www.multishare.cz/monitoring/") - return re.findall(self.HOSTER_PATTERN, html) diff --git a/module/plugins/hooks/MyfastfileComHook.py b/module/plugins/hooks/MyfastfileComHook.py deleted file mode 100644 index 20a1cfac2..000000000 --- a/module/plugins/hooks/MyfastfileComHook.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class MyfastfileComHook(MultiHook): - __name__ = "MyfastfileComHook" - __type__ = "hook" - __version__ = "0.05" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Myfastfile.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("stickell", "l.stickell@yahoo.it")] - - - def getHosters(self): - json_data = self.getURL("http://myfastfile.com/api.php", get={'hosts': ""}, decode=True) - self.logDebug("JSON data", json_data) - json_data = json_loads(json_data) - - return json_data['hosts'] diff --git a/module/plugins/hooks/NoPremiumPlHook.py b/module/plugins/hooks/NoPremiumPlHook.py deleted file mode 100644 index b5a007ff9..000000000 --- a/module/plugins/hooks/NoPremiumPlHook.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class NoPremiumPlHook(MultiHook): - __name__ = "NoPremiumPlHook" - __type__ = "hook" - __version__ = "0.03" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """NoPremium.pl hook plugin""" - __license__ = "GPLv3" - __authors__ = [("goddie", "dev@nopremium.pl")] - - - def getHosters(self): - hostings = json_loads(self.getURL("https://www.nopremium.pl/clipboard.php?json=3").strip()) - hostings_domains = [domain for row in hostings for domain in row["domains"] if row["sdownload"] == "0"] - - self.logDebug(hostings_domains) - - return hostings_domains diff --git a/module/plugins/hooks/OverLoadMeHook.py b/module/plugins/hooks/OverLoadMeHook.py deleted file mode 100644 index d608a2ecd..000000000 --- a/module/plugins/hooks/OverLoadMeHook.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class OverLoadMeHook(MultiHook): - __name__ = "OverLoadMeHook" - __type__ = "hook" - __version__ = "0.04" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 ), - ("ssl" , "bool" , "Use HTTPS" , True )] - - __description__ = """Over-Load.me hook plugin""" - __license__ = "GPLv3" - __authors__ = [("marley", "marley@over-load.me")] - - - def getHosters(self): - https = "https" if self.getConfig('ssl') else "http" - html = self.getURL(https + "://api.over-load.me/hoster.php", - get={'auth': "0001-cb1f24dadb3aa487bda5afd3b76298935329be7700cd7-5329be77-00cf-1ca0135f"}).replace("\"", "").strip() - self.logDebug("Hosterlist", html) - - return [x.strip() for x in html.split(",") if x.strip()] diff --git a/module/plugins/hooks/PremiumToHook.py b/module/plugins/hooks/PremiumToHook.py deleted file mode 100644 index ef2a84223..000000000 --- a/module/plugins/hooks/PremiumToHook.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class PremiumToHook(MultiHook): - __name__ = "PremiumToHook" - __type__ = "hook" - __version__ = "0.08" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Premium.to hook plugin""" - __license__ = "GPLv3" - __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), - ("zoidberg", "zoidberg@mujmail.cz"), - ("stickell", "l.stickell@yahoo.it")] - - - def getHosters(self): - html = self.getURL("http://premium.to/api/hosters.php", - get={'username': self.account.username, 'password': self.account.password}) - return [x.strip() for x in html.replace("\"", "").split(";")] diff --git a/module/plugins/hooks/PremiumizeMeHook.py b/module/plugins/hooks/PremiumizeMeHook.py deleted file mode 100644 index e081fb389..000000000 --- a/module/plugins/hooks/PremiumizeMeHook.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class PremiumizeMeHook(MultiHook): - __name__ = "PremiumizeMeHook" - __type__ = "hook" - __version__ = "0.17" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Premiumize.me hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com")] - - - def getHosters(self): - # Get account data - user, data = self.account.selectAccount() - - # Get supported hosters list from premiumize.me using the - # json API v1 (see https://secure.premiumize.me/?show=api) - answer = self.getURL("https://api.premiumize.me/pm-api/v1.php", - get={'method': "hosterlist", 'params[login]': user, 'params[pass]': data['password']}) - data = json_loads(answer) - - # If account is not valid thera are no hosters available - if data['status'] != 200: - return [] - - # Extract hosters from json file - return data['result']['hosterlist'] diff --git a/module/plugins/hooks/PutdriveComHook.py b/module/plugins/hooks/PutdriveComHook.py deleted file mode 100644 index c3ebf4ff3..000000000 --- a/module/plugins/hooks/PutdriveComHook.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.hooks.ZeveraComHook import ZeveraComHook - - -class PutdriveComHook(ZeveraComHook): - __name__ = "PutdriveComHook" - __type__ = "hook" - __version__ = "0.01" - - __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed", "bool" , "Revert to standard download if download fails", False), - ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )] - - __description__ = """Putdrive.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] diff --git a/module/plugins/hooks/RPNetBizHook.py b/module/plugins/hooks/RPNetBizHook.py deleted file mode 100644 index 10332948d..000000000 --- a/module/plugins/hooks/RPNetBizHook.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class RPNetBizHook(MultiHook): - __name__ = "RPNetBizHook" - __type__ = "hook" - __version__ = "0.14" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """RPNet.biz hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Dman", "dmanugm@gmail.com")] - - - def getHosters(self): - # Get account data - user, data = self.account.selectAccount() - - res = self.getURL("https://premium.rpnet.biz/client_api.php", - get={'username': user, 'password': data['password'], 'action': "showHosterList"}) - hoster_list = json_loads(res) - - # If account is not valid thera are no hosters available - if 'error' in hoster_list: - return [] - - # Extract hosters from json file - return hoster_list['hosters'] diff --git a/module/plugins/hooks/RapideoPlHook.py b/module/plugins/hooks/RapideoPlHook.py deleted file mode 100644 index 0400f07ba..000000000 --- a/module/plugins/hooks/RapideoPlHook.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class RapideoPlHook(MultiHook): - __name__ = "RapideoPlHook" - __type__ = "hook" - __version__ = "0.03" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Rapideo.pl hook plugin""" - __license__ = "GPLv3" - __authors__ = [("goddie", "dev@rapideo.pl")] - - - def getHosters(self): - hostings = json_loads(self.getURL("https://www.rapideo.pl/clipboard.php?json=3").strip()) - hostings_domains = [domain for row in hostings for domain in row["domains"] if row["sdownload"] == "0"] - - self.logDebug(hostings_domains) - - return hostings_domains diff --git a/module/plugins/hooks/RealdebridComHook.py b/module/plugins/hooks/RealdebridComHook.py deleted file mode 100644 index aa0c9f640..000000000 --- a/module/plugins/hooks/RealdebridComHook.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class RealdebridComHook(MultiHook): - __name__ = "RealdebridComHook" - __type__ = "hook" - __version__ = "0.46" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 ), - ("ssl" , "bool" , "Use HTTPS" , True )] - - __description__ = """Real-Debrid.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Devirex Hazzard", "naibaf_11@yahoo.de")] - - - def getHosters(self): - https = "https" if self.getConfig('ssl') else "http" - html = self.getURL(https + "://real-debrid.com/api/hosters.php").replace("\"", "").strip() - - return [x.strip() for x in html.split(",") if x.strip()] diff --git a/module/plugins/hooks/RehostToHook.py b/module/plugins/hooks/RehostToHook.py deleted file mode 100644 index a2415129a..000000000 --- a/module/plugins/hooks/RehostToHook.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class RehostToHook(MultiHook): - __name__ = "RehostToHook" - __type__ = "hook" - __version__ = "0.50" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Rehost.to hook plugin""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.org")] - - - def getHosters(self): - user, data = self.account.selectAccount() - html = self.getURL("http://rehost.to/api.php", - get={'cmd' : "get_supported_och_dl", - 'long_ses': self.account.getAccountInfo(user)['session']}) - return [x.strip() for x in html.replace("\"", "").split(",")] diff --git a/module/plugins/hooks/RestartFailed.py b/module/plugins/hooks/RestartFailed.py deleted file mode 100644 index cab986d9e..000000000 --- a/module/plugins/hooks/RestartFailed.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.Hook import Hook - - -class RestartFailed(Hook): - __name__ = "RestartFailed" - __type__ = "hook" - __version__ = "1.58" - - __config__ = [("interval", "int", "Check interval in minutes", 90)] - - __description__ = """Restart all the failed downloads in queue""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - # event_list = ["pluginConfigChanged"] - - MIN_CHECK_INTERVAL = 15 * 60 #: 15 minutes - - - # def pluginConfigChanged(self, plugin, name, value): - # if name == "interval": - # interval = value * 60 - # if self.MIN_CHECK_INTERVAL <= interval != self.interval: - # self.core.scheduler.removeJob(self.cb) - # self.interval = interval - # self.initPeriodical() - # else: - # self.logDebug("Invalid interval value, kept current") - - - def periodical(self): - self.logDebug(_("Restart failed downloads")) - self.core.api.restartFailed() - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.interval = self.MIN_CHECK_INTERVAL - - - def coreReady(self): - # self.pluginConfigChanged(self.__name__, "interval", self.getConfig('interval')) - self.interval = max(self.MIN_CHECK_INTERVAL, self.getConfig('interval') * 60) diff --git a/module/plugins/hooks/SimplyPremiumComHook.py b/module/plugins/hooks/SimplyPremiumComHook.py deleted file mode 100644 index 116e3a76e..000000000 --- a/module/plugins/hooks/SimplyPremiumComHook.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.common.json_layer import json_loads -from module.plugins.internal.MultiHook import MultiHook - - -class SimplyPremiumComHook(MultiHook): - __name__ = "SimplyPremiumComHook" - __type__ = "hook" - __version__ = "0.05" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Simply-Premium.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("EvolutionClip", "evolutionclip@live.de")] - - - def getHosters(self): - json_data = self.getURL("http://www.simply-premium.com/api/hosts.php", get={'format': "json", 'online': 1}) - json_data = json_loads(json_data) - - host_list = [element['regex'] for element in json_data['result']] - - return host_list diff --git a/module/plugins/hooks/SimplydebridComHook.py b/module/plugins/hooks/SimplydebridComHook.py deleted file mode 100644 index 01629df99..000000000 --- a/module/plugins/hooks/SimplydebridComHook.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class SimplydebridComHook(MultiHook): - __name__ = "SimplydebridComHook" - __type__ = "hook" - __version__ = "0.04" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Simply-Debrid.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")] - - - def getHosters(self): - html = self.getURL("http://simply-debrid.com/api.php", get={'list': 1}) - return [x.strip() for x in html.rstrip(';').replace("\"", "").split(";")] diff --git a/module/plugins/hooks/SkipRev.py b/module/plugins/hooks/SkipRev.py deleted file mode 100644 index 7901ca540..000000000 --- a/module/plugins/hooks/SkipRev.py +++ /dev/null @@ -1,112 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -import urllib -import urlparse - -from types import MethodType - -from module.PyFile import PyFile -from module.plugins.Hook import Hook -from module.plugins.Plugin import SkipDownload - - -class SkipRev(Hook): - __name__ = "SkipRev" - __type__ = "hook" - __version__ = "0.29" - - __config__ = [("mode" , "Auto;Manual", "Choose recovery archives to skip" , "Auto"), - ("revtokeep", "int" , "Number of recovery archives to keep for package", 0 )] - - __description__ = """Skip recovery archives (.rev)""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - @staticmethod - def _setup(self): - self.pyfile.plugin._setup() - if self.pyfile.hasStatus("skipped"): - raise SkipDownload(self.pyfile.statusname or self.pyfile.pluginname) - - - def _name(self, pyfile): - if hasattr(pyfile.pluginmodule, "getInfo"): #@NOTE: getInfo is deprecated in 0.4.10 - return pyfile.pluginmodule.getInfo([pyfile.url]).next()[0] - else: - self.logWarning("Unable to grab file name") - return urlparse.urlparse(urllib.unquote(pyfile.url)).path.split('/')[-1] - - - def _pyfile(self, link): - return PyFile(self.core.files, - link.fid, - link.url, - link.name, - link.size, - link.status, - link.error, - link.plugin, - link.packageID, - link.order) - - - def downloadPreparing(self, pyfile): - name = self._name(pyfile) - - if pyfile.statusname is _("unskipped") or not name.endswith(".rev") or not ".part" in name: - return - - revtokeep = -1 if self.getConfig('mode') == "Auto" else self.getConfig('revtokeep') - - if revtokeep: - status_list = (1, 4, 8, 9, 14) if revtokeep < 0 else (1, 3, 4, 8, 9, 14) - pyname = re.compile(r'%s\.part\d+\.rev$' % name.rsplit('.', 2)[0].replace('.', '\.')) - - queued = [True for link in self.core.api.getPackageData(pyfile.package().id).links \ - if link.status not in status_list and pyname.match(link.name)].count(True) - - if not queued or queued < revtokeep: #: keep one rev at least in auto mode - return - - pyfile.setCustomStatus("SkipRev", "skipped") - - if not hasattr(pyfile.plugin, "_setup"): - # Work-around: inject status checker inside the preprocessing routine of the plugin - pyfile.plugin._setup = pyfile.plugin.setup - pyfile.plugin.setup = MethodType(self._setup, pyfile.plugin) - - - def downloadFailed(self, pyfile): - #: Check if pyfile is still "failed", - # maybe might has been restarted in meantime - if pyfile.status != 8 or pyfile.name.rsplit('.', 1)[-1].strip() not in ("rar", "rev"): - return - - revtokeep = -1 if self.getConfig('mode') == "Auto" else self.getConfig('revtokeep') - - if not revtokeep: - return - - pyname = re.compile(r'%s\.part\d+\.rev$' % pyfile.name.rsplit('.', 2)[0].replace('.', '\.')) - - for link in self.core.api.getPackageData(pyfile.package().id).links: - if link.status is 4 and pyname.match(link.name): - pylink = self._pyfile(link) - - if revtokeep > -1 or pyfile.name.endswith(".rev"): - pylink.setStatus("queued") - else: - pylink.setCustomStatus(_("unskipped"), "queued") - - self.core.files.save() - pylink.release() - return diff --git a/module/plugins/hooks/SmoozedComHook.py b/module/plugins/hooks/SmoozedComHook.py deleted file mode 100644 index 24b7c8df0..000000000 --- a/module/plugins/hooks/SmoozedComHook.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class SmoozedComHook(MultiHook): - __name__ = "SmoozedComHook" - __type__ = "hook" - __version__ = "0.03" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Smoozed.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("", "")] - - - def getHosters(self): - user, data = self.account.selectAccount() - return self.account.getAccountInfo(user)["hosters"] diff --git a/module/plugins/hooks/UnSkipOnFail.py b/module/plugins/hooks/UnSkipOnFail.py deleted file mode 100644 index 9059d0350..000000000 --- a/module/plugins/hooks/UnSkipOnFail.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.PyFile import PyFile -from module.plugins.Hook import Hook - - -class UnSkipOnFail(Hook): - __name__ = "UnSkipOnFail" - __type__ = "hook" - __version__ = "0.07" - - __config__ = [("activated", "bool", "Activated", True)] - - __description__ = """Restart skipped duplicates when download fails""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def downloadFailed(self, pyfile): - #: Check if pyfile is still "failed", - # maybe might has been restarted in meantime - if pyfile.status != 8: - return - - msg = _("Looking for skipped duplicates of: %s (pid:%s)") - self.logInfo(msg % (pyfile.name, pyfile.package().id)) - - link = self.findDuplicate(pyfile) - if link: - self.logInfo(_("Queue found duplicate: %s (pid:%s)") % (link.name, link.packageID)) - - #: Change status of "link" to "new_status". - # "link" has to be a valid FileData object, - # "new_status" has to be a valid status name - # (i.e. "queued" for this Plugin) - # It creates a temporary PyFile object using - # "link" data, changes its status, and tells - # the core.files-manager to save its data. - pylink = self._pyfile(link) - - pylink.setCustomStatus(_("unskipped"), "queued") - - self.core.files.save() - pylink.release() - - else: - self.logInfo(_("No duplicates found")) - - - def findDuplicate(self, pyfile): - """ Search all packages for duplicate links to "pyfile". - Duplicates are links that would overwrite "pyfile". - To test on duplicity the package-folder and link-name - of twolinks are compared (link.name). - So this method returns a list of all links with equal - package-folders and filenames as "pyfile", but except - the data for "pyfile" iotselöf. - It does MOT check the link's status. - """ - queue = self.core.api.getQueue() #: get packages (w/o files, as most file data is useless here) - - for package in queue: - #: check if package-folder equals pyfile's package folder - if package.folder != pyfile.package().folder: - continue - - #: now get packaged data w/ files/links - pdata = self.core.api.getPackageData(package.pid) - for link in pdata.links: - #: check if link is "skipped" - if link.status != 4: - continue - - #: check if link name collides with pdata's name - #: AND at last check if it is not pyfile itself - if link.name == pyfile.name and link.fid != pyfile.id: - return link - - - def _pyfile(self, link): - return PyFile(self.core.files, - link.fid, - link.url, - link.name, - link.size, - link.status, - link.error, - link.plugin, - link.packageID, - link.order) diff --git a/module/plugins/hooks/UpdateManager.py b/module/plugins/hooks/UpdateManager.py deleted file mode 100644 index 5779e7c80..000000000 --- a/module/plugins/hooks/UpdateManager.py +++ /dev/null @@ -1,329 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import os -import re -import sys -import time - -from operator import itemgetter - -from module.network.RequestFactory import getURL -from module.plugins.Hook import Expose, Hook, threaded -from module.utils import save_join - - -# Case-sensitive os.path.exists -def exists(path): - if os.path.exists(path): - if os.name == 'nt': - dir, name = os.path.split(path) - return name in os.listdir(dir) - else: - return True - else: - return False - - -class UpdateManager(Hook): - __name__ = "UpdateManager" - __type__ = "hook" - __version__ = "0.51" - - __config__ = [("activated" , "bool", "Activated" , True ), - ("checkinterval", "int" , "Check interval in hours" , 8 ), - ("autorestart" , "bool", "Auto-restart pyLoad when required" , True ), - ("checkonstart" , "bool", "Check for updates on startup" , True ), - ("checkperiod" , "bool", "Check for updates periodically" , True ), - ("reloadplugins", "bool", "Monitor plugin code changes in debug mode", True ), - ("nodebugupdate", "bool", "Don't update plugins in debug mode" , False)] - - __description__ = """ Check for updates """ - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - interval = 0 - - SERVER_URL = "http://updatemanager.pyload.org" - MIN_CHECK_INTERVAL = 3 * 60 * 60 #: 3 hours - - event_list = ["allDownloadsProcessed"] - - - def coreReady(self): - if self.checkonstart: - self.update() - - self.initPeriodical() - - - def setup(self): - self.interval = 10 - self.info = {'pyload': False, 'version': None, 'plugins': False, 'last_check': time.time()} - self.mtimes = {} #: store modification time for each plugin - - if self.getConfig('checkonstart'): - self.core.api.pauseServer() - self.checkonstart = True - else: - self.checkonstart = False - - self.do_restart = False - - - def allDownloadsProcessed(self): - if self.do_restart is True: - self.logWarning(_("Downloads are done, restarting pyLoad to reload the updated plugins")) - self.core.api.restart() - - - def periodical(self): - if self.core.debug: - if self.getConfig('reloadplugins'): - self.autoreloadPlugins() - - if self.getConfig('nodebugupdate'): - return - - if self.getConfig('checkperiod') \ - and time.time() - max(self.MIN_CHECK_INTERVAL, self.getConfig('checkinterval') * 60 * 60) > self.info['last_check']: - self.update() - - - @Expose - def autoreloadPlugins(self): - """ reload and reindex all modified plugins """ - modules = filter( - lambda m: m and (m.__name__.startswith("module.plugins.") or - m.__name__.startswith("userplugins.")) and - m.__name__.count(".") >= 2, sys.modules.itervalues() - ) - - reloads = [] - - for m in modules: - root, type, name = m.__name__.rsplit(".", 2) - id = (type, name) - if type in self.core.pluginManager.plugins: - f = m.__file__.replace(".pyc", ".py") - if not os.path.isfile(f): - continue - - mtime = os.stat(f).st_mtime - - if id not in self.mtimes: - self.mtimes[id] = mtime - elif self.mtimes[id] < mtime: - reloads.append(id) - self.mtimes[id] = mtime - - return True if self.core.pluginManager.reloadPlugins(reloads) else False - - - def server_response(self): - try: - return getURL(self.SERVER_URL, get={'v': self.core.api.getServerVersion()}).splitlines() - - except Exception: - self.logWarning(_("Unable to retrieve server to get updates")) - - - @Expose - @threaded - def update(self): - """ check for updates """ - - self.core.api.pauseServer() - - if self._update() is 2 and self.getConfig('autorestart'): - if not self.core.api.statusDownloads(): - self.core.api.restart() - else: - self.do_restart = True - self.logWarning(_("Downloads are active, will restart once the download is done")) - else: - self.core.api.unpauseServer() - - - def _update(self): - data = self.server_response() - - self.info['last_check'] = time.time() - - if not data: - exitcode = 0 - - elif data[0] == "None": - self.logInfo(_("No new pyLoad version available")) - exitcode = self._updatePlugins(data[1:]) - - elif onlyplugin: - exitcode = 0 - - else: - self.logInfo(_("*** New pyLoad Version %s available ***") % data[0]) - self.logInfo(_("*** Get it here: https://github.com/pyload/pyload/releases ***")) - self.info['pyload'] = True - self.info['version'] = data[0] - exitcode = 3 - - # Exit codes: - # -1 = No plugin updated, new pyLoad version available - # 0 = No plugin updated - # 1 = Plugins updated - # 2 = Plugins updated, but restart required - return exitcode - - - def _updatePlugins(self, data): - """ check for plugin updates """ - - exitcode = 0 - updated = [] - - url = data[0] - schema = data[1].split('|') - - VERSION = re.compile(r'__version__.*=.*("|\')([\d.]+)') - - if "BLACKLIST" in data: - blacklist = data[data.index('BLACKLIST') + 1:] - updatelist = data[2:data.index('BLACKLIST')] - else: - blacklist = [] - updatelist = data[2:] - - updatelist = [dict(zip(schema, x.split('|'))) for x in updatelist] - blacklist = [dict(zip(schema, x.split('|'))) for x in blacklist] - - if blacklist: - type_plugins = [(plugin['type'], plugin['name'].rsplit('.', 1)[0]) for plugin in blacklist] - - # Protect UpdateManager from self-removing - try: - type_plugins.remove(("hook", "UpdateManager")) - except ValueError: - pass - - for t, n in type_plugins: - for idx, plugin in enumerate(updatelist): - if n == plugin['name'] and t == plugin['type']: - updatelist.pop(idx) - break - - for t, n in self.removePlugins(sorted(type_plugins)): - self.logInfo(_("Removed blacklisted plugin: [%(type)s] %(name)s") % { - 'type': t, - 'name': n, - }) - - for plugin in sorted(updatelist, key=itemgetter("type", "name")): - filename = plugin['name'] - prefix = plugin['type'] - version = plugin['version'] - - if filename.endswith(".pyc"): - name = filename[:filename.find("_")] - else: - name = filename.replace(".py", "") - - #@TODO: Remove in 0.4.10 - if prefix.endswith("s"): - type = prefix[:-1] - else: - type = prefix - - plugins = getattr(self.core.pluginManager, "%sPlugins" % type) - - oldver = float(plugins[name]['v']) if name in plugins else None - newver = float(version) - - if not oldver: - msg = "New plugin: [%(type)s] %(name)s (v%(newver).2f)" - elif newver > oldver: - msg = "New version of plugin: [%(type)s] %(name)s (v%(oldver).2f -> v%(newver).2f)" - else: - continue - - self.logInfo(_(msg) % {'type' : type, - 'name' : name, - 'oldver': oldver, - 'newver': newver}) - try: - content = getURL(url % plugin) - m = VERSION.search(content) - - if m and m.group(2) == version: - with open(save_join("userplugins", prefix, filename), "wb") as f: - f.write(content) - - updated.append((prefix, name)) - else: - raise Exception, _("Version mismatch") - - except Exception, e: - self.logError(_("Error updating plugin: %s") % filename, e) - - if updated: - self.logInfo(_("*** Plugins updated ***")) - - if self.core.pluginManager.reloadPlugins(updated): - exitcode = 1 - else: - self.logWarning(_("pyLoad restart required to reload the updated plugins")) - self.info['plugins'] = True - exitcode = 2 - - self.manager.dispatchEvent("plugin_updated", updated) - else: - self.logInfo(_("No plugin updates available")) - - # Exit codes: - # 0 = No plugin updated - # 1 = Plugins updated - # 2 = Plugins updated, but restart required - return exitcode - - - @Expose - def removePlugins(self, type_plugins): - """ delete plugins from disk """ - - if not type_plugins: - return - - removed = set() - - self.logDebug("Requested deletion of plugins: %s" % type_plugins) - - for type, name in type_plugins: - rootplugins = os.path.join(pypath, "module", "plugins") - - for dir in ("userplugins", rootplugins): - py_filename = save_join(dir, type, name + ".py") - pyc_filename = py_filename + "c" - - if type == "hook": - try: - self.manager.deactivateHook(name) - - except Exception, e: - self.logDebug(e) - - for filename in (py_filename, pyc_filename): - if not exists(filename): - continue - - try: - os.remove(filename) - - except OSError, e: - self.logError(_("Error removing: %s") % filename, e) - - else: - id = (type, name) - removed.add(id) - - return list(removed) #: return a list of the plugins successfully removed diff --git a/module/plugins/hooks/UserAgentSwitcher.py b/module/plugins/hooks/UserAgentSwitcher.py deleted file mode 100644 index 912c2ef09..000000000 --- a/module/plugins/hooks/UserAgentSwitcher.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- - -from __future__ import with_statement - -import os -import pycurl -import random - -from module.plugins.Hook import Hook -from module.utils import fs_encode - - -class UserAgentSwitcher(Hook): - __name__ = "UserAgentSwitcher" - __type__ = "hook" - __version__ = "0.04" - - __config__ = [("activated", "bool", "Activated" , True ), - ("uaf" , "file", "Random user-agents file" , "" ), - ("uar" , "bool", "Random user-agent" , False ), - ("uas" , "str" , "Custom user-agent string", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0")] - - __description__ = """Custom user-agent""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def downloadPreparing(self, pyfile): - uar = self.getConfig('uar') - uaf = fs_encode(self.getConfig('uaf')) - - if uar and os.path.isfile(uaf): - with open(uaf) as f: - uas = random.choice([ua for ua in f.read().splitlines()]) - else: - uas = self.getConfig('uas') - - if uas: - self.logDebug("Use custom user-agent string: " + uas) - pyfile.plugin.req.http.c.setopt(pycurl.USERAGENT, uas.encode('utf-8')) diff --git a/module/plugins/hooks/WindowsPhoneNotify.py b/module/plugins/hooks/WindowsPhoneNotify.py deleted file mode 100644 index e61057f9f..000000000 --- a/module/plugins/hooks/WindowsPhoneNotify.py +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: utf-8 -*- - -import httplib -import time - -from module.plugins.Hook import Hook, Expose - - -class WindowsPhoneNotify(Hook): - __name__ = "WindowsPhoneNotify" - __type__ = "hook" - __version__ = "0.09" - - __config__ = [("id" , "str" , "Push ID" , "" ), - ("url" , "str" , "Push url" , "" ), - ("notifycaptcha" , "bool", "Notify captcha request" , True ), - ("notifypackage" , "bool", "Notify package finished" , True ), - ("notifyprocessed", "bool", "Notify packages processed" , True ), - ("notifyupdate" , "bool", "Notify plugin updates" , True ), - ("notifyexit" , "bool", "Notify pyLoad shutdown" , True ), - ("sendtimewait" , "int" , "Timewait in seconds between notifications", 5 ), - ("sendpermin" , "int" , "Max notifications per minute" , 12 ), - ("ignoreclient" , "bool", "Send notifications if client is connected", False)] - - __description__ = """Send push notifications to Windows Phone""" - __license__ = "GPLv3" - __authors__ = [("Andy Voigt" , "phone-support@hotmail.de"), - ("Walter Purcaro", "vuolter@gmail.com" )] - - - event_list = ["allDownloadsProcessed", "plugin_updated"] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.last_notify = 0 - self.notifications = 0 - - - def plugin_updated(self, type_plugins): - if not self.getConfig('notifyupdate'): - return - - self.notify(_("Plugins updated"), str(type_plugins)) - - - def coreExiting(self): - if not self.getConfig('notifyexit'): - return - - if self.core.do_restart: - self.notify(_("Restarting pyLoad")) - else: - self.notify(_("Exiting pyLoad")) - - - def newCaptchaTask(self, task): - if not self.getConfig('notifycaptcha'): - return - - self.notify(_("Captcha"), _("New request waiting user input")) - - - def packageFinished(self, pypack): - if self.getConfig('notifypackage'): - self.notify(_("Package finished"), pypack.name) - - - def allDownloadsProcessed(self): - if not self.getConfig('notifyprocessed'): - return - - if any(True for pdata in self.core.api.getQueue() if pdata.linksdone < pdata.linkstotal): - self.notify(_("Package failed"), _("One or more packages was not completed successfully")) - else: - self.notify(_("All packages finished")) - - - def getXmlData(self, msg): - return ("<?xml version='1.0' encoding='utf-8'?> <wp:Notification xmlns:wp='WPNotification'> " - "<wp:Toast> <wp:Text1>pyLoad</wp:Text1> <wp:Text2>%s</wp:Text2> " - "</wp:Toast> </wp:Notification>" % msg) - - - @Expose - def notify(self, - event, - msg="", - key=(self.getConfig('id'), self.getConfig('url'))): - - id, url = key - - if not id or not url: - return - - if self.core.isClientConnected() and not self.getConfig('ignoreclient'): - return - - elapsed_time = time.time() - self.last_notify - - if elapsed_time < self.getConf("sendtimewait"): - return - - if elapsed_time > 60: - self.notifications = 0 - - elif self.notifications >= self.getConf("sendpermin"): - return - - - request = self.getXmlData("%s: %s" % (event, msg) if msg else event) - webservice = httplib.HTTP(url) - - webservice.putrequest("POST", id) - webservice.putheader("Host", url) - webservice.putheader("Content-type", "text/xml") - webservice.putheader("X-NotificationClass", "2") - webservice.putheader("X-WindowsPhone-Target", "toast") - webservice.putheader("Content-length", "%d" % len(request)) - webservice.endheaders() - webservice.send(request) - webservice.close() - - self.last_notify = time.time() - self.notifications += 1 diff --git a/module/plugins/hooks/XFileSharingPro.py b/module/plugins/hooks/XFileSharingPro.py deleted file mode 100644 index d80515a22..000000000 --- a/module/plugins/hooks/XFileSharingPro.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.Hook import Hook - - -class XFileSharingPro(Hook): - __name__ = "XFileSharingPro" - __type__ = "hook" - __version__ = "0.37" - - __config__ = [("activated" , "bool", "Activated" , True ), - ("use_hoster_list" , "bool", "Load listed hosters only" , False), - ("use_crypter_list", "bool", "Load listed crypters only" , False), - ("use_builtin_list", "bool", "Load built-in plugin list" , True ), - ("hoster_list" , "str" , "Hoster list (comma separated)" , "" ), - ("crypter_list" , "str" , "Crypter list (comma separated)", "" )] - - __description__ = """Load XFileSharingPro based hosters and crypter which don't need a own plugin to run""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - # event_list = ["pluginConfigChanged"] - interval = 0 #@TODO: Remove in 0.4.10 - regexp = {'hoster' : (r'https?://(?:www\.)?(?P<DOMAIN>[\w\-.^_]{3,63}(?:\.[a-zA-Z]{2,})(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)', - r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:embed-)?\w+'), - 'crypter': (r'https?://(?:www\.)?(?P<DOMAIN>[\w\-.^_]{3,63}(?:\.[a-zA-Z]{2,})(?:\:\d+)?)/(?:user|folder)s?/\w+', - r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:user|folder)s?/\w+')} - - HOSTER_BUILTIN = [#WORKING HOSTERS: - "backin.net", "eyesfile.ca", "file4safe.com", "fileband.com", "filedwon.com", "fileparadox.in", - "filevice.com", "hostingbulk.com", "junkyvideo.com", "linestorage.com", "ravishare.com", "ryushare.com", - "salefiles.com", "sendmyway.com", "sharesix.com", "thefile.me", "verzend.be", "xvidstage.com", - #NOT TESTED: - "101shared.com", "4upfiles.com", "filemaze.ws", "filenuke.com", "linkzhost.com", "mightyupload.com", - "rockdizfile.com", "sharebeast.com", "sharerepo.com", "shareswift.com", "uploadbaz.com", "uploadc.com", - "vidbull.com", "worldbytez.com", "zalaa.com", "zomgupload.com", - #NOT WORKING: - "amonshare.com", "banicrazy.info", "boosterking.com", "host4desi.com", "laoupload.com", "rd-fs.com"] - CRYPTER_BUILTIN = ["junocloud.me", "rapidfileshare.net"] - - - # def pluginConfigChanged(self, plugin, name, value): - # self.loadPattern() - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def coreReady(self): - self.loadPattern() - - - def loadPattern(self): - use_builtin_list = self.getConfig('use_builtin_list') - - for type, plugin in (("hoster", "XFileSharingPro"), - ("crypter", "XFileSharingProFolder")): - every_plugin = not self.getConfig("use_%s_list" % type) - - if every_plugin: - self.logInfo(_("Handling any %s I can!") % type) - pattern = self.regexp[type][0] - else: - plugins = self.getConfig('%s_list' % type) - plugin_set = set(plugins.replace(' ', '').replace('\\', '').replace('|', ',').replace(';', ',').lower().split(',')) - - if use_builtin_list: - plugin_set |= set(x.lower() for x in getattr(self, "%s_BUILTIN" % type.upper())) - - plugin_set -= set(('', u'')) - - if not plugin_set: - self.logInfo(_("No %s to handle") % type) - self._unload(type, plugin) - return - - match_list = '|'.join(sorted(plugin_set)) - - len_match_list = len(plugin_set) - self.logInfo(_("Handling %d %s%s: %s") % (len_match_list, - type, - "" if len_match_list == 1 else "s", - match_list.replace('|', ', '))) - - pattern = self.regexp[type][1] % match_list.replace('.', '\.') - - dict = self.core.pluginManager.plugins[type][plugin] - dict['pattern'] = pattern - dict['re'] = re.compile(pattern) - - self.logDebug("Loaded %s pattern: %s" % (type, pattern)) - - - def _unload(self, type, plugin): - dict = self.core.pluginManager.plugins[type][plugin] - dict['pattern'] = r'^unmatchable$' - dict['re'] = re.compile(dict['pattern']) - - - def unload(self): - # self.unloadHoster("BasePlugin") - for type, plugin in (("hoster", "XFileSharingPro"), - ("crypter", "XFileSharingProFolder")): - self._unload(type, plugin) - - - def unloadHoster(self, hoster): - hdict = self.core.pluginManager.hosterPlugins[hoster] - if "new_name" in hdict and hdict['new_name'] == "XFileSharingPro": - if "module" in hdict: - hdict.pop('module', None) - - if "new_module" in hdict: - hdict.pop('new_module', None) - hdict.pop('new_name', None) - - return True - else: - return False - - - # def downloadFailed(self, pyfile): - # if pyfile.pluginname == "BasePlugin" \ - # and pyfile.hasStatus("failed") \ - # and not self.getConfig('use_hoster_list') \ - # and self.unloadHoster("BasePlugin"): - # self.logDebug("Unloaded XFileSharingPro from BasePlugin") - # pyfile.setStatus("queued") diff --git a/module/plugins/hooks/XMPPInterface.py b/module/plugins/hooks/XMPPInterface.py deleted file mode 100644 index b61428392..000000000 --- a/module/plugins/hooks/XMPPInterface.py +++ /dev/null @@ -1,252 +0,0 @@ -# -*- coding: utf-8 -*- - -from pyxmpp import streamtls -from pyxmpp.all import JID, Message -from pyxmpp.interface import implements -from pyxmpp.interfaces import * -from pyxmpp.jabber.client import JabberClient - -from module.plugins.hooks.IRCInterface import IRCInterface - - -class XMPPInterface(IRCInterface, JabberClient): - __name__ = "XMPPInterface" - __type__ = "hook" - __version__ = "0.11" - - __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"), - ("info_file", "bool", "Inform about every file finished", False), - ("info_pack", "bool", "Inform about every package finished", True), - ("captcha", "bool", "Send captcha requests", True)] - - __description__ = """Connect to jabber and let owner perform different tasks""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.org")] - - - implements(IMessageHandlersProvider) - - - def __init__(self, core, manager): - IRCInterface.__init__(self, core, manager) - - self.jid = JID(self.getConfig('jid')) - password = self.getConfig('pw') - - # if bare JID is provided add a resource -- it is required - if not self.jid.resource: - self.jid = JID(self.jid.node, self.jid.domain, "pyLoad") - - if self.getConfig('tls'): - tls_settings = streamtls.TLSSettings(require=True, verify_peer=False) - auth = ("sasl:PLAIN", "sasl:DIGEST-MD5") - else: - tls_settings = None - auth = ("sasl:DIGEST-MD5", "digest") - - # setup client with provided connection information - # and identity data - JabberClient.__init__(self, self.jid, password, - disco_name="pyLoad XMPP Client", disco_type="bot", - tls_settings=tls_settings, auth_methods=auth) - - self.interface_providers = [ - VersionHandler(self), - self, - ] - - - def coreReady(self): - self.new_package = {} - - self.start() - - - def packageFinished(self, pypack): - try: - if self.getConfig('info_pack'): - self.announce(_("Package finished: %s") % pypack.name) - except Exception: - pass - - - def downloadFinished(self, pyfile): - try: - if self.getConfig('info_file'): - self.announce( - _("Download finished: %(name)s @ %(plugin)s") % {"name": pyfile.name, "plugin": pyfile.pluginname}) - except Exception: - pass - - - def run(self): - # connect to IRC etc. - self.connect() - try: - self.loop() - 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. - - The handlers returned will be called when matching message is received - in a client session.""" - return [("normal", self.message)] - - - def message(self, stanza): - """Message handler for the component.""" - subject = stanza.get_subject() - body = stanza.get_body() - t = stanza.get_type() - self.logDebug("Message from %s received." % unicode(stanza.get_from())) - self.logDebug("Body: %s Subject: %s Type: %s" % (body, subject, t)) - - if t == "headline": - # 'headline' messages should never be replied to - return True - if subject: - subject = u"Re: " + subject - - to_jid = stanza.get_from() - from_jid = stanza.get_to() - - #j = JID() - to_name = to_jid.as_utf8() - from_name = from_jid.as_utf8() - - names = self.getConfig('owners').split(";") - - if to_name in names or to_jid.node + "@" + to_jid.domain in names: - messages = [] - - trigger = "pass" - args = None - - try: - temp = body.split() - trigger = temp[0] - if len(temp) > 1: - args = temp[1:] - except Exception: - pass - - handler = getattr(self, "event_%s" % trigger, self.event_pass) - try: - res = handler(args) - for line in res: - m = Message( - to_jid=to_jid, - from_jid=from_jid, - stanza_type=stanza.get_type(), - subject=subject, - body=line) - - messages.append(m) - except Exception, 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(";"): - self.logDebug("Send message to", user) - - to_jid = JID(user) - - m = Message(from_jid=self.jid, - to_jid=to_jid, - stanza_type="chat", - body=message) - - stream = self.get_stream() - if not stream: - self.connect() - stream = self.get_stream() - - stream.send(m) - - - def beforeReconnecting(self, ip): - self.disconnect() - - - def afterReconnecting(self, ip): - self.connect() - - -class VersionHandler(object): - """Provides handler for a version query. - - This class will answer version query and announce 'jabber:iq:version' namespace - in the client's disco#info results.""" - - 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. - - jabber:iq:version queries are not supported directly by PyXMPP, so the - XML node is accessed directly through the libxml2 API. This should be - used very carefully!""" - iq = iq.make_result_response() - q = iq.new_query("jabber:iq:version") - q.newTextChild(q.ns(), "name", "Echo component") - q.newTextChild(q.ns(), "version", "1.0") - return iq diff --git a/module/plugins/hooks/ZeveraComHook.py b/module/plugins/hooks/ZeveraComHook.py deleted file mode 100644 index 21c1741d2..000000000 --- a/module/plugins/hooks/ZeveraComHook.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.MultiHook import MultiHook - - -class ZeveraComHook(MultiHook): - __name__ = "ZeveraComHook" - __type__ = "hook" - __version__ = "0.05" - - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] - - __description__ = """Zevera.com hook plugin""" - __license__ = "GPLv3" - __authors__ = [("zoidberg" , "zoidberg@mujmail.cz"), - ("Walter Purcaro", "vuolter@gmail.com" )] - - - def getHosters(self): - html = self.account.api_response(pyreq.getHTTPRequest(timeout=120), cmd="gethosters") - return [x.strip() for x in html.split(",")] diff --git a/module/plugins/hooks/__init__.py b/module/plugins/hooks/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/module/plugins/hooks/__init__.py +++ /dev/null |