diff options
Diffstat (limited to 'pyload/plugin/hook/CaptchaBrotherhood.py')
| -rw-r--r-- | pyload/plugin/hook/CaptchaBrotherhood.py | 172 | 
1 files changed, 172 insertions, 0 deletions
| diff --git a/pyload/plugin/hook/CaptchaBrotherhood.py b/pyload/plugin/hook/CaptchaBrotherhood.py new file mode 100644 index 000000000..eff005d14 --- /dev/null +++ b/pyload/plugin/hook/CaptchaBrotherhood.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement + +import StringIO +import pycurl +import time + +try: +    from PIL import Image +except ImportError: +    import Image + +from urllib import urlencode + +from pyload.network.RequestFactory import getURL, getRequest +from pyload.plugin.Hook import Hook, threaded + + +class CaptchaBrotherhoodException(Exception): + +    def __init__(self, err): +        self.err = err + + +    def getCode(self): +        return self.err + + +    def __str__(self): +        return "<CaptchaBrotherhoodException %s>" % self.err + + +    def __repr__(self): +        return "<CaptchaBrotherhoodException %s>" % self.err + + +class CaptchaBrotherhood(Hook): +    __name    = "CaptchaBrotherhood" +    __type    = "hook" +    __version = "0.08" + +    __config = [("username", "str", "Username", ""), +                ("force", "bool", "Force CT even if client is connected", False), +                ("passkey", "password", "Password", "")] + +    __description = """Send captchas to CaptchaBrotherhood.com""" +    __license     = "GPLv3" +    __authors     = [("RaNaN"   , "RaNaN@pyload.org"   ), +                       ("zoidberg", "zoidberg@mujmail.cz")] + + +    API_URL = "http://www.captchabrotherhood.com/" + + +    def activate(self): +        if self.getConfig('ssl'): +            self.API_URL = self.API_URL.replace("http://", "https://") + + +    def getCredits(self): +        res = getURL(self.API_URL + "askCredits.aspx", +                     get={"username": self.getConfig('username'), "password": self.getConfig('passkey')}) +        if not res.startswith("OK"): +            raise CaptchaBrotherhoodException(res) +        else: +            credits = int(res[3:]) +            self.logInfo(_("%d credits left") % credits) +            self.info['credits'] = credits +            return credits + + +    def submit(self, captcha, captchaType="file", match=None): +        try: +            img = Image.open(captcha) +            output = StringIO.StringIO() +            self.logDebug("CAPTCHA IMAGE", img, img.format, img.mode) +            if img.format in ("GIF", "JPEG"): +                img.save(output, img.format) +            else: +                if img.mode != "RGB": +                    img = img.convert("RGB") +                img.save(output, "JPEG") +            data = output.getvalue() +            output.close() +        except Exception, e: +            raise CaptchaBrotherhoodException("Reading or converting captcha image failed: %s" % e) + +        req = getRequest() + +        url = "%ssendNewCaptcha.aspx?%s" % (self.API_URL, +                                            urlencode({'username'     : self.getConfig('username'), +                                                       'password'     : self.getConfig('passkey'), +                                                       'captchaSource': "pyLoad", +                                                       'timeout'      : "80"})) + +        req.c.setopt(pycurl.URL, url) +        req.c.setopt(pycurl.POST, 1) +        req.c.setopt(pycurl.POSTFIELDS, data) +        req.c.setopt(pycurl.HTTPHEADER, ["Content-Type: text/html"]) + +        try: +            req.c.perform() +            res = req.getResponse() +        except Exception, e: +            raise CaptchaBrotherhoodException("Submit captcha image failed") + +        req.close() + +        if not res.startswith("OK"): +            raise CaptchaBrotherhoodException(res[1]) + +        ticket = res[3:] + +        for _i in xrange(15): +            time.sleep(5) +            res = self.api_response("askCaptchaResult", ticket) +            if res.startswith("OK-answered"): +                return ticket, res[12:] + +        raise CaptchaBrotherhoodException("No solution received in time") + + +    def api_response(self, api, ticket): +        res = getURL("%s%s.aspx" % (self.API_URL, api), +                          get={"username": self.getConfig('username'), +                               "password": self.getConfig('passkey'), +                               "captchaID": ticket}) +        if not res.startswith("OK"): +            raise CaptchaBrotherhoodException("Unknown response: %s" % res) + +        return res + + +    def captchaTask(self, task): +        if "service" in task.data: +            return False + +        if not task.isTextual(): +            return False + +        if not self.getConfig('username') or not self.getConfig('passkey'): +            return False + +        if self.core.isClientConnected() and not self.getConfig('force'): +            return False + +        if self.getCredits() > 10: +            task.handler.append(self) +            task.data['service'] = self.__name +            task.setWaiting(100) +            self._processCaptcha(task) +        else: +            self.logInfo(_("Your CaptchaBrotherhood Account has not enough credits")) + + +    def captchaInvalid(self, task): +        if task.data['service'] == self.__name and "ticket" in task.data: +            res = self.api_response("complainCaptcha", task.data['ticket']) + + +    @threaded +    def _processCaptcha(self, task): +        c = task.captchaFile +        try: +            ticket, result = self.submit(c) +        except CaptchaBrotherhoodException, e: +            task.error = e.getCode() +            return + +        task.data['ticket'] = ticket +        task.setResult(result) | 
