diff options
-rw-r--r-- | module/plugins/crypter/LinkdecrypterCom.py | 62 | ||||
-rw-r--r-- | module/plugins/hoster/HellshareCz.py | 76 | ||||
-rw-r--r-- | module/plugins/internal/SimpleHoster.py | 75 |
3 files changed, 78 insertions, 135 deletions
diff --git a/module/plugins/crypter/LinkdecrypterCom.py b/module/plugins/crypter/LinkdecrypterCom.py index ff21916ef..69d2f8192 100644 --- a/module/plugins/crypter/LinkdecrypterCom.py +++ b/module/plugins/crypter/LinkdecrypterCom.py @@ -22,79 +22,79 @@ from module.plugins.Crypter import Crypter class LinkdecrypterCom(Crypter): __name__ = "LinkdecrypterCom" __type__ = "crypter" - __version__ = "0.26" + __version__ = "0.27" __description__ = """linkdecrypter.com""" __author_name__ = ("zoidberg", "flowlee") - + TEXTAREA_PATTERN = r'<textarea name="links" wrap="off" readonly="1" class="caja_des">(.+)</textarea>' PASSWORD_PATTERN = r'<input type="text" name="password"' CAPTCHA_PATTERN = r'<img class="captcha" src="(.+?)"(.*?)>' REDIR_PATTERN = r'<i>(Click <a href="./">here</a> if your browser does not redirect you).</i>' - + def decrypt(self, pyfile): self.passwords = self.getPassword().splitlines() - + # API not working anymore - new_links = self.decryptHTML() + new_links = self.decryptHTML() if new_links: self.core.files.addLinks(new_links, self.pyfile.package().id) else: - self.fail('Could not extract any links') + self.fail('Could not extract any links') def decryptAPI(self): - - get_dict = { "t": "link", "url": self.pyfile.url, "lcache": "1" } + + get_dict = { "t": "link", "url": self.pyfile.url, "lcache": "1" } self.html = self.load('http://linkdecrypter.com/api', get = get_dict) if self.html.startswith('http://'): return self.html.splitlines() - + if self.html == 'INTERRUPTION(PASSWORD)': for get_dict['pass'] in self.passwords: self.html = self.load('http://linkdecrypter.com/api', get= get_dict) - if self.html.startswith('http://'): return self.html.splitlines() - + if self.html.startswith('http://'): return self.html.splitlines() + self.logError('API', self.html) if self.html == 'INTERRUPTION(PASSWORD)': self.fail("No or incorrect password") - - return None - + + return None + def decryptHTML(self): retries = 5 - - post_dict = { "link_cache": "on", "pro_links": self.pyfile.url, "modo_links": "text" } - self.html = self.load('http://linkdecrypter.com/', post = post_dict, cookies = True) - - while self.passwords or retries: - found = re.search(self.TEXTAREA_PATTERN, self.html, flags=re.DOTALL) + + post_dict = { "link_cache": "on", "pro_links": self.pyfile.url, "modo_links": "text" } + self.html = self.load('http://linkdecrypter.com/', post=post_dict, cookies=True, decode=True) + + while self.passwords or retries: + found = re.search(self.TEXTAREA_PATTERN, self.html, flags=re.DOTALL) if found: return [ x for x in found.group(1).splitlines() if '[LINK-ERROR]' not in x ] - + found = re.search(self.CAPTCHA_PATTERN, self.html) if found: captcha_url = 'http://linkdecrypter.com/' + found.group(1) result_type = "positional" if "getPos" in found.group(2) else "textual" - + found = re.search(r"<p><i><b>([^<]+)</b></i></p>", self.html) msg = found.group(1) if found else "" self.logInfo("Captcha protected link", result_type, msg) - + captcha = self.decryptCaptcha(captcha_url, result_type = result_type) if result_type == "positional": captcha = "%d|%d" % captcha - self.html = self.load('http://linkdecrypter.com/', post={ "captcha": captcha }) + self.html = self.load('http://linkdecrypter.com/', post={ "captcha": captcha }, decode=True) retries -= 1 - + elif self.PASSWORD_PATTERN in self.html: if self.passwords: password = self.passwords.pop(0) self.logInfo("Password protected link, trying " + password) - self.html = self.load('http://linkdecrypter.com/', post= {'password': password}) + self.html = self.load('http://linkdecrypter.com/', post={'password': password}, decode=True) else: self.fail("No or incorrect password") - + else: - retries -= 1 - self.html = self.load('http://linkdecrypter.com/', cookies = True) - - return None
\ No newline at end of file + retries -= 1 + self.html = self.load('http://linkdecrypter.com/', cookies=True, decode=True) + + return None diff --git a/module/plugins/hoster/HellshareCz.py b/module/plugins/hoster/HellshareCz.py index 15d00be70..fd9f2ac32 100644 --- a/module/plugins/hoster/HellshareCz.py +++ b/module/plugins/hoster/HellshareCz.py @@ -17,25 +17,22 @@ """ import re -import datetime from math import ceil from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from module.network.RequestFactory import getURL + class HellshareCz(SimpleHoster): __name__ = "HellshareCz" __type__ = "hoster" __pattern__ = r"(http://(?:.*\.)*hellshare\.(?:cz|com|sk|hu|pl)/[^?]*/\d+).*" - __version__ = "0.80" - __description__ = """Hellshare.cz""" + __version__ = "0.81" + __description__ = """Hellshare.cz - premium only""" __author_name__ = ("zoidberg") - FREE_URL_PATTERN = r'<form[^>]*action="(http://free\d*\.helldata[^"]*)"' PREMIUM_URL_PATTERN = r"launchFullDownload\('([^']*)'\);" FILE_NAME_PATTERN = r'<h1 id="filename"[^>]*>(?P<N>[^<]+)</h1>' FILE_SIZE_PATTERN = r'<strong id="FileSize_master">(?P<S>[0-9.]*) (?P<U>[kKMG])i?B</strong>' FILE_OFFLINE_PATTERN = r'<h1>File not found.</h1>' - CAPTCHA_PATTERN = r'<img class="left" id="captcha-img"src="([^"]*)" />' #FILE_CREDITS_PATTERN = r'<strong class="filesize">(\d+) MB</strong>' CREDIT_LEFT_PATTERN = r'<th>(\d+)</th><td>credits' DOWNLOAD_AGAIN_PATTERN = r'<p>This file you downloaded already and re-download is for free. </p>' @@ -46,65 +43,15 @@ class HellshareCz(SimpleHoster): self.chunkLimit = 1 def process(self, pyfile): + if not self.account: self.fail("User not logged in") pyfile.url = re.search(self.__pattern__, pyfile.url).group(1) self.html = self.load(pyfile.url, decode = True) self.getFileInfo() - + found = re.search(self.SHOW_WINDOW_PATTERN, self.html) if not found: self.parseError('SHOW WINDOW') - self.url = "http://www.hellshare.com" + found.group(1) - self.logDebug("SHOW WINDOW: " + self.url) - self.html = self.load(self.url, decode=True) - - if self.account: - self.handlePremium() - else: - self.handleFree() - - def handleFree(self): - # hellshare is very generous - if "You exceeded your today's limit for free download. You can download only 1 files per 24 hours." in self.html: - t = datetime.datetime.today().replace(hour=1, minute=0, second=0) + datetime.timedelta( - days=1) - datetime.datetime.today() - self.setWait(t.seconds, True) - self.wait() - self.retry() - - while "Server load: 100%" in self.html: - self.setWait(60) - self.wait() - self.html = self.load(self.url, decode=True) - - # parse free download url - found = re.search(self.FREE_URL_PATTERN, self.html) - if found is None: self.parseError("Free URL)") - parsed_url = found.group(1) - self.logDebug("Free URL: %s" % parsed_url) - - # decrypt captcha - found = re.search(self.CAPTCHA_PATTERN, self.html) - if found is None: self.parseError("Captcha") - captcha_url = found.group(1) - - captcha = self.decryptCaptcha(captcha_url) - self.logDebug('CAPTCHA_URL:' + captcha_url + ' CAPTCHA:' + captcha) - - self.download(parsed_url, post = {"captcha" : captcha, "submit" : "Download"}) - - # check download - check = self.checkDownload({ - "wrong_captcha": re.compile(self.FREE_URL_PATTERN) - }) - - if check == "wrong_captcha": - self.invalidCaptcha() - self.retry() - - def handlePremium(self): - # get premium download url - found = re.search(self.PREMIUM_URL_PATTERN, self.html) - if found is None: self.fail("Parse error (URL)") - download_url = found.group(1) + self.url = "http://www.hellshare.com" + found.group(1) + self.logDebug("DOWNLOAD URL: " + self.url) # check credit if self.DOWNLOAD_AGAIN_PATTERN in self.html: @@ -113,13 +60,12 @@ class HellshareCz(SimpleHoster): found = re.search(self.CREDIT_LEFT_PATTERN, self.html) credits_left = int(found.group(1)) if found else (self.account.getAccountInfo(self.user, True)["trafficleft"] / 1024) file_credits = ceil(self.pyfile.size / float(1024 ** 2)) - + if credits_left < file_credits: - self.logError("Not enough credit left for user %s: %d (%d needed). Downloading as free user." % (self.user, credits_left, file_credits)) - self.resetAccount() + self.fail("Not enough credit left for user %s: %d (%d needed)." % (self.user, credits_left, file_credits)) else: self.logInfo("Downloading file for %d credits, %d credits left" % (file_credits, credits_left)) - self.download(download_url) + self.download(self.url) -getInfo = create_getInfo(HellshareCz)
\ No newline at end of file +getInfo = create_getInfo(HellshareCz) diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index a4a7c5efa..cfc9f2b43 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -31,17 +31,17 @@ def replace_patterns(string, ruleslist): string = re.sub(rf, rt, string) #self.logDebug(rf, rt, string) return string - + def set_cookies(cj, cookies): for cookie in cookies: if isinstance(cookie, tuple) and len(cookie) == 3: domain, name, value = cookie cj.setCookie(domain, name, value) - + def parseHtmlTagAttrValue(attr_name, tag): - m = re.search(r"%s\s*=\s*([\"']?)((?<=\")[^\"]+|(?<=')[^']+|[^>\s\"'][^>\s]*)\1" % attr_name, tag, re.I) + m = re.search(r"%s\s*=\s*([\"']?)((?<=\")[^\"]+|(?<=')[^']+|[^>\s\"'][^>\s]*)\1" % attr_name, tag, re.I) return m.group(2) if m else None - + def parseHtmlForm(attr_str, html, input_names=None): for form in re.finditer(r"(?P<tag><form[^>]*%s[^>]*>)(?P<content>.*?)</?(form|body|html)[^>]*>" % attr_str, html, re.S | re.I): inputs = {} @@ -54,50 +54,42 @@ def parseHtmlForm(attr_str, html, input_names=None): inputs[name] = inputtag.group(3) or '' else: inputs[name] = value - + if isinstance(input_names, dict): # check input attributes for key, val in input_names.items(): if key in inputs: if isinstance(val, basestring) and inputs[key] == val: - print "MATCH STRING", val, inputs[key] - continue + continue elif isinstance(val, tuple) and inputs[key] in val: - print "MATCH TUPLE", val, inputs[key] continue elif hasattr(val, "search") and re.match(val, inputs[key]): - print "MATCH REGEXP", val, inputs[key] continue - print "NO MATCH", inputs, input_names break # attibute value does not match else: - print "NO KEY", inputs, input_names break # attibute name does not match - else: - print "ALL MATCH", inputs, input_names - return action, inputs # passed attribute check + else: + return action, inputs # passed attribute check else: - # no attribute check - print "NOCHECK", inputs, input_names, type(input_names) - return action, inputs - - print "NONE", inputs + # no attribute check + return action, inputs + return {}, None # no matching form found -def parseFileInfo(self, url = '', html = ''): +def parseFileInfo(self, url = '', html = ''): info = {"name" : url, "size" : 0, "status" : 3} - - if hasattr(self, "pyfile"): - url = self.pyfile.url + + if hasattr(self, "pyfile"): + url = self.pyfile.url if hasattr(self, "req") and self.req.http.code == '404': info['status'] = 1 else: if not html and hasattr(self, "html"): html = self.html - if isinstance(self.SH_BROKEN_ENCODING, (str, unicode)): + if isinstance(self.SH_BROKEN_ENCODING, (str, unicode)): html = unicode(html, self.SH_BROKEN_ENCODING) if hasattr(self, "html"): self.html = html - + if hasattr(self, "FILE_OFFLINE_PATTERN") and re.search(self.FILE_OFFLINE_PATTERN, html): # File offline info['status'] = 1 @@ -107,7 +99,7 @@ def parseFileInfo(self, url = '', html = ''): info.update(re.match(self.__pattern__, url).groupdict()) except: pass - + for pattern in ("FILE_INFO_PATTERN", "FILE_NAME_PATTERN", "FILE_SIZE_PATTERN"): try: info.update(re.search(getattr(self, pattern), html).groupdict()) @@ -154,7 +146,7 @@ class PluginParseError(Exception): class SimpleHoster(Hoster): __name__ = "SimpleHoster" - __version__ = "0.27" + __version__ = "0.28" __pattern__ = None __type__ = "hoster" __description__ = """Base hoster plugin""" @@ -172,13 +164,13 @@ class SimpleHoster(Hoster): FILE_SIZE_REPLACEMENTS = [] FILE_NAME_REPLACEMENTS = [("&#?\w+;", fixup)] FILE_URL_REPLACEMENTS = [] - + SH_BROKEN_ENCODING = False # Set to True or encoding name if encoding in http header is not correct SH_COOKIES = True # or False or list of tuples [(domain, name, value)] SH_CHECK_TRAFFIC = False # True = force check traffic left for a premium account - + def init(self): - self.file_info = {} + self.file_info = {} def setup(self): self.resumeDownload = self.multiDL = True if self.premium else False @@ -186,6 +178,7 @@ class SimpleHoster(Hoster): def process(self, pyfile): pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS) + self.req.setOption("timeout", 120) self.html = self.load(pyfile.url, decode = not self.SH_BROKEN_ENCODING, cookies = self.SH_COOKIES) self.getFileInfo() if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()): @@ -193,13 +186,17 @@ class SimpleHoster(Hoster): else: self.handleFree() + def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False, decode=False): + if type(url) == unicode: url = url.encode('utf8') + return Hoster.load(self, url=url, get=get, post=post, ref=ref, cookies=cookies, just_header=just_header, decode=decode) + def getFileInfo(self): self.logDebug("URL: %s" % self.pyfile.url) if hasattr(self, "TEMP_OFFLINE_PATTERN") and re.search(self.TEMP_OFFLINE_PATTERN, self.html): self.tempOffline() name, size, status = parseFileInfo(self)[:3] - + if status == 1: self.offline() elif status != 2: @@ -227,28 +224,28 @@ class SimpleHoster(Hoster): def parseError(self, msg): raise PluginParseError(msg) - + def longWait(self, wait_time = None, max_tries = 3): if wait_time and isinstance(wait_time, (int, long, float)): time_str = "%dh %dm" % divmod(wait_time / 60, 60) else: wait_time = 900 time_str = "(unknown time)" - max_tries = 100 - + max_tries = 100 + self.logInfo("Download limit reached, reconnect or wait %s" % time_str) - + self.setWait(wait_time, True) self.wait() - self.retry(max_tries = max_tries, reason="Download limit reached") + self.retry(max_tries = max_tries, reason="Download limit reached") def parseHtmlForm(self, attr_str='', input_names=None): return parseHtmlForm(attr_str, self.html, input_names) - - def checkTrafficLeft(self): + + def checkTrafficLeft(self): traffic = self.account.getAccountInfo(self.user, True)["trafficleft"] if traffic == -1: return True size = self.pyfile.size / 1024 - self.logInfo("Filesize: %i KiB, Traffic left for user %s: %i KiB" % (size, self.user, traffic)) + self.logInfo("Filesize: %i KiB, Traffic left for user %s: %i KiB" % (size, self.user, traffic)) return size <= traffic
\ No newline at end of file |