diff options
Diffstat (limited to 'module/plugins/addons')
-rw-r--r-- | module/plugins/addons/AlldebridCom.py | 39 | ||||
-rw-r--r-- | module/plugins/addons/BypassCaptcha.py | 143 | ||||
-rw-r--r-- | module/plugins/addons/CaptchaBrotherhood.py | 169 | ||||
-rw-r--r-- | module/plugins/addons/CaptchaTrader.py | 8 | ||||
-rw-r--r-- | module/plugins/addons/Checksum.py | 123 | ||||
-rw-r--r-- | module/plugins/addons/DeathByCaptcha.py | 210 | ||||
-rw-r--r-- | module/plugins/addons/DownloadScheduler.py | 78 | ||||
-rw-r--r-- | module/plugins/addons/EasybytezCom.py | 18 | ||||
-rw-r--r-- | module/plugins/addons/ExpertDecoders.py | 112 | ||||
-rw-r--r-- | module/plugins/addons/ImageTyperz.py | 160 | ||||
-rw-r--r-- | module/plugins/addons/LinkdecrypterCom.py | 54 | ||||
-rw-r--r-- | module/plugins/addons/MultishareCz.py | 26 | ||||
-rw-r--r-- | module/plugins/addons/PremiumizeMe.py | 65 | ||||
-rw-r--r-- | module/plugins/addons/RealdebridCom.py | 36 | ||||
-rw-r--r-- | module/plugins/addons/XFileSharingPro.py | 74 | ||||
-rw-r--r-- | module/plugins/addons/ZeveraCom.py | 33 |
16 files changed, 1326 insertions, 22 deletions
diff --git a/module/plugins/addons/AlldebridCom.py b/module/plugins/addons/AlldebridCom.py new file mode 100644 index 000000000..f9657ed8c --- /dev/null +++ b/module/plugins/addons/AlldebridCom.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +# should be working + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster + +class AlldebridCom(MultiHoster): + __name__ = "AlldebridCom" + __version__ = "0.11" + __type__ = "hook" + + __config__ = [("activated", "bool", "Activated", "False"), + ("https", "bool", "Enable HTTPS", "False"), + ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"), + ("hosterList", "str", "Hoster list (comma separated)", "")] + + __description__ = """Real-Debrid.com hook plugin""" + __author_name__ = ("Andy, Voigt") + __author_mail__ = ("spamsales@online.de") + + replacements = [("freakshare.net", "freakshare.com")] + + def getHoster(self): + https = "https" if self.getConfig("https") else "http" + page = getURL(https + "://www.alldebrid.com/api.php?action=get_host").replace("\"","").strip() + + hosters = set([x.strip() for x in page.split(",") if x.strip()]) + + configMode = self.getConfig('hosterListMode') + if configMode in ("listed", "unlisted"): + configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(',')) + configList.discard(u'') + if configMode == "listed": + hosters &= configList + else: + hosters -= configList + + return list(hosters) diff --git a/module/plugins/addons/BypassCaptcha.py b/module/plugins/addons/BypassCaptcha.py new file mode 100644 index 000000000..24ad17dd8 --- /dev/null +++ b/module/plugins/addons/BypassCaptcha.py @@ -0,0 +1,143 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: RaNaN, Godofdream, zoidberg +""" + +from thread import start_new_thread +from pycurl import FORM_FILE, LOW_SPEED_TIME + +from module.network.RequestFactory import getURL, getRequest +from module.network.HTTPRequest import BadHeader + +from module.plugins.Hook import Hook + +PYLOAD_KEY = "4f771155b640970d5607f919a615bdefc67e7d32" + +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" + __version__ = "0.03" + __description__ = """send captchas to BypassCaptcha.com""" + __config__ = [("activated", "bool", "Activated", True), + ("force", "bool", "Force BC even if client is connected", False), + ("passkey", "password", "Passkey", "")] + __author_name__ = ("RaNaN", "Godofdream", "zoidberg") + __author_mail__ = ("RaNaN@pyload.org", "soilfcition@gmail.com", "zoidberg@mujmail.cz") + + 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 = {} + + def getCredits(self): + response = getURL(self.GETCREDITS_URL, + post = {"key": self.getConfig("passkey")} + ) + + data = dict([x.split(' ',1) for x in response.splitlines()]) + return int(data['Left']) + + + def submit(self, captcha, captchaType="file", match=None): + req = getRequest() + + #raise timeout threshold + req.c.setopt(LOW_SPEED_TIME, 80) + + try: + response = req.load(self.SUBMIT_URL, + post={"vendor_key": PYLOAD_KEY, + "key": self.getConfig("passkey"), + "gen_task_id": "1", + "file": (FORM_FILE, captcha)}, + multipart=True) + finally: + req.close() + + data = dict([x.split(' ',1) for x in response.splitlines()]) + if not data or "Value" not in data: + raise BypassCaptchaException(response) + + result = data['Value'] + ticket = data['TaskId'] + self.logDebug("result %s : %s" % (ticket,result)) + + return ticket, result + + def respond(self, ticket, success): + try: + response = 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.", str(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) + start_new_thread(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) + + 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)
\ No newline at end of file diff --git a/module/plugins/addons/CaptchaBrotherhood.py b/module/plugins/addons/CaptchaBrotherhood.py new file mode 100644 index 000000000..a22a5ee1d --- /dev/null +++ b/module/plugins/addons/CaptchaBrotherhood.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: mkaay, RaNaN, zoidberg +""" +from __future__ import with_statement + +from thread import start_new_thread + +import pycurl +import StringIO +from urllib import urlencode +from time import sleep +import Image + +from module.network.RequestFactory import getURL, getRequest +from module.network.HTTPRequest import BadHeader +from module.plugins.Hook import Hook + +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" + __version__ = "0.03" + __description__ = """send captchas to CaptchaBrotherhood.com""" + __config__ = [("activated", "bool", "Activated", False), + ("username", "str", "Username", ""), + ("force", "bool", "Force CT even if client is connected", False), + ("passkey", "password", "Password", ""),] + __author_name__ = ("RaNaN", "zoidberg") + __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz") + + API_URL = "http://ocrhood.gazcad.com/" + + def setup(self): + self.info = {} + + def getCredits(self): + response = getURL(self.API_URL + "askCredits.aspx", + get = {"username": self.getConfig("username"), + "password": self.getConfig("passkey")}) + if not response.startswith("OK"): + raise CaptchaBrotherhoodException(response) + else: + credits = int(response[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, + 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() + response = req.getResponse() + except Exception, e: + raise CaptchaBrotherhoodException("Submit captcha image failed") + + req.close() + + if not response.startswith("OK"): + raise CaptchaBrotherhoodException(response[1]) + + ticket = response[3:] + + for i in range(15): + sleep(5) + response = self.get_api("askCaptchaResult", ticket) + if response.startswith("OK-answered"): + return ticket, response[12:] + + raise CaptchaBrotherhoodException("No solution received in time") + + def get_api(self, api, ticket): + response = getURL("%s%s.aspx" % (self.API_URL, api), + get={"username": self.getConfig("username"), + "password": self.getConfig("passkey"), + "captchaID": ticket} + ) + if not response.startswith("OK"): + raise CaptchaBrotherhoodException("Unknown response: %s" % response) + + return response + + 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) + start_new_thread(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: + response = self.get_api("complainCaptcha", task.data['ticket']) + + 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)
\ No newline at end of file diff --git a/module/plugins/addons/CaptchaTrader.py b/module/plugins/addons/CaptchaTrader.py index b3374ec1d..889fa38ef 100644 --- a/module/plugins/addons/CaptchaTrader.py +++ b/module/plugins/addons/CaptchaTrader.py @@ -46,7 +46,7 @@ class CaptchaTraderException(Exception): class CaptchaTrader(Addon): __name__ = "CaptchaTrader" - __version__ = "0.13" + __version__ = "0.14" __description__ = """send captchas to captchatrader.com""" __config__ = [("activated", "bool", "Activated", True), ("username", "str", "Username", ""), @@ -55,9 +55,9 @@ class CaptchaTrader(Addon): __author_name__ = ("RaNaN") __author_mail__ = ("RaNaN@pyload.org") - SUBMIT_URL = "http://captchatrader.com/api/submit" - RESPOND_URL = "http://captchatrader.com/api/respond" - GETCREDITS_URL = "http://captchatrader.com/api/get_credits/username:%(user)s/password:%(password)s/" + SUBMIT_URL = "http://api.captchatrader.com/submit" + RESPOND_URL = "http://api.captchatrader.com/respond" + GETCREDITS_URL = "http://api.captchatrader.com/get_credits/username:%(user)s/password:%(password)s/" def setup(self): self.info = {} diff --git a/module/plugins/addons/Checksum.py b/module/plugins/addons/Checksum.py new file mode 100644 index 000000000..cb6f4bfe8 --- /dev/null +++ b/module/plugins/addons/Checksum.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" +from __future__ import with_statement +import hashlib, zlib +from os.path import getsize, isfile + +from module.utils import save_join, fs_encode +from module.plugins.Hook import Hook + +def computeChecksum(local_file, algorithm): + if algorithm in getattr(hashlib, "algorithms", ("md5", "sha1", "sha224", "sha256", "sha384", "sha512")): + h = getattr(hashlib, algorithm)() + chunk_size = 128 * h.block_size + + with open(local_file, 'rb') as f: + for chunk in iter(lambda: f.read(chunk_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" + __version__ = "0.05" + __description__ = "Verify downloaded file size and checksum (enable in general preferences)" + __config__ = [("activated", "bool", "Activated", True), + ("action", "fail;retry;nothing", "What to do if check fails?", "retry"), + ("max_tries", "int", "Number of retries", 2)] + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + def setup(self): + self.algorithms = sorted(getattr(hashlib, "algorithms", ("md5", "sha1", "sha224", "sha256", "sha384", "sha512")), reverse = True) + self.algorithms.extend(["crc32", "adler32"]) + + if not self.config['general']['checksum']: + self.logInfo("Checksum validation is disabled in general configuration") + + 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() + else: + return + + self.logDebug(data) + + download_folder = self.config['general']['download_folder'] + local_file = fs_encode(save_join(download_folder, pyfile.package().folder, pyfile.name)) + + if not isfile(local_file): + self.checkFailed(pyfile, "File does not exist") + + # validate file size + if "size" in data: + api_size = int(data['size']) + file_size = 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, "Incorrect file size") + del data['size'] + + # validate checksum + if data and self.config['general']['checksum']: + if "checksum" in data: + data['md5'] = data['checksum'] + + for key in self.algorithms: + if key in data: + checksum = computeChecksum(local_file, key.replace("-","").lower()) + if checksum: + if checksum == data[key]: + self.logInfo('File integrity of "%s" verified by %s checksum (%s).' % (pyfile.name, key.upper(), checksum)) + return + else: + self.logWarning("%s checksum for file %s does not match (%s != %s)" % (key.upper(), pyfile.name, checksum, data[key])) + self.checkFailed(pyfile, "Checksums do not match") + else: + self.logWarning("Unsupported hashing algorithm: %s" % key.upper()) + else: + self.logWarning("Unable to validate checksum for file %s" % (pyfile.name)) + + def checkFailed(self, pyfile, msg): + action = self.getConfig("action") + if action == "fail": + pyfile.plugin.fail(reason = msg) + elif action == "retry": + pyfile.plugin.retry(reason = msg, max_tries = self.getConfig("max_tries"))
\ No newline at end of file diff --git a/module/plugins/addons/DeathByCaptcha.py b/module/plugins/addons/DeathByCaptcha.py new file mode 100644 index 000000000..59ff40ded --- /dev/null +++ b/module/plugins/addons/DeathByCaptcha.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: mkaay, RaNaN, zoidberg +""" +from __future__ import with_statement + +from thread import start_new_thread +from pycurl import FORM_FILE, HTTPHEADER, RESPONSE_CODE +from time import sleep +from base64 import b64encode +import re + +from module.network.RequestFactory import getURL, getRequest +from module.network.HTTPRequest import BadHeader +from module.plugins.Hook import Hook +from module.common.json_layer import json_loads + +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" + __version__ = "0.03" + __description__ = """send captchas to DeathByCaptcha.com""" + __config__ = [("activated", "bool", "Activated", False), + ("username", "str", "Username", ""), + ("passkey", "password", "Password", ""), + ("force", "bool", "Force DBC even if client is connected", False)] + __author_name__ = ("RaNaN", "zoidberg") + __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz") + + API_URL = "http://api.dbcapi.me/api/" + + def setup(self): + self.info = {} + + def call_api(self, api="captcha", post=False, multipart=False): + req = getRequest() + req.c.setopt(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")}) + + response = None + try: + json = req.load("%s%s" % (self.API_URL, api), + post = post, + multipart=multipart) + self.logDebug(json) + response = json_loads(json) + + if "error" in response: + raise DeathByCaptchaException(response['error']) + elif "status" not in response: + raise DeathByCaptchaException(str(response)) + + 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 response + + def getCredits(self): + response = self.call_api("user", True) + + if 'is_banned' in response and response['is_banned']: + raise DeathByCaptchaException('banned') + elif 'balance' in response and 'rate' in response: + self.info.update(response) + else: + raise DeathByCaptchaException(response) + + def getStatus(self): + response = self.call_api("status", False) + + if 'is_service_overloaded' in response and response['is_service_overloaded']: + raise DeathByCaptchaException('service-overload') + + def submit(self, captcha, captchaType="file", match=None): + #workaround multipart-post bug in HTTPRequest.py + if re.match("^[A-Za-z0-9]*$", self.getConfig("passkey")): + multipart = True + data = (FORM_FILE, captcha) + else: + multipart = False + with open(captcha, 'rb') as f: + data = f.read() + data = "base64:" + b64encode(data) + + response = self.call_api("captcha", {"captchafile": data}, multipart) + + if "captcha" not in response: + raise DeathByCaptchaException(response) + ticket = response['captcha'] + + for i in range(24): + sleep(5) + response = self.call_api("captcha/%d" % ticket, False) + if response['text'] and response['is_correct']: + break + else: + raise DeathByCaptchaException('timed-out') + + result = response['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) + start_new_thread(self.processCaptcha, (task,)) + + def captchaInvalid(self, task): + if task.data['service'] == self.__name__ and "ticket" in task.data: + try: + response = self.call_api("captcha/%d/report" % task.data["ticket"], True) + except DeathByCaptchaException, e: + self.logError(e.getDesc()) + except Exception, e: + self.logError(e) + + 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)
\ No newline at end of file diff --git a/module/plugins/addons/DownloadScheduler.py b/module/plugins/addons/DownloadScheduler.py new file mode 100644 index 000000000..7cadede38 --- /dev/null +++ b/module/plugins/addons/DownloadScheduler.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg + Original idea by new.cze +""" + +import re +from time import localtime +from module.plugins.Hook import Hook + +class DownloadScheduler(Hook): + __name__ = "DownloadScheduler" + __version__ = "0.20" + __description__ = """Download Scheduler""" + __config__ = [("activated", "bool", "Activated", "False"), + ("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")] + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + def setup(self): + 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 = 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: + self.logInfo("Stopping download server. (Running downloads will not be aborted.)") + self.core.api.pauseServer() + 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)
\ No newline at end of file diff --git a/module/plugins/addons/EasybytezCom.py b/module/plugins/addons/EasybytezCom.py index 4dd39cca6..21a988555 100644 --- a/module/plugins/addons/EasybytezCom.py +++ b/module/plugins/addons/EasybytezCom.py @@ -11,11 +11,11 @@ def getConfigSet(option): class EasybytezCom(MultiHoster): __name__ = "EasybytezCom" - __version__ = "0.01" + __version__ = "0.02" __type__ = "hook" __config__ = [("activated", "bool", "Activated", "False"), - ("includeHoster", "str", "Use only for downloads from (comma-separated hosters)", ""), - ("excludeHoster", "str", "Do not use for downloads from (comma-separated hosters)", "")] + ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"), + ("hosterList", "str", "Hoster list (comma separated)", "")] __description__ = """EasyBytez.com hook plugin""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") @@ -24,9 +24,13 @@ class EasybytezCom(MultiHoster): hoster = set(['2shared.com', 'easy-share.com', 'filefactory.com', 'fileserve.com', 'filesonic.com', 'hotfile.com', 'mediafire.com', 'megaupload.com', 'netload.in', 'rapidshare.com', 'uploading.com', 'wupload.com', 'oron.com', 'uploadstation.com', 'ul.to', 'uploaded.to']) - option = self.getConfig('includeHoster').strip() - if option: hoster &= getConfigSet(option) - option = self.getConfig('excludeHoster').strip() - if option: hoster -= getConfigSet(option) + configMode = self.getConfig('hosterListMode') + if configMode in ("listed", "unlisted"): + configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(',')) + configList.discard(u'') + if configMode == "listed": + hoster &= configList + else: + hoster -= configList return list(hoster)
\ No newline at end of file diff --git a/module/plugins/addons/ExpertDecoders.py b/module/plugins/addons/ExpertDecoders.py new file mode 100644 index 000000000..2e66e49ca --- /dev/null +++ b/module/plugins/addons/ExpertDecoders.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: mkaay, RaNaN, zoidberg +""" +from __future__ import with_statement + +from thread import start_new_thread +from pycurl import FORM_FILE, LOW_SPEED_TIME +from uuid import uuid4 +from base64 import b64encode + +from module.network.RequestFactory import getURL, getRequest +from module.network.HTTPRequest import BadHeader + +from module.plugins.Hook import Hook + +class ExpertDecoders(Hook): + __name__ = "ExpertDecoders" + __version__ = "0.01" + __description__ = """send captchas to expertdecoders.com""" + __config__ = [("activated", "bool", "Activated", False), + ("force", "bool", "Force CT even if client is connected", False), + ("passkey", "password", "Access key", ""),] + __author_name__ = ("RaNaN", "zoidberg") + __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz") + + API_URL = "http://www.fasttypers.org/imagepost.ashx" + + def setup(self): + self.info = {} + + def getCredits(self): + response = getURL(self.API_URL, post = { "key": self.getConfig("passkey"), "action": "balance" }) + + if response.isdigit(): + self.logInfo(_("%s credits left") % response) + self.info["credits"] = credits = int(response) + return credits + else: + self.logError(response) + return 0 + + def processCaptcha(self, task): + task.data["ticket"] = ticket = uuid4() + result = None + + with open(task.captchaFile, 'rb') as f: + data = f.read() + data = b64encode(data) + #self.logDebug("%s: %s : %s" % (ticket, task.captchaFile, data)) + + req = getRequest() + #raise timeout threshold + req.c.setopt(LOW_SPEED_TIME, 80) + + try: + result = req.load(self.API_URL, + post={ "action": "upload", + "key": self.getConfig("passkey"), + "file": 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) + start_new_thread(self.processCaptcha, (task,)) + + else: + self.logInfo(_("Your ExpertDecoders Account has not enough credits")) + + def captchaInvalid(self, task): + if "ticket" in task.data: + + try: + response = getURL(self.API_URL, + post={ "action": "refund", + "key": self.getConfig("passkey"), + "gen_task_id": task.data["ticket"] } + ) + self.logInfo("Request refund: %s" % response) + + except BadHeader, e: + self.logError("Could not send refund request.", str(e))
\ No newline at end of file diff --git a/module/plugins/addons/ImageTyperz.py b/module/plugins/addons/ImageTyperz.py new file mode 100644 index 000000000..59b6334a7 --- /dev/null +++ b/module/plugins/addons/ImageTyperz.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: mkaay, RaNaN, zoidberg +""" +from __future__ import with_statement + +from thread import start_new_thread +from pycurl import FORM_FILE, LOW_SPEED_TIME + +from module.network.RequestFactory import getURL, getRequest +from module.network.HTTPRequest import BadHeader + +from module.plugins.Hook import Hook +import re +from base64 import b64encode + +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" + __version__ = "0.03" + __description__ = """send captchas to ImageTyperz.com""" + __config__ = [("activated", "bool", "Activated", True), + ("username", "str", "Username", ""), + ("passkey", "password", "Password", ""), + ("force", "bool", "Force IT even if client is connected", False)] + __author_name__ = ("RaNaN", "zoidberg") + __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz") + + 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 = {} + + def getCredits(self): + response = getURL(self.GETCREDITS_URL, + post = {"action": "REQUESTBALANCE", + "username": self.getConfig("username"), + "password": self.getConfig("passkey")} + ) + + if response.startswith('ERROR'): + raise ImageTyperzException(response) + + try: + balance = float(response) + except: + raise ImageTyperzException("invalid response") + + self.logInfo("Account balance: $%s left" % response) + return balance + + def submit(self, captcha, captchaType="file", match=None): + req = getRequest() + #raise timeout threshold + req.c.setopt(LOW_SPEED_TIME, 80) + + try: + #workaround multipart-post bug in HTTPRequest.py + if re.match("^[A-Za-z0-9]*$", self.getConfig("passkey")): + multipart = True + data = (FORM_FILE, captcha) + else: + multipart = False + with open(captcha, 'rb') as f: + data = f.read() + data = b64encode(data) + + response = req.load(self.SUBMIT_URL, + post={ "action": "UPLOADCAPTCHA", + "username": self.getConfig("username"), + "password": self.getConfig("passkey"), + "file": data}, + multipart = multipart) + finally: + req.close() + + if response.startswith("ERROR"): + raise ImageTyperzException(response) + else: + data = response.split('|') + if len(data) == 2: + ticket, result = data + else: + raise ImageTyperzException("Unknown response %s" % response) + + 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) + start_new_thread(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: + response = getURL(self.RESPOND_URL, + post={"action": "SETBADIMAGE", + "username": self.getConfig("username"), + "password": self.getConfig("passkey"), + "imageid": task.data["ticket"]} + ) + + if response == "SUCCESS": + self.logInfo("Bad captcha solution received, requested refund") + else: + self.logError("Bad captcha solution received, refund request failed", response) + + 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)
\ No newline at end of file diff --git a/module/plugins/addons/LinkdecrypterCom.py b/module/plugins/addons/LinkdecrypterCom.py new file mode 100644 index 000000000..ac939afd9 --- /dev/null +++ b/module/plugins/addons/LinkdecrypterCom.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: zoidberg +""" + +import re + +from module.plugins.Hook import Hook +from module.network.RequestFactory import getURL +from module.utils import remove_chars + +class LinkdecrypterCom(Hook): + __name__ = "LinkdecrypterCom" + __version__ = "0.14" + __description__ = """linkdecrypter.com - regexp loader""" + __config__ = [ ("activated", "bool", "Activated" , "True") ] + __author_name__ = ("zoidberg") + + def coreReady(self): + page = getURL("http://linkdecrypter.com/") + m = re.search(r'<b>Supported</b>: <i>([^+<]*)', page) + if not m: + self.logError(_("Crypter list not found")) + return + + online = m.group(1).split(', ') + builtin = [ name.lower() for name in self.core.pluginManager.crypterPlugins.keys() ] + builtin.extend([ "downloadserienjunkiesorg" ]) + + online = [ crypter.replace(".", "\\.") for crypter in online if remove_chars(crypter, "-.") not in builtin ] + if not online: + self.logError(_("Crypter list is empty")) + return + + regexp = r"https?://([^.]+\.)*?(%s)/.*" % "|".join(online) + + dict = self.core.pluginManager.crypterPlugins[self.__name__] + dict["pattern"] = regexp + dict["re"] = re.compile(regexp) + + self.logDebug("REGEXP: " + regexp)
\ No newline at end of file diff --git a/module/plugins/addons/MultishareCz.py b/module/plugins/addons/MultishareCz.py index a934f43ef..a00c6cb2b 100644 --- a/module/plugins/addons/MultishareCz.py +++ b/module/plugins/addons/MultishareCz.py @@ -11,26 +11,30 @@ def getConfigSet(option): class MultishareCz(MultiHoster): __name__ = "MultishareCz" - __version__ = "0.01" + __version__ = "0.03" __type__ = "hook" __config__ = [("activated", "bool", "Activated", "False"), - ("includeHoster", "str", "Use only for downloads from (bar-separated hosters)", ""), - ("excludeHoster", "str", "Do not use for downloads from (bar-separated hosters)", "rapidshare.com|uloz.to")] + ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"), + ("hosterList", "str", "Hoster list (comma separated)", "uloz.to")] __description__ = """MultiShare.cz hook plugin""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") - #replacements = [("freakshare.net", "freakshare.com")] - HOSTER_PATTERN = r'<img class="logo-shareserveru"[^>]*alt="([^"]+)"></td>\s*<td class="stav"><img src="/img/loga/ok.png" alt="OK">' + replacements = [("share-rapid.cz", "sharerapid.com")] + HOSTER_PATTERN = r'<img class="logo-shareserveru"[^>]*?alt="([^"]+)"></td>\s*<td class="stav">[^>]*?alt="OK"' def getHoster(self): page = getURL("http://www.multishare.cz/monitoring/") - hoster = set(m.group(1).lower() for m in re.finditer(self.HOSTER_PATTERN, page)) + hosters = set(h.lower().strip() for h in re.findall(self.HOSTER_PATTERN, page)) - option = self.getConfig('includeHoster').strip() - if option: hoster &= getConfigSet(option) - option = self.getConfig('excludeHoster').strip() - if option: hoster -= getConfigSet(option) + configMode = self.getConfig('hosterListMode') + if configMode in ("listed", "unlisted"): + configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(',')) + configList.discard(u'') + if configMode == "listed": + hosters &= configList + elif configMode == "unlisted": + hosters -= configList - return list(hoster)
\ No newline at end of file + return list(hosters)
\ No newline at end of file diff --git a/module/plugins/addons/PremiumizeMe.py b/module/plugins/addons/PremiumizeMe.py new file mode 100644 index 000000000..3825e9219 --- /dev/null +++ b/module/plugins/addons/PremiumizeMe.py @@ -0,0 +1,65 @@ +from module.plugins.internal.MultiHoster import MultiHoster + +from module.common.json_layer import json_loads +from module.network.RequestFactory import getURL + +class PremiumizeMe(MultiHoster): + __name__ = "PremiumizeMe" + __version__ = "0.1" + __type__ = "hook" + __description__ = """Premiumize.Me hook plugin""" + + __config__ = [("activated", "bool", "Activated", "False"), + ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported):", "all"), + ("hosterList", "str", "Hoster list (comma separated)", "")] + + __author_name__ = ("Florian Franzen") + __author_mail__ = ("FlorianFranzen@gmail.com") + + replacements = [("freakshare.net", "freakshare.com")] + + interval = 0 # Disable periodic calls, we dont use them anyway + + def getHoster(self): + # If no accounts are available there will be no hosters available + if not self.account or not self.account.canUse(): + return [] + + # 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 = getURL("https://api.premiumize.me/pm-api/v1.php?method=hosterlist¶ms[login]=%s¶ms[pass]=%s" % (user, 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 + hosters = set(data['result']['hosterlist']) + + + # Read config to check if certain hosters should not be handled + configMode = self.getConfig('hosterListMode') + if configMode in ("listed", "unlisted"): + configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(',')) + configList.discard(u'') + if configMode == "listed": + hosters &= configList + else: + hosters -= configList + + return list(hosters) + + def coreReady(self): + # Get account plugin and check if there is a valid account available + self.account = self.core.accountManager.getAccountPlugin("PremiumizeMe") + if not self.account.canUse(): + self.account = None + self.logError(_("Please add a valid premiumize.me account first and restart pyLoad.")) + return + + # Run the overwriten core ready which actually enables the multihoster hook + return MultiHoster.coreReady(self)
\ No newline at end of file diff --git a/module/plugins/addons/RealdebridCom.py b/module/plugins/addons/RealdebridCom.py new file mode 100644 index 000000000..bd3179673 --- /dev/null +++ b/module/plugins/addons/RealdebridCom.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster + +class RealdebridCom(MultiHoster): + __name__ = "RealdebridCom" + __version__ = "0.41" + __type__ = "hook" + + __config__ = [("activated", "bool", "Activated", "False"), + ("https", "bool", "Enable HTTPS", "False"), + ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported):", "all"), + ("hosterList", "str", "Hoster list (comma separated)", "")] + __description__ = """Real-Debrid.com hook plugin""" + __author_name__ = ("Devirex, Hazzard") + __author_mail__ = ("naibaf_11@yahoo.de") + + replacements = [("freakshare.net", "freakshare.com")] + + def getHoster(self): + https = "https" if self.getConfig("https") else "http" + page = getURL(https + "://real-debrid.com/api/hosters.php").replace("\"","").strip() + + hosters = set([x.strip() for x in page.split(",") if x.strip()]) + + configMode = self.getConfig('hosterListMode') + if configMode in ("listed", "unlisted"): + configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(',')) + configList.discard(u'') + if configMode == "listed": + hosters &= configList + else: + hosters -= configList + + return list(hosters) diff --git a/module/plugins/addons/XFileSharingPro.py b/module/plugins/addons/XFileSharingPro.py new file mode 100644 index 000000000..3981db2d0 --- /dev/null +++ b/module/plugins/addons/XFileSharingPro.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- + +from module.plugins.Hook import Hook +import re + +class XFileSharingPro(Hook): + __name__ = "XFileSharingPro" + __version__ = "0.03" + __type__ = "hook" + __config__ = [ ("activated" , "bool" , "Activated" , "True"), + ("loadDefault", "bool", "Include default (built-in) hoster list" , "True"), + ("includeList", "str", "Include hosters (comma separated)", ""), + ("excludeList", "str", "Exclude hosters (comma separated)", "") ] + __description__ = """Hoster URL pattern loader for the generic XFileSharingPro plugin""" + __author_name__ = ("zoidberg") + __author_mail__ = ("zoidberg@mujmail.cz") + + def coreReady(self): + self.loadPattern() + + def loadPattern(self): + hosterList = self.getConfigSet('includeList') + excludeList = self.getConfigSet('excludeList') + + if self.getConfig('loadDefault'): + hosterList |= set(( + #WORKING HOSTERS: + "azsharing.com", "banashare.com", "fileband.com", "kingsupload.com", "migahost.com", "ryushare.com", "xfileshare.eu", + #NOT TESTED: + "aieshare.com", "amonshare.com", "asixfiles.com", + "bebasupload.com", "boosterking.com", "buckshare.com", "bulletupload.com", "crocshare.com", "ddlanime.com", "divxme.com", + "dopeshare.com", "downupload.com", "eyesfile.com", "eyvx.com", "fik1.com", "file4safe.com", "file4sharing.com", + "fileforth.com", "filemade.com", "filemak.com", "fileplaygroud.com", "filerace.com", "filestrack.com", + "fileupper.com", "filevelocity.com", "fooget.com", "4bytez.com", "freefilessharing.com", "glumbouploads.com", "grupload.com", + "heftyfile.com", "hipfile.com", "host4desi.com", "hulkshare.com", "idupin.com", "imageporter.com", "isharefast.com", + "jalurcepat.com", "laoupload.com", "linkzhost.com", "loombo.com", "maknyos.com", + "mlfat4arab.com", "movreel.com", "netuploaded.com", "ok2upload.com", "180upload.com", "1hostclick.com", "ovfile.com", + "putshare.com", "pyramidfiles.com", "q4share.com", "queenshare.com", "ravishare.com", "rockdizfile.com", "sendmyway.com", + "share76.com", "sharebeast.com", "sharehut.com", "sharerun.com", "shareswift.com", "sharingonline.com", "6ybh-upload.com", + "skipfile.com", "spaadyshare.com", "space4file.com", "speedoshare.com", "uploadbaz.com", "uploadboost.com", "uploadc.com", + "uploaddot.com", "uploadfloor.com", "uploadic.com", "uploadville.com", "uptobox.com", "vidbull.com", "zalaa.com", + "zomgupload.com", "kupload.org", "movbay.org", "multishare.org", "omegave.org", "toucansharing.org", "uflinq.org", + "banicrazy.info", "flowhot.info", "upbrasil.info", "shareyourfilez.biz", "bzlink.us", "cloudcache.cc", "fileserver.cc" + "farshare.to", "kingshare.to", "filemaze.ws", "filehost.ws", "goldfile.eu", "filestock.ru", "moidisk.ru" + "4up.me", "kfiles.kz", "odsiebie.pl", "upchi.co.il", "upit.in", "verzend.be" + )) + + #NOT WORKING: + """ + """ + + hosterList -= (excludeList) + hosterList -= set(('', u'')) + + if not hosterList: + self.unload() + return + + regexp = r"http://(?:[^/]*\.)?(%s)/\w{12}" % ("|".join(sorted(hosterList)).replace('.','\.')) + #self.logDebug(regexp) + + dict = self.core.pluginManager.hosterPlugins['XFileSharingPro'] + dict["pattern"] = regexp + dict["re"] = re.compile(regexp) + self.logDebug("Pattern loaded - handling %d hosters" % len(hosterList)) + + def getConfigSet(self, option): + s = self.getConfig(option).lower().replace('|',',').replace(';',',') + return set([x.strip() for x in s.split(',')]) + + def unload(self): + dict = self.core.pluginManager.hosterPlugins['XFileSharingPro'] + dict["pattern"] = r"^unmatchable$" + dict["re"] = re.compile(r"^unmatchable$")
\ No newline at end of file diff --git a/module/plugins/addons/ZeveraCom.py b/module/plugins/addons/ZeveraCom.py new file mode 100644 index 000000000..46c752c21 --- /dev/null +++ b/module/plugins/addons/ZeveraCom.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster + +class ZeveraCom(MultiHoster): + __name__ = "ZeveraCom" + __version__ = "0.01" + __type__ = "hook" + __config__ = [("activated", "bool", "Activated", "False"), + ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"), + ("hosterList", "str", "Hoster list (comma separated)", "")] + __description__ = """Real-Debrid.com hook plugin""" + __author_name__ = ("Devirex, Hazzard") + __author_mail__ = ("naibaf_11@yahoo.de") + + replacements = [("freakshare.net", "freakshare.com"), ("2shared.com", "twoshared.com"), ("4shared.com", "fourshared.com"), + ("easy-share.com", "crocko.com"), ("hellshare.com", "hellshare.cz")] + + def getHoster(self): + page = getURL("http://www.zevera.com/jDownloader.ashx?cmd=gethosters") + hosters = set([x.strip() for x in page.replace("\"", "").split(",")]) + + configMode = self.getConfig('hosterListMode') + if configMode in ("listed", "unlisted"): + configList = set(self.getConfig('hosterList').strip().lower().replace('|',',').replace(';',',').split(',')) + configList.discard(u'') + if configMode == "listed": + hosters &= configList + else: + hosters -= configList + + return list(hosters)
\ No newline at end of file |