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 | 
