From 2d893a24d4bb8b5a7a00807ed6320358454577f8 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sun, 29 Jun 2014 21:55:29 +0200 Subject: [SimpleHoster] Improve documentation of own public attributes --- module/plugins/internal/SimpleHoster.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index f10433e78..8c2e3daae 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -169,15 +169,19 @@ class SimpleHoster(Hoster): __description__ = """Simple hoster plugin""" __author_name__ = ("zoidberg", "stickell") __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") + """ - These patterns should be defined by each hoster: - FILE_INFO_PATTERN = r'(?Pfile_name) (?Pfile_size) (?Punits)' - or FILE_NAME_PATTERN = r'(?Pfile_name)' - and FILE_SIZE_PATTERN = r'(?Pfile_size) (?Punits)' + Following patterns should be defined by each hoster: + FILE_INFO_PATTERN = r'(?Pfile_name) (?Pfile_size) (?Psize_unit)' + or + FILE_NAME_PATTERN = r'(?Pfile_name)' + FILE_SIZE_PATTERN = r'(?Pfile_size) (?Psize_unit)' + FILE_OFFLINE_PATTERN = r'File (deleted|not found)' TEMP_OFFLINE_PATTERN = r'Server maintainance' - You can also define a PREMIUM_ONLY_PATTERN to detect links that can be downloaded only with a premium account. + You can also define: + PREMIUM_ONLY_PATTERN = r'Premium account required' """ FILE_SIZE_REPLACEMENTS = [] -- cgit v1.2.3 From 9c9cc6d4871b9847dada36c63ae1cbadfacef999 Mon Sep 17 00:00:00 2001 From: Stefano Date: Wed, 2 Jul 2014 15:23:46 +0200 Subject: [SimpleCrypter] ability to set cookies --- module/plugins/internal/SimpleCrypter.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py index b1a18f5e0..268efee86 100644 --- a/module/plugins/internal/SimpleCrypter.py +++ b/module/plugins/internal/SimpleCrypter.py @@ -21,12 +21,12 @@ import re from module.plugins.Crypter import Crypter from module.utils import html_unescape -from module.plugins.internal.SimpleHoster import replace_patterns +from module.plugins.internal.SimpleHoster import replace_patterns, set_cookies class SimpleCrypter(Crypter): __name__ = "SimpleCrypter" - __version__ = "0.07" + __version__ = "0.08" __pattern__ = None __type__ = "crypter" __description__ = """Simple decrypter plugin""" @@ -55,6 +55,12 @@ class SimpleCrypter(Crypter): FILE_URL_REPLACEMENTS = [] + SH_COOKIES = True # or False or list of tuples [(domain, name, value)] + + def setup(self): + if isinstance(self.SH_COOKIES, list): + set_cookies(self.req.cj, self.SH_COOKIES) + def decrypt(self, pyfile): pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS) -- cgit v1.2.3 From 15362ebceaee1eb66920d4822d2faa947151e74a Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 5 Jul 2014 16:42:24 +0200 Subject: [SimpleCrypter] Better inline docs + support for offline & temp.offline check --- module/plugins/internal/SimpleCrypter.py | 40 +++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py index 268efee86..2c024d738 100644 --- a/module/plugins/internal/SimpleCrypter.py +++ b/module/plugins/internal/SimpleCrypter.py @@ -26,34 +26,44 @@ from module.plugins.internal.SimpleHoster import replace_patterns, set_cookies class SimpleCrypter(Crypter): __name__ = "SimpleCrypter" - __version__ = "0.08" + __version__ = "0.09" __pattern__ = None __type__ = "crypter" __description__ = """Simple decrypter plugin""" __author_name__ = ("stickell", "zoidberg") __author_mail__ = ("l.stickell@yahoo.it", "zoidberg@mujmail.cz") + """ - These patterns should be defined by each crypter: + Following patterns should be defined by each crypter: + + LINK_PATTERN: group(1) must be a download link or a regex to catch more links + example: LINK_PATTERN = r'' + RECAPTCHA_PATTERN = None + SOLVEMEDIA_PATTERN = None FORM_PATTERN = None FORM_INPUTS_MAP = None #: dict passed as input_names to parseHtmlForm @@ -234,10 +234,10 @@ class XFSHoster(SimpleHoster): retries = 3 else: delay = 1 * 60 * 60 - retries = 25 + retries = 24 - self.wait(delay, True) - self.retry(retries, reason=_("Download limit exceeded")) + self.wantReconnect = True + self.retry(retries, delay, _("Download limit exceeded")) elif 'countdown' in self.errmsg or 'Expired' in self.errmsg: self.retry(reason=_("Link expired")) @@ -249,6 +249,7 @@ class XFSHoster(SimpleHoster): self.fail(_("File too large for free download")) else: + self.wantReconnect = True self.retry(wait_time=60, reason=self.errmsg) if self.errmsg: @@ -311,7 +312,7 @@ class XFSHoster(SimpleHoster): inputs['code'] = self.decryptCaptcha(captcha_url) return 1 - m = re.search(self.CAPTCHA_DIV_PATTERN, self.html, re.S) + m = re.search(self.CAPTCHA_BLOCK_PATTERN, self.html, re.S) if m: captcha_div = m.group(1) numerals = re.findall(r'(\d)', html_unescape(captcha_div)) -- cgit v1.2.3 From a83f45f14aefb4fd766f7908e11bc6beaac3d0e8 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 1 Dec 2014 18:51:37 +0100 Subject: [XFSAccount] Improve patterns --- module/plugins/internal/XFSAccount.py | 8 ++++---- module/plugins/internal/XFSHoster.py | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/XFSAccount.py b/module/plugins/internal/XFSAccount.py index 5a265c08a..2094b1480 100644 --- a/module/plugins/internal/XFSAccount.py +++ b/module/plugins/internal/XFSAccount.py @@ -12,7 +12,7 @@ from module.plugins.internal.SimpleHoster import parseHtmlForm, set_cookies class XFSAccount(Account): __name__ = "XFSAccount" __type__ = "account" - __version__ = "0.31" + __version__ = "0.32" __description__ = """XFileSharing account plugin""" __license__ = "GPLv3" @@ -27,15 +27,15 @@ class XFSAccount(Account): PREMIUM_PATTERN = r'\(Premium only\)' - VALID_UNTIL_PATTERN = r'>Premium.[Aa]ccount expire:.*?(\d{1,2} [\w^_]+ \d{4})' + VALID_UNTIL_PATTERN = r'Premium.[Aa]ccount expire:.*?(\d{1,2} [\w^_]+ \d{4})' - TRAFFIC_LEFT_PATTERN = r'>Traffic available today:.*?\s*(?P[\d.,]+|[Uu]nlimited)\s*(?:(?P[\w^_]+)\s*)?' + TRAFFIC_LEFT_PATTERN = r'Traffic available today:.*?\s*(?P[\d.,]+|[Uu]nlimited)\s*(?:(?P[\w^_]+)\s*)?' TRAFFIC_LEFT_UNIT = "MB" #: used only if no group was found LEECH_TRAFFIC_PATTERN = r'Leech Traffic left:.*?(?P[\d.,]+|[Uu]nlimited)\s*(?:(?P[\w^_]+)\s*)?' LEECH_TRAFFIC_UNIT = "MB" #: used only if no group was found - LOGIN_FAIL_PATTERN = r'>(Incorrect Login or Password|Error<)' + LOGIN_FAIL_PATTERN = r'>\s*(Incorrect Login or Password|Error<)' def __init__(self, manager, accounts): #@TODO: remove in 0.4.10 diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index 587d47f6e..c3db3f335 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -35,7 +35,6 @@ class XFSHoster(SimpleHoster): CHECK_DIRECT_LINK = None MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy... - INFO_PATTERN = r'Filename:(?P[^<]+)\s*.*?\((?P[^<]+)\)' NAME_PATTERN = r'(>Filename:|name="fname" value="|)(?P.+?)(\s*<|")' SIZE_PATTERN = r'(>Size:|>File:.*>|)(?P[\d.,]+)\s*(?P[\w^_]+)' -- cgit v1.2.3 From 1bcdfb409ded0c369735c413b33f2e344b36bd7a Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 1 Dec 2014 20:00:14 +0100 Subject: Fixes --- module/plugins/internal/SimpleHoster.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 736d15f3a..cf03a1242 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -123,7 +123,7 @@ def _isDirectLink(self, url, resumable=True): location = header['location'] if resumable: #: sometimes http code may be wrong... - if self.load(location, ref=True, cookies=True, just_header=True, decode=True)['location']: + if 'location' in self.load(location, ref=True, cookies=True, just_header=True, decode=True): return "" else: if not 'code' in header or header['code'] != 302: @@ -388,7 +388,7 @@ class SimpleHoster(Hoster): self.checkFile() - def checkFile(self) + def checkFile(self): if self.checkDownload({'empty': re.compile(r"^$")}) is "empty": #@TODO: Move to hoster in 0.4.10 self.fail(_("Empty file")) -- cgit v1.2.3 From eb71f308010e35aaec7f7bfa529ada96975c909d Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 2 Dec 2014 00:04:41 +0100 Subject: [SimpleHoster] Force _isDirectLink to old style --- module/plugins/internal/SimpleHoster.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index cf03a1242..ba718950d 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -122,6 +122,8 @@ def _isDirectLink(self, url, resumable=True): location = header['location'] + resumable = False #@NOTE: Testing... + if resumable: #: sometimes http code may be wrong... if 'location' in self.load(location, ref=True, cookies=True, just_header=True, decode=True): return "" -- cgit v1.2.3 From be05dce2da77bca4613efbdfb0f6357a983e6e1c Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 3 Dec 2014 14:38:22 +0100 Subject: Fix https://github.com/pyload/pyload/issues/943 --- module/plugins/internal/SimpleHoster.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index ba718950d..809e89c02 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -33,7 +33,7 @@ def _error(self, reason, type): #@TODO: Remove in 0.4.10 def _wait(self, seconds, reconnect): if seconds: - self.setWait(seconds + 1) + self.setWait(int(seconds) + 1) if reconnect is not None: self.wantReconnect = reconnect @@ -144,7 +144,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.69" + __version__ = "0.70" __pattern__ = r'^unmatchable$' -- cgit v1.2.3 From 5a23de6f32dc99960cccd634d2fd2cc47c34be2a Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 5 Dec 2014 23:08:44 +0100 Subject: Code cosmetics about checkErrors --- module/plugins/internal/SimpleHoster.py | 4 ++-- module/plugins/internal/XFSHoster.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 809e89c02..f391445fd 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -399,8 +399,8 @@ class SimpleHoster(Hoster): if hasattr(self, 'ERROR_PATTERN'): m = re.search(self.ERROR_PATTERN, self.html) if m: - e = self.info['error'] = m.group(1) - self.error(e) + errmsg = self.info['error'] = m.group(1) + self.error(errmsg) if hasattr(self, 'PREMIUM_ONLY_PATTERN'): m = re.search(self.PREMIUM_ONLY_PATTERN, self.html) diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index c3db3f335..3ae0692dc 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -256,8 +256,6 @@ class XFSHoster(SimpleHoster): else: self.info.pop('error', None) - return self.errmsg - def getPostParameters(self): if self.FORM_PATTERN or self.FORM_INPUTS_MAP: -- cgit v1.2.3 From dcf495b582440c33d878115556ceddf0f523a1ab Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 6 Dec 2014 11:02:24 +0100 Subject: [MultiHoster] Code cosmetics --- module/plugins/internal/MultiHoster.py | 45 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index c86f9b286..6ec2e4b82 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -9,25 +9,28 @@ from module.utils import remove_chars class MultiHoster(Hook): __name__ = "MultiHoster" __type__ = "hook" - __version__ = "0.19" + __version__ = "0.20" __description__ = """Generic MultiHoster plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - interval = 24 * 60 * 60 #: reload hosters daily + interval = 12 * 60 * 60 #: reload hosters every 12h - HOSTER_REPLACEMENTS = [("2shared.com", "twoshared.com"), ("4shared.com", "fourshared.com"), ("cloudnator.com", "shragle.com"), - ("ifile.it", "filecloud.io"), ("easy-share.com", "crocko.com"), ("freakshare.net", "freakshare.com"), - ("hellshare.com", "hellshare.cz"), ("share-rapid.cz", "sharerapid.com"), ("sharerapid.cz", "sharerapid.com"), - ("ul.to", "uploaded.to"), ("uploaded.net", "uploaded.to"), ("1fichier.com", "onefichier.com")] + HOSTER_REPLACEMENTS = [("1fichier.com", "onefichier.com"), ("2shared.com", "twoshared.com"), + ("4shared.com", "fourshared.com"), ("cloudnator.com", "shragle.com"), + ("easy-share.com", "crocko.com"), ("freakshare.net", "freakshare.com"), + ("hellshare.com", "hellshare.cz"), ("ifile.it", "filecloud.io"), + ("putlocker.com", "firedrive.com"), ("share-rapid.cz", "multishare.cz"), + ("sharerapid.cz", "multishare.cz"), ("ul.to", "uploaded.to"), + ("uploaded.net", "uploaded.to")] HOSTER_EXCLUDED = [] def setup(self): - self.hosters = [] - self.supported = [] + self.hosters = [] + self.supported = [] self.new_supported = [] @@ -41,7 +44,6 @@ class MultiHoster(Hook): def getHosterCached(self): if not self.hosters: - try: hosterSet = self.toHosterSet(self.getHoster()) - set(self.HOSTER_EXCLUDED) except Exception, e: @@ -110,8 +112,10 @@ class MultiHoster(Hook): """reload hoster list periodically""" self.logInfo(_("Reloading supported hoster list")) - old_supported = self.supported - self.supported, self.new_supported, self.hosters = [], [], [] + old_supported = self.supported + self.supported = [] + self.new_supported = [] + self.hosters = [] self.overridePlugins() @@ -123,11 +127,8 @@ class MultiHoster(Hook): def overridePlugins(self): - pluginMap = {} - for name in self.core.pluginManager.hosterPlugins.keys(): - pluginMap[name.lower()] = name - - accountList = [name.lower() for name, data in self.core.accountManager.accounts.iteritems() if data] + pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.keys()) + accountList = [name.lower() for name, data in self.core.accountManager.accounts.iteritems() if data] excludedList = [] for hoster in self.getHosterCached(): @@ -146,14 +147,14 @@ class MultiHoster(Hook): return module = self.core.pluginManager.getPlugin(self.__name__) - klass = getattr(module, self.__name__) + klass = getattr(module, self.__name__) # inject plugin plugin self.logDebug("Overwritten Hosters", ", ".join(sorted(self.supported))) for hoster in self.supported: dict = self.core.pluginManager.hosterPlugins[hoster] dict['new_module'] = module - dict['new_name'] = self.__name__ + dict['new_name'] = self.__name__ if excludedList: self.logInfo(_("The following hosters were not overwritten - account exists"), ", ".join(sorted(excludedList))) @@ -162,7 +163,7 @@ class MultiHoster(Hook): self.logDebug("New Hosters", ", ".join(sorted(self.new_supported))) # create new regexp - regexp = r'.*(%s).*' % "|".join([x.replace(".", "\\.") for x in self.new_supported]) + regexp = r'.*(%s).*' % "|".join([x.replace(".", "\.") for x in self.new_supported]) if hasattr(klass, "__pattern__") and isinstance(klass.__pattern__, basestring) and '://' in klass.__pattern__: regexp = r'%s|%s' % (klass.__pattern__, regexp) @@ -170,7 +171,7 @@ class MultiHoster(Hook): dict = self.core.pluginManager.hosterPlugins[self.__name__] dict['pattern'] = regexp - dict['re'] = re.compile(regexp) + dict['re'] = re.compile(regexp) def unloadHoster(self, hoster): @@ -190,9 +191,9 @@ class MultiHoster(Hook): # reset pattern klass = getattr(self.core.pluginManager.getPlugin(self.__name__), self.__name__) - dict = self.core.pluginManager.hosterPlugins[self.__name__] + dict = self.core.pluginManager.hosterPlugins[self.__name__] dict['pattern'] = getattr(klass, "__pattern__", r'^unmatchable$') - dict['re'] = re.compile(dict['pattern']) + dict['re'] = re.compile(dict['pattern']) def downloadFailed(self, pyfile): -- cgit v1.2.3 From ef0d8692b04d75f4a39a565d52c2eb381eb43055 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 6 Dec 2014 11:03:57 +0100 Subject: [SimpleHoster] Fix multihost --- module/plugins/internal/SimpleHoster.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index f391445fd..530b67692 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -144,7 +144,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.70" + __version__ = "0.71" __pattern__ = r'^unmatchable$' @@ -319,8 +319,8 @@ class SimpleHoster(Hoster): set_cookies(self.req.cj, self.COOKIES) if (self.MULTI_HOSTER - and self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] - and re.match(self.__pattern__, self.pyfile.url) is None): + and (self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] + or re.match(self.__pattern__, self.pyfile.url) is None)): self.logInfo("Multi hoster detected") @@ -384,12 +384,17 @@ class SimpleHoster(Hoster): self.logDebug("Handled as free download") self.handleFree() - if self.link: - self.download(self.link, disposition=self.CONTENT_DISPOSITION) - + self.downloadLink(self.link) self.checkFile() + def downloadLink(self, link): + if not link: + return + + self.download(link, disposition=self.CONTENT_DISPOSITION) + + def checkFile(self): if self.checkDownload({'empty': re.compile(r"^$")}) is "empty": #@TODO: Move to hoster in 0.4.10 self.fail(_("Empty file")) -- cgit v1.2.3 From 6151e81fa0b325dffda3da4228d5821e73db3ef3 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 9 Dec 2014 01:19:46 +0100 Subject: Fix __version__ format in some plugins --- module/plugins/internal/AbstractExtractor.py | 2 +- module/plugins/internal/UnZip.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/AbstractExtractor.py b/module/plugins/internal/AbstractExtractor.py index 8a69ebb56..2317ad689 100644 --- a/module/plugins/internal/AbstractExtractor.py +++ b/module/plugins/internal/AbstractExtractor.py @@ -14,7 +14,7 @@ class WrongPassword(Exception): class AbtractExtractor: __name__ = "AbtractExtractor" - __version__ = "0.1" + __version__ = "0.10" __description__ = """Abtract extractor plugin""" __license__ = "GPLv3" diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index e754141a1..053946dbe 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -8,7 +8,7 @@ from module.plugins.internal.AbstractExtractor import AbtractExtractor class UnZip(AbtractExtractor): __name__ = "UnZip" - __version__ = "0.1" + __version__ = "0.10" __description__ = """Zip extractor plugin""" __license__ = "GPLv3" -- cgit v1.2.3 From 58656ab0b1b7f79ee31c38b7675f0587269f014f Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 10 Dec 2014 02:59:27 +0100 Subject: [CaptchaService] New service AdYouLike + AdsCaptcha detect_key fixup --- module/plugins/internal/CaptchaService.py | 203 +++++++++++++++++++++++------- 1 file changed, 161 insertions(+), 42 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py index 7009e6986..965799e8e 100644 --- a/module/plugins/internal/CaptchaService.py +++ b/module/plugins/internal/CaptchaService.py @@ -4,10 +4,12 @@ import re from random import random +from module.common.json_layer import json_loads + class CaptchaService: __name__ = "CaptchaService" - __version__ = "0.15" + __version__ = "0.16" __description__ = """Base captcha service plugin""" __license__ = "GPLv3" @@ -34,7 +36,7 @@ class CaptchaService: m = re.search(self.KEY_PATTERN, html) if m: - self.key = m.group("KEY") + self.key = m.group(1).strip() self.plugin.logDebug("%s key: %s" % (self.__name__, self.key)) return self.key else: @@ -59,8 +61,8 @@ class ReCaptcha(CaptchaService): __authors__ = [("pyLoad Team", "admin@pyload.org")] - KEY_PATTERN = r'recaptcha(/api|\.net)/(challenge|noscript)\?k=(?P[\w-]+)' - KEY_AJAX_PATTERN = r'Recaptcha\.create\s*\(\s*["\'](?P[\w-]+)' + KEY_PATTERN = r'recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=([\w-]+)' + KEY_AJAX_PATTERN = r'Recaptcha\.create\s*\(\s*["\']([\w-]+)' def detect_key(self, html=None): @@ -74,7 +76,7 @@ class ReCaptcha(CaptchaService): m = re.search(self.KEY_PATTERN, html) or re.search(self.KEY_AJAX_PATTERN, html) if m: - self.key = m.group("KEY") + self.key = m.group(1).strip() self.plugin.logDebug("ReCaptcha key: %s" % self.key) return self.key else: @@ -91,36 +93,43 @@ class ReCaptcha(CaptchaService): self.plugin.fail(errmsg) raise TypeError(errmsg) - js = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", get={'k': key}) + html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", get={'k': key}) try: - challenge = re.search("challenge : '(.+?)',", js).group(1) - server = re.search("server : '(.+?)',", js).group(1) + challenge = re.search("challenge : '(.+?)',", html).group(1) + server = re.search("server : '(.+?)',", html).group(1) except: - self.plugin.error("ReCaptcha challenge pattern not found") - - result = self.result(server, challenge) + errmsg = _("ReCaptcha challenge pattern not found") + self.plugin.fail(errmsg) + raise ValueError(errmsg) - self.plugin.logDebug("ReCaptcha result: %s" % result, "challenge: %s" % challenge) + self.plugin.logDebug("ReCaptcha challenge: %s" % challenge) - return challenge, result + return challenge, self.result(server, challenge) def result(self, server, challenge): - return self.plugin.decryptCaptcha("%simage" % server, get={'c': challenge}, - cookies=True, forceUser=True, imgtype="jpg") + result = self.plugin.decryptCaptcha("%simage" % server, + get={'c': challenge}, + cookies=True, + forceUser=True, + imgtype="jpg") + + self.plugin.logDebug("ReCaptcha result: %s" % result) + + return result class AdsCaptcha(CaptchaService): __name__ = "AdsCaptcha" - __version__ = "0.05" + __version__ = "0.06" __description__ = """AdsCaptcha captcha service plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - ID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*CaptchaId=(?P\d+)' - KEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*PublicKey=(?P[\w-]+)' + CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*CaptchaId=(\d+)' + PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*PublicKey=([\w-]+)' def detect_key(self, html=None): @@ -132,18 +141,18 @@ class AdsCaptcha(CaptchaService): self.plugin.fail(errmsg) raise TypeError(errmsg) - m = re.search(self.ID_PATTERN, html) - n = re.search(self.KEY_PATTERN, html) + m = re.search(self.PUBLICKEY_PATTERN, html) + n = re.search(self.CAPTCHAID_PATTERN, html) if m and n: - self.key = (m.group("ID"), m.group("KEY")) - self.plugin.logDebug("AdsCaptcha id|key: %s | %s" % self.key) + self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId) + self.plugin.logDebug("AdsCaptcha key|id: %s | %s" % self.key) return self.key else: - self.plugin.logDebug("AdsCaptcha id or key not found") + self.plugin.logDebug("AdsCaptcha key or id not found") return None - def challenge(self, key=None): #: key is a tuple(CaptchaId, PublicKey) + def challenge(self, key=None): if not key: if self.detect_key(): key = self.key @@ -152,25 +161,31 @@ class AdsCaptcha(CaptchaService): self.plugin.fail(errmsg) raise TypeError(errmsg) - CaptchaId, PublicKey = key + PublicKey, CaptchaId = key - js = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", get={'CaptchaId': CaptchaId, 'PublicKey': PublicKey}) + html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", get={'CaptchaId': CaptchaId, 'PublicKey': PublicKey}) try: - challenge = re.search("challenge: '(.+?)',", js).group(1) - server = re.search("server: '(.+?)',", js).group(1) + challenge = re.search("challenge: '(.+?)',", html).group(1) + server = re.search("server: '(.+?)',", html).group(1) except: - self.plugin.error("AdsCaptcha challenge pattern not found") - - result = self.result(server, challenge) + errmsg = _("AdsCaptcha challenge pattern not found") + self.plugin.fail(errmsg) + raise ValueError(errmsg) - self.plugin.logDebug("AdsCaptcha result: %s" % result, "challenge: %s" % challenge) + self.plugin.logDebug("AdsCaptcha challenge: %s" % challenge) - return challenge, result + return challenge, self.result(server, challenge) def result(self, server, challenge): - return self.plugin.decryptCaptcha("%sChallenge.aspx" % server, get={'cid': challenge, 'dummy': random()}, - cookies=True, imgtype="jpg") + result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server, + get={'cid': challenge, 'dummy': random()}, + cookies=True, + imgtype="jpg") + + self.plugin.logDebug("AdsCaptcha result: %s" % result) + + return result class SolveMedia(CaptchaService): @@ -182,7 +197,7 @@ class SolveMedia(CaptchaService): __authors__ = [("pyLoad Team", "admin@pyload.org")] - KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(no)?script\?k=(?P.+?)["\']' + KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' def challenge(self, key=None): @@ -198,16 +213,120 @@ class SolveMedia(CaptchaService): try: challenge = re.search(r'', html).group(1) - server = "http://api.solvemedia.com/papi/media" + server = "http://api.solvemedia.com/papi/media" except: - self.plugin.error("SolveMedia challenge pattern not found") + errmsg = _("SolveMedia challenge pattern not found") + self.plugin.fail(errmsg) + raise ValueError(errmsg) + + self.plugin.logDebug("SolveMedia challenge: %s" % challenge) + + return challenge, self.result(server, challenge) + + + def result(self, server, challenge): + result = self.plugin.decryptCaptcha(server, get={'c': challenge}, imgtype="gif") + + self.plugin.logDebug("SolveMedia result: %s" % result) + + return result + + +class AdYouLike(CaptchaService): + __name__ = "AdYouLike" + __version__ = "0.02" + + __description__ = """AdYouLike captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)' + CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' + + + def detect_key(self, html=None): + if not html: + if hasattr(self.plugin, "html") and self.plugin.html: + html = self.plugin.html + else: + errmsg = _("AdYouLike html not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) - result = self.result(server, challenge) + m = re.search(self.AYL_PATTERN, html) + n = re.search(self.CALLBACK_PATTERN, html) + if m and n: + self.key = (m.group(1).strip(), n.group(1).strip()) + self.plugin.logDebug("AdYouLike ayl|callback: %s | %s" % self.key) + return self.key #: key is the tuple(ayl, callback) + else: + self.plugin.logDebug("AdYouLike ayl or callback not found") + return None - self.plugin.logDebug("SolveMedia result: %s" % result, "challenge: %s" % challenge) - return challenge, result + def challenge(self, key=None): + if not key: + if self.detect_key(): + key = self.key + else: + errmsg = _("AdYouLike key not found") + self.plugin.fail(errmsg) + raise TypeError(errmsg) + + ayl, callback = key + + # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, + # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} + ayl = json_loads(ayl) + + html = self.plugin.req.load("http://api-ayl.appspot.com/challenge", + get={'key' : ayl['adyoulike']['key'], + 'env' : ayl['all']['env'], + 'callback': callback}) + try: + challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) + except: + errmsg = _("AdYouLike challenge pattern not found") + self.plugin.fail(errmsg) + raise ValueError(errmsg) + + self.plugin.logDebug("AdYouLike challenge: %s" % challenge) + + return self.result(ayl, challenge) def result(self, server, challenge): - return self.plugin.decryptCaptcha(server, get={'c': challenge}, imgtype="gif") + # Adyoulike.g._jsonp_5579316662423138 + # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}}, + # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[], + # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike", + # "iframes":{"big":""},"shares":{},"id":256, + # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60}, + # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}}, + # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"}) + + if isinstance(server, basestring): + server = json_loads(server) + + if isinstance(challenge, basestring): + challenge = json_loads(challenge) + + try: + instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual'] + result = re.search(u'«(.+?)»', instructions_visual).group(1).strip() + except: + errmsg = _("AdYouLike result not found") + self.plugin.fail(errmsg) + raise ValueError(errmsg) + + result = {'_ayl_captcha_engine' : "adyoulike", + '_ayl_env' : server['all']['env'], + '_ayl_tid' : challenge['tid'], + '_ayl_token_challenge': challenge['token'], + '_ayl_response' : response} + + self.plugin.logDebug("AdYouLike result: %s" % result) + + return result -- cgit v1.2.3 From 1fe525b92affd6d3829af219a9b1b5eeda136ca2 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 12 Dec 2014 20:31:37 +0100 Subject: [SimpleHoster] Remove CONTENT_DISPOSITION + Rename parseInfo to parseInfos --- module/plugins/internal/SimpleHoster.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 530b67692..ddaea020a 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -104,9 +104,9 @@ def parseFileInfo(plugin, url="", html=""): #@TODO: Remove in 0.4.10 -#@NOTE: Every plugin must have own parseInfo classmethod to work with 0.4.10 +#@NOTE: Every plugin must have own parseInfos classmethod to work with 0.4.10 def create_getInfo(plugin): - return lambda urls: [(info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfo(urls)] + return lambda urls: [(info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfos(urls)] def timestamp(): @@ -144,7 +144,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.71" + __version__ = "0.72" __pattern__ = r'^unmatchable$' @@ -206,11 +206,10 @@ class SimpleHoster(Hoster): FORCE_CHECK_TRAFFIC = False #: Set to True to force checking traffic left for premium account CHECK_DIRECT_LINK = None #: Set to True to check for direct link, set to None to do it only if self.account is True MULTI_HOSTER = False #: Set to True to leech other hoster link (according its multihoster hook if available) - CONTENT_DISPOSITION = False #: Set to True to replace file name with content-disposition value from http header @classmethod - def parseInfo(cls, urls): + def parseInfos(cls, urls): for url in urls: url = replace_patterns(url, cls.FILE_URL_REPLACEMENTS if hasattr(cls, "FILE_URL_REPLACEMENTS") else cls.URL_REPLACEMENTS) #@TODO: Remove FILE_URL_REPLACEMENTS check in 0.4.10 yield cls.getInfo(url) @@ -392,7 +391,7 @@ class SimpleHoster(Hoster): if not link: return - self.download(link, disposition=self.CONTENT_DISPOSITION) + self.download(link, disposition=True) def checkFile(self): -- cgit v1.2.3 From 0f530be2642c63759cb6156866f1d4ab119760da Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 12 Dec 2014 20:33:34 +0100 Subject: Fix missing create_getInfo --- module/plugins/internal/XFSCrypter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/XFSCrypter.py b/module/plugins/internal/XFSCrypter.py index 62fd8c017..4b57dab90 100644 --- a/module/plugins/internal/XFSCrypter.py +++ b/module/plugins/internal/XFSCrypter.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class XFSCrypter(SimpleCrypter): __name__ = "XFSCrypter" __type__ = "crypter" - __version__ = "0.04" + __version__ = "0.05" __pattern__ = r'^unmatchable$' -- cgit v1.2.3 From c9b4f3b9a78904d34d7e58593eacdc26b93c2562 Mon Sep 17 00:00:00 2001 From: philou75 Date: Fri, 12 Dec 2014 22:49:23 +0100 Subject: Make the waiting time work again on OneFichier.com --- module/plugins/internal/SimpleHoster.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index f391445fd..47b713173 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -144,7 +144,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.70" + __version__ = "0.71" __pattern__ = r'^unmatchable$' @@ -412,7 +412,7 @@ class SimpleHoster(Hoster): m = re.search(self.WAIT_PATTERN, self.html) if m: wait_time = sum([int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in - re.findall(r'(\d+)\s*(hr|hour|min|sec)', m, re.I)]) + re.findall(r'(\d+)\s*(hr|hour|min|sec)', m.group(0), re.I)]) self.wait(wait_time, False) return -- cgit v1.2.3 From 3d27f5ccee412d38102873a5b02e3f236375eb97 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 16 Dec 2014 03:44:15 +0100 Subject: Update plugins (2) --- module/plugins/internal/MultiHoster.py | 50 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index 6ec2e4b82..6d10d17d9 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -9,7 +9,7 @@ from module.utils import remove_chars class MultiHoster(Hook): __name__ = "MultiHoster" __type__ = "hook" - __version__ = "0.20" + __version__ = "0.21" __description__ = """Generic MultiHoster plugin""" __license__ = "GPLv3" @@ -18,12 +18,18 @@ class MultiHoster(Hook): interval = 12 * 60 * 60 #: reload hosters every 12h - HOSTER_REPLACEMENTS = [("1fichier.com", "onefichier.com"), ("2shared.com", "twoshared.com"), - ("4shared.com", "fourshared.com"), ("cloudnator.com", "shragle.com"), - ("easy-share.com", "crocko.com"), ("freakshare.net", "freakshare.com"), - ("hellshare.com", "hellshare.cz"), ("ifile.it", "filecloud.io"), - ("putlocker.com", "firedrive.com"), ("share-rapid.cz", "multishare.cz"), - ("sharerapid.cz", "multishare.cz"), ("ul.to", "uploaded.to"), + HOSTER_REPLACEMENTS = [("1fichier.com", "onefichier.com"), + ("2shared.com", "twoshared.com"), + ("4shared.com", "fourshared.com"), + ("cloudnator.com", "shragle.com"), + ("easy-share.com", "crocko.com"), + ("freakshare.net", "freakshare.com"), + ("hellshare.com", "hellshare.cz"), + ("ifile.it", "filecloud.io"), + ("putlocker.com", "firedrive.com"), + ("share-rapid.cz", "multishare.cz"), + ("sharerapid.cz", "multishare.cz"), + ("ul.to", "uploaded.to"), ("uploaded.net", "uploaded.to")] HOSTER_EXCLUDED = [] @@ -152,9 +158,9 @@ class MultiHoster(Hook): # inject plugin plugin self.logDebug("Overwritten Hosters", ", ".join(sorted(self.supported))) for hoster in self.supported: - dict = self.core.pluginManager.hosterPlugins[hoster] - dict['new_module'] = module - dict['new_name'] = self.__name__ + hdict = self.core.pluginManager.hosterPlugins[hoster] + hdict['new_module'] = module + hdict['new_name'] = self.__name__ if excludedList: self.logInfo(_("The following hosters were not overwritten - account exists"), ", ".join(sorted(excludedList))) @@ -169,19 +175,19 @@ class MultiHoster(Hook): self.logDebug("Regexp", regexp) - dict = self.core.pluginManager.hosterPlugins[self.__name__] - dict['pattern'] = regexp - dict['re'] = re.compile(regexp) + hdict = self.core.pluginManager.hosterPlugins[self.__name__] + hdict['pattern'] = regexp + hdict['re'] = re.compile(regexp) def unloadHoster(self, hoster): - dict = self.core.pluginManager.hosterPlugins[hoster] - if "module" in dict: - del dict['module'] + hdict = self.core.pluginManager.hosterPlugins[hoster] + if "module" in hdict: + del hdict['module'] - if "new_module" in dict: - del dict['new_module'] - del dict['new_name'] + if "new_module" in hdict: + del hdict['new_module'] + del hdict['new_name'] def unload(self): @@ -191,9 +197,9 @@ class MultiHoster(Hook): # reset pattern klass = getattr(self.core.pluginManager.getPlugin(self.__name__), self.__name__) - dict = self.core.pluginManager.hosterPlugins[self.__name__] - dict['pattern'] = getattr(klass, "__pattern__", r'^unmatchable$') - dict['re'] = re.compile(dict['pattern']) + hdict = self.core.pluginManager.hosterPlugins[self.__name__] + hdict['pattern'] = getattr(klass, "__pattern__", r'^unmatchable$') + hdict['re'] = re.compile(hdict['pattern']) def downloadFailed(self, pyfile): -- cgit v1.2.3 From f633832bbfce04f4b1b83e59c02701483ef03525 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 16 Dec 2014 23:01:43 +0100 Subject: [XFSHoster] Improve SIZE_PATTERN --- module/plugins/internal/XFSHoster.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index 3ae0692dc..bb4baa274 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -16,7 +16,7 @@ from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.27" + __version__ = "0.28" __pattern__ = r'^unmatchable$' @@ -36,7 +36,7 @@ class XFSHoster(SimpleHoster): MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy... NAME_PATTERN = r'(>Filename:|name="fname" value="|)(?P.+?)(\s*<|")' - SIZE_PATTERN = r'(>Size:|>File:.*>|)(?P[\d.,]+)\s*(?P[\w^_]+)' + SIZE_PATTERN = r'(>Size:|>File:.*>|\s*\(|)(?P[\d.,]+)\s*(?P[\w^_]+)' OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)' TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)' @@ -199,13 +199,7 @@ class XFSHoster(SimpleHoster): def checkErrors(self): - m = re.search(self.PREMIUM_ONLY_PATTERN, self.html) - if m: - self.info['error'] = "premium-only" - return - m = re.search(self.ERROR_PATTERN, self.html) - if m is None: self.errmsg = None else: -- cgit v1.2.3 From b18bf426955d85d6cb3d046aa8b074dfe56340c1 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 16 Dec 2014 23:02:20 +0100 Subject: [UnZip] Password support --- module/plugins/internal/UnZip.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index 053946dbe..52e279ccf 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -3,12 +3,12 @@ import sys import zipfile -from module.plugins.internal.AbstractExtractor import AbtractExtractor +from module.plugins.internal.AbstractExtractor import AbtractExtractor, WrongPassword, ArchiveError class UnZip(AbtractExtractor): __name__ = "UnZip" - __version__ = "0.10" + __version__ = "0.11" __description__ = """Zip extractor plugin""" __license__ = "GPLv3" @@ -32,9 +32,19 @@ class UnZip(AbtractExtractor): def extract(self, progress, password=None): - z = zipfile.ZipFile(self.file) - self.files = z.namelist() - z.extractall(self.out) + try: + z = zipfile.ZipFile(self.file) + self.files = z.namelist() + z.extractall(self.out, pwd=password) + + except (BadZipfile, LargeZipFile), e: + raise ArchiveError(e) + + except RuntimeError, e: + if e is "Bad password for file": + raise WrongPassword + else: + raise ArchiveError(e) def getDeleteFiles(self): -- cgit v1.2.3 From a51d35534fc38650dd7714572f6874ab262bd119 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 16 Dec 2014 23:03:05 +0100 Subject: [SimpleHoster] Improve and fix --- module/plugins/internal/SimpleHoster.py | 58 +++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 24 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 992454451..86d9b4c9a 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -99,14 +99,24 @@ def parseHtmlForm(attr_str, html, input_names={}): #: Deprecated def parseFileInfo(plugin, url="", html=""): - info = plugin.getInfo(url, html) - return info['name'], info['size'], info['status'], info['url'] + if hasattr(plugin, "getInfo"): + info = plugin.getInfo(url, html) + res = info['name'], info['size'], info['status'], info['url'] + else: + res = urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 0, 3, url + + return res #@TODO: Remove in 0.4.10 #@NOTE: Every plugin must have own parseInfos classmethod to work with 0.4.10 def create_getInfo(plugin): - return lambda urls: [(info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfos(urls)] + if hasattr(plugin, "parseInfos"): + fn = lambda urls: [(info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfos(urls)] + else: + fn = lambda urls: [parseFileInfo(url) for url in urls] + + return fn def timestamp(): @@ -144,7 +154,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.73" + __version__ = "0.74" __pattern__ = r'^unmatchable$' @@ -260,18 +270,18 @@ class SimpleHoster(Hoster): try: info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: pattern groups will be saved here, please save api stuff to info['api'] except: - pass + info['pattern'] = {} for pattern in ("FILE_INFO_PATTERN", "INFO_PATTERN", "FILE_NAME_PATTERN", "NAME_PATTERN", "FILE_SIZE_PATTERN", "SIZE_PATTERN", "HASHSUM_PATTERN"): #@TODO: Remove old patterns starting with "FILE_" in 0.4.10 try: - attr = getattr(cls, pattern) - dict = re.search(attr, html).groupdict() + attr = getattr(cls, pattern) + pdict = re.search(attr, html).groupdict() - if all(True for k in dict if k not in info['pattern']): - info['pattern'].update(dict) + if all(True for k in pdict if k not in info['pattern']): + info['pattern'].update(pdict) except AttributeError: continue @@ -279,6 +289,9 @@ class SimpleHoster(Hoster): else: online = True + if not info['pattern']: + info.pop('pattern', None) + if online: info['status'] = 2 @@ -360,18 +373,21 @@ class SimpleHoster(Hoster): if self.html is None: self.fail(_("No html retrieved")) - self.checkErrors() - - premium_only = 'error' in self.info and self.info['error'] == "premium-only" - - self._updateInfo(self.getInfo(pyfile.url, self.html)) + self.updateInfo(self.getInfo(pyfile.url, self.html)) self.checkNameSize() + if hasattr(self, 'PREMIUM_ONLY_PATTERN'): + premium_only = re.search(self.PREMIUM_ONLY_PATTERN, self.html) + else: + premium_only = False + #: Usually premium only pages doesn't show any file information if not premium_only: self.checkStatus() + self.checkErrors() + if self.premium and (not self.FORCE_CHECK_TRAFFIC or self.checkTrafficLeft()): self.logDebug("Handled as premium download") self.handlePremium() @@ -406,18 +422,12 @@ class SimpleHoster(Hoster): errmsg = self.info['error'] = m.group(1) self.error(errmsg) - if hasattr(self, 'PREMIUM_ONLY_PATTERN'): - m = re.search(self.PREMIUM_ONLY_PATTERN, self.html) - if m: - self.info['error'] = "premium-only" - return - if hasattr(self, 'WAIT_PATTERN'): m = re.search(self.WAIT_PATTERN, self.html) if m: wait_time = sum([int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in re.findall(r'(\d+)\s*(hr|hour|min|sec)', m.group(0), re.I)]) - self.wait(wait_time, True if wait_time > 300 else False) + self.wait(wait_time, wait_time > 300) return self.info.pop('error', None) @@ -460,7 +470,7 @@ class SimpleHoster(Hoster): def checkInfo(self): self.checkErrors() - self._updateInfo(self.getInfo(self.pyfile.url, self.html or "")) + self.updateInfo(self.getInfo(self.pyfile.url, self.html or "")) self.checkNameSize() self.checkStatus() @@ -473,7 +483,7 @@ class SimpleHoster(Hoster): return self.info - def _updateInfo(self, info): + def updateInfo(self, info): self.logDebug(_("File info (before update): %s") % self.info) self.info.update(info) self.logDebug(_("File info (after update): %s") % self.info) @@ -487,7 +497,7 @@ class SimpleHoster(Hoster): self.link = link - self._updateInfo(self.getInfo(self.pyfile.url)) + self.updateInfo(self.getInfo(self.pyfile.url)) self.checkNameSize() else: self.logDebug(_("Direct download link not found")) -- cgit v1.2.3 From 8bb189cf5495b293cf574e5049c34a64ae36ffe1 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 16 Dec 2014 23:04:15 +0100 Subject: Spare code cosmetics --- module/plugins/internal/UnRar.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index c15a4c96e..716a62613 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -22,7 +22,7 @@ def renice(pid, value): class UnRar(AbtractExtractor): __name__ = "UnRar" - __version__ = "0.19" + __version__ = "0.20" __description__ = """Rar extractor plugin""" __license__ = "GPLv3" @@ -32,7 +32,7 @@ class UnRar(AbtractExtractor): CMD = "unrar" # there are some more uncovered rar formats - re_version = re.compile(r'UNRAR ([\w .]+?) freeware') + re_version = re.compile(r'UNRAR ([\w .]+?)') re_splitfile = re.compile(r'(.*)\.part(\d+)\.rar$', re.I) re_partfiles = re.compile(r'.*\.(rar|r\d+)', re.I) re_filelist = re.compile(r'(.+)\s+(\d+)\s+(\d+)\s+') @@ -91,7 +91,7 @@ class UnRar(AbtractExtractor): out, err = p.communicate() if self.re_wrongpwd.search(err): self.passwordProtected = True - self.headerProtected = True + self.headerProtected = True return True # output only used to check if passworded files are present @@ -124,7 +124,7 @@ class UnRar(AbtractExtractor): return True - def extract(self, progress, password=None): + def extract(self, progress, password=""): command = "x" if self.fullpath else "e" p = self.call_unrar(command, self.file, self.out, password=password) @@ -156,6 +156,7 @@ class UnRar(AbtractExtractor): raise CRCError elif "CRC failed" in err: raise WrongPassword + if err.strip(): #: raise error if anything is on stderr raise ArchiveError(err.strip()) if p.returncode: -- cgit v1.2.3 From 69616099c133fdc783abad44c2a0916acba4b6d1 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 17 Dec 2014 22:38:24 +0100 Subject: [SimpleHoster] Fix filesize recognition --- module/plugins/internal/SimpleHoster.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 86d9b4c9a..ad140423c 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -154,7 +154,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.74" + __version__ = "0.75" __pattern__ = r'^unmatchable$' @@ -300,7 +300,7 @@ class SimpleHoster(Hoster): cls.FILE_NAME_REPLACEMENTS if hasattr(cls, "FILE_NAME_REPLACEMENTS") else cls.NAME_REPLACEMENTS) #@TODO: Remove FILE_NAME_REPLACEMENTS check in 0.4.10 if 'S' in info['pattern']: - size = replace_patterns(info['pattern']['S'] + info['pattern']['U'] if 'U' in info else info['pattern']['S'], + size = replace_patterns(info['pattern']['S'] + info['pattern']['U'] if 'U' in info['pattern'] else info['pattern']['S'], cls.FILE_SIZE_REPLACEMENTS if hasattr(cls, "FILE_SIZE_REPLACEMENTS") else cls.SIZE_REPLACEMENTS) #@TODO: Remove FILE_SIZE_REPLACEMENTS check in 0.4.10 info['size'] = parseFileSize(size) @@ -361,6 +361,7 @@ class SimpleHoster(Hoster): if self.multihost: self.logDebug("Looking for leeched download link...") + self.logDebug("File url: %s" % self.pyfile.url) self.handleMulti() elif self.directDL: @@ -404,10 +405,8 @@ class SimpleHoster(Hoster): def downloadLink(self, link): - if not link: - return - - self.download(link, disposition=True) + if link and isinstance(link, basestring): + self.download(link, disposition=True) def checkFile(self): -- cgit v1.2.3 From 0860e09f5ff16ee3f097f6f9d444f277a38abd72 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 17 Dec 2014 23:03:46 +0100 Subject: Extend SimpleHoster in multi-hoster plugins (3) --- module/plugins/internal/MultiHoster.py | 41 ++++++++++++++++++--------------- module/plugins/internal/SimpleHoster.py | 2 +- 2 files changed, 24 insertions(+), 19 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index 6d10d17d9..0bcb79817 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -9,7 +9,7 @@ from module.utils import remove_chars class MultiHoster(Hook): __name__ = "MultiHoster" __type__ = "hook" - __version__ = "0.21" + __version__ = "0.22" __description__ = """Generic MultiHoster plugin""" __license__ = "GPLv3" @@ -18,19 +18,22 @@ class MultiHoster(Hook): interval = 12 * 60 * 60 #: reload hosters every 12h - HOSTER_REPLACEMENTS = [("1fichier.com", "onefichier.com"), - ("2shared.com", "twoshared.com"), - ("4shared.com", "fourshared.com"), - ("cloudnator.com", "shragle.com"), - ("easy-share.com", "crocko.com"), - ("freakshare.net", "freakshare.com"), - ("hellshare.com", "hellshare.cz"), - ("ifile.it", "filecloud.io"), - ("putlocker.com", "firedrive.com"), - ("share-rapid.cz", "multishare.cz"), - ("sharerapid.cz", "multishare.cz"), - ("ul.to", "uploaded.to"), - ("uploaded.net", "uploaded.to")] + HOSTER_REPLACEMENTS = [("1fichier.com" , "onefichier.com"), + ("2shared.com" , "twoshared.com" ), + ("4shared.com" , "fourshared.com"), + ("cloudnator.com" , "shragle.com" ), + ("easy-share.com" , "crocko.com" ), + ("fileparadox.com", "fileparadox.in"), + ("freakshare.net" , "freakshare.com"), + ("hellshare.com" , "hellshare.cz" ), + ("ifile.it" , "filecloud.io" ), + ("nowdownload.ch" , "nowdownload.sx"), + ("nowvideo.co" , "nowvideo.sx" ), + ("putlocker.com" , "firedrive.com" ), + ("share-rapid.cz" , "multishare.cz" ), + ("sharerapid.cz" , "multishare.cz" ), + ("ul.to" , "uploaded.to" ), + ("uploaded.net" , "uploaded.to" )] HOSTER_EXCLUDED = [] @@ -133,12 +136,12 @@ class MultiHoster(Hook): def overridePlugins(self): - pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.keys()) + pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys()) accountList = [name.lower() for name, data in self.core.accountManager.accounts.iteritems() if data] excludedList = [] for hoster in self.getHosterCached(): - name = remove_chars(hoster.lower(), "-.") + name = remove_chars(hoster, "-.") if name in accountList: excludedList.append(hoster) @@ -166,10 +169,12 @@ class MultiHoster(Hook): self.logInfo(_("The following hosters were not overwritten - account exists"), ", ".join(sorted(excludedList))) if self.new_supported: - self.logDebug("New Hosters", ", ".join(sorted(self.new_supported))) + hosters = sorted(self.new_supported) + + self.logDebug("New Hosters", ", ".join(hosters)) # create new regexp - regexp = r'.*(%s).*' % "|".join([x.replace(".", "\.") for x in self.new_supported]) + regexp = r'.*(%s).*' % "|".join([x.replace(".", "\.") for x in hosters]) if hasattr(klass, "__pattern__") and isinstance(klass.__pattern__, basestring) and '://' in klass.__pattern__: regexp = r'%s|%s' % (klass.__pattern__, regexp) diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index ad140423c..2ff60d6ea 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -361,7 +361,7 @@ class SimpleHoster(Hoster): if self.multihost: self.logDebug("Looking for leeched download link...") - self.logDebug("File url: %s" % self.pyfile.url) + self.logDebug("File url: %s" % pyfile.url) self.handleMulti() elif self.directDL: -- cgit v1.2.3 From ad2808a5eb6903875036c00b5195e8b7651379f0 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 17 Dec 2014 23:48:23 +0100 Subject: [XFSHoster] Improve NAME_PATTERN & SIZE_PATTERN --- module/plugins/internal/XFSHoster.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index bb4baa274..622f34ea9 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -16,7 +16,7 @@ from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.28" + __version__ = "0.29" __pattern__ = r'^unmatchable$' @@ -35,8 +35,8 @@ class XFSHoster(SimpleHoster): CHECK_DIRECT_LINK = None MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy... - NAME_PATTERN = r'(>Filename:|name="fname" value="|)(?P.+?)(\s*<|")' - SIZE_PATTERN = r'(>Size:|>File:.*>|\s*\(|)(?P[\d.,]+)\s*(?P[\w^_]+)' + NAME_PATTERN = r'(Filename[ ]*:[ ]*()?|name="fname"[ ]+value="|<[\w^_]+ class="(file)?name">)\s*(?P.+?)(\s*<|")' + SIZE_PATTERN = r'(Size[ ]*:[ ]*()?|File:.*>|\s*\(|<[\w^_]+ class="size">)\s*(?P[\d.,]+)\s*(?P[\w^_]+)' OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)' TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)' -- cgit v1.2.3 From 4e9c8f7ab1269966a9eac9e1b6363f5458f9f970 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Thu, 18 Dec 2014 16:07:21 +0100 Subject: Update checkFile routine in some hoster plugins --- module/plugins/internal/MultiHoster.py | 2 +- module/plugins/internal/SimpleHoster.py | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index 0bcb79817..68550a4dd 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -33,7 +33,7 @@ class MultiHoster(Hook): ("share-rapid.cz" , "multishare.cz" ), ("sharerapid.cz" , "multishare.cz" ), ("ul.to" , "uploaded.to" ), - ("uploaded.net" , "uploaded.to" )] + ("uploaded.net" , "uploaded.to" )] HOSTER_EXCLUDED = [] diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 2ff60d6ea..949a6c66a 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -2,6 +2,7 @@ import re +from os.path import exists from time import time from urllib import unquote from urlparse import urljoin, urlparse @@ -11,7 +12,7 @@ from module.network.CookieJar import CookieJar from module.network.RequestFactory import getURL from module.plugins.Hoster import Hoster from module.plugins.Plugin import Fail -from module.utils import fixup, parseFileSize +from module.utils import fixup, fs_encode, parseFileSize #@TODO: Adapt and move to PyFile in 0.4.10 @@ -154,7 +155,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.75" + __version__ = "0.76" __pattern__ = r'^unmatchable$' @@ -410,8 +411,19 @@ class SimpleHoster(Hoster): def checkFile(self): - if self.checkDownload({'empty': re.compile(r"^$")}) is "empty": #@TODO: Move to hoster in 0.4.10 - self.fail(_("Empty file")) + if not self.lastDownload or not exists(fs_encode(self.lastDownload)): + self.fail(_("No file downloaded")) + + else: + rules = {'empty file': re.compile(r"^$")} + + if hasattr(self, 'ERROR_PATTERN'): + rules['error'] = re.compile(self.ERROR_PATTERN) + + check = self.checkDownload(rules) + if check: #@TODO: Move to hoster in 0.4.10 + errmsg = check.strip().capitalize() + (" | " + self.lastCheck.strip() if self.lastCheck else "") + self.retry(10, 60, errmsg) def checkErrors(self): -- cgit v1.2.3 From da9e6c949243613f4d5e100cac6ff192449b4718 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Thu, 18 Dec 2014 18:45:17 +0100 Subject: Update extractor plugins --- module/plugins/internal/AbstractExtractor.py | 29 +++++++-------- module/plugins/internal/UnRar.py | 54 +++++++++++++--------------- module/plugins/internal/UnZip.py | 15 ++++---- 3 files changed, 47 insertions(+), 51 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/AbstractExtractor.py b/module/plugins/internal/AbstractExtractor.py index 2317ad689..c8a73c861 100644 --- a/module/plugins/internal/AbstractExtractor.py +++ b/module/plugins/internal/AbstractExtractor.py @@ -14,23 +14,24 @@ class WrongPassword(Exception): class AbtractExtractor: __name__ = "AbtractExtractor" - __version__ = "0.10" + __version__ = "0.11" __description__ = """Abtract extractor plugin""" __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] + __authors__ = [("RaNaN", "ranan@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com")] - @staticmethod - def checkDeps(): + @classmethod + def checkDeps(cls): """ Check if system statisfy dependencies :return: boolean """ return True - @staticmethod - def getTargets(files_ids): + @classmethod + def getTargets(cls, files_ids): """ Filter suited targets from list of filename id tuple list :param files_ids: List of filepathes :return: List of targets, id tuple list @@ -48,14 +49,14 @@ class AbtractExtractor: :param overwrite: Overwrite existing archives :param renice: Renice value """ - self.m = m - self.file = file - self.out = out - self.fullpath = fullpath - self.overwrite = overwrite + self.m = m + self.file = file + self.out = out + self.fullpath = fullpath + self.overwrite = overwrite self.excludefiles = excludefiles - self.renice = renice - self.files = [] #: Store extracted files here + self.renice = renice + self.files = [] #: Store extracted files here def init(self): @@ -83,7 +84,7 @@ class AbtractExtractor: return True - def extract(self, progress, password=None): + def extract(self, progress, password=""): """Extract the archive. Raise specific errors in case of failure. :param progress: Progress function, call this to update status diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index 716a62613..4bbd2042c 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -22,53 +22,52 @@ def renice(pid, value): class UnRar(AbtractExtractor): __name__ = "UnRar" - __version__ = "0.20" + __version__ = "0.21" __description__ = """Rar extractor plugin""" __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.org")] + __authors__ = [("RaNaN", "RaNaN@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com")] CMD = "unrar" - # there are some more uncovered rar formats - re_version = re.compile(r'UNRAR ([\w .]+?)') + #@NOTE: there are some more uncovered rar formats re_splitfile = re.compile(r'(.*)\.part(\d+)\.rar$', re.I) re_partfiles = re.compile(r'.*\.(rar|r\d+)', re.I) - re_filelist = re.compile(r'(.+)\s+(\d+)\s+(\d+)\s+') - re_filelist5 = re.compile(r'(.+)\s+(\d+)\s+\d\d-\d\d-\d\d\s+\d\d:\d\d\s+(.+)') + re_filelist = re.compile(r'(.+)\s+(\d+)\s+(\d+)\s+|(.+)\s+(\d+)\s+\d\d-\d\d-\d\d\s+\d\d:\d\d\s+(.+)') re_wrongpwd = re.compile(r'(Corrupt file or wrong password|password incorrect)', re.I) - @staticmethod - def checkDeps(): + @classmethod + def checkDeps(cls): if os.name == "nt": - UnRar.CMD = join(pypath, "UnRAR.exe") - p = Popen([UnRar.CMD], stdout=PIPE, stderr=PIPE) + cls.CMD = join(pypath, "UnRAR.exe") + p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) p.communicate() else: try: - p = Popen([UnRar.CMD], stdout=PIPE, stderr=PIPE) + p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) p.communicate() - except OSError: + except OSError: # fallback to rar - UnRar.CMD = "rar" - p = Popen([UnRar.CMD], stdout=PIPE, stderr=PIPE) + cls.CMD = "rar" + p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE) p.communicate() return True - @staticmethod - def getTargets(files_ids): + @classmethod + def getTargets(cls, files_ids): result = [] for file, id in files_ids: if not file.endswith(".rar"): continue - match = UnRar.re_splitfile.findall(file) + match = cls.re_splitfile.findall(file) if match: # only add first parts if int(match[0][1]) == 1: @@ -81,9 +80,8 @@ class UnRar(AbtractExtractor): def init(self): self.passwordProtected = False - self.headerProtected = False #: list files will not work without password - self.smallestFile = None #: small file to test passwords - self.password = "" #: save the correct password + self.headerProtected = False #: list files will not work without password + self.password = "" #: save the correct password def checkArchive(self): @@ -95,16 +93,10 @@ class UnRar(AbtractExtractor): return True # output only used to check if passworded files are present - if self.re_version.search(out): - for attr, size, name in self.re_filelist5.findall(out): - if attr.startswith("*"): - self.passwordProtected = True - return True - else: - for name, size, packed in self.re_filelist.findall(out): - if name.startswith("*"): - self.passwordProtected = True - return True + for attr in self.re_filelist.findall(out): + if attr[0].startswith("*"): + self.passwordProtected = True + return True self.listContent() if not self.files: @@ -131,6 +123,7 @@ class UnRar(AbtractExtractor): renice(p.pid, self.renice) progress(0) + progressstring = "" while True: c = p.stdout.read(1) @@ -147,6 +140,7 @@ class UnRar(AbtractExtractor): # add digit to progressstring else: progressstring = progressstring + c + progress(100) # retrieve stderr diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index 52e279ccf..81c298784 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -8,20 +8,21 @@ from module.plugins.internal.AbstractExtractor import AbtractExtractor, WrongPas class UnZip(AbtractExtractor): __name__ = "UnZip" - __version__ = "0.11" + __version__ = "0.12" __description__ = """Zip extractor plugin""" __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.org")] + __authors__ = [("RaNaN", "RaNaN@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com")] - @staticmethod - def checkDeps(): + @classmethod + def checkDeps(cls): return sys.version_info[:2] >= (2, 6) - @staticmethod - def getTargets(files_ids): + @classmethod + def getTargets(cls, files_ids): result = [] for file, id in files_ids: @@ -31,7 +32,7 @@ class UnZip(AbtractExtractor): return result - def extract(self, progress, password=None): + def extract(self, progress, password=""): try: z = zipfile.ZipFile(self.file) self.files = z.namelist() -- cgit v1.2.3 From 6d9c5ff2e06e06e33fa6674f013dd0e290092bbd Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 20 Dec 2014 14:25:57 +0100 Subject: [SimpleHoster] Improve checkFile --- module/plugins/internal/SimpleHoster.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 949a6c66a..784ef8c85 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -155,7 +155,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.76" + __version__ = "0.77" __pattern__ = r'^unmatchable$' @@ -407,11 +407,16 @@ class SimpleHoster(Hoster): def downloadLink(self, link): if link and isinstance(link, basestring): + self.correctCaptcha() self.download(link, disposition=True) def checkFile(self): - if not self.lastDownload or not exists(fs_encode(self.lastDownload)): + if self.cTask and not self.lastDownload: + self.invalidCaptcha() + self.retry(10, reason=_("Wrong captcha")) + + elif not self.lastDownload or not exists(fs_encode(self.lastDownload)): self.fail(_("No file downloaded")) else: -- cgit v1.2.3 From ad8d5997b60012e7f1c895956f5ea713870177bb Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 23 Dec 2014 00:58:03 +0100 Subject: [XFSHoster] Improve error handling --- module/plugins/internal/XFSHoster.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index 622f34ea9..7038743c1 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -16,7 +16,7 @@ from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.29" + __version__ = "0.30" __pattern__ = r'^unmatchable$' @@ -238,7 +238,7 @@ class XFSHoster(SimpleHoster): elif 'maintenance' in self.errmsg or 'maintainance' in self.errmsg: self.tempOffline() - elif 'download files up to' in self.errmsg: + elif 'up to' in self.errmsg: self.fail(_("File too large for free download")) else: -- cgit v1.2.3 From 57a319563651a07bf8265ab52da0d7375191319c Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 23 Dec 2014 13:13:42 +0100 Subject: Rename MultiHoster plugin to MultiHook --- module/plugins/internal/MultiHook.py | 217 +++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 module/plugins/internal/MultiHook.py (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py new file mode 100644 index 000000000..dcf1c3383 --- /dev/null +++ b/module/plugins/internal/MultiHook.py @@ -0,0 +1,217 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.Hook import Hook +from module.utils import remove_chars + + +class MultiHook(Hook): + __name__ = "MultiHook" + __type__ = "hook" + __version__ = "0.22" + + __description__ = """Hook plugin for MultiHoster""" + __license__ = "GPLv3" + __authors__ = [("pyLoad Team", "admin@pyload.org")] + + + interval = 12 * 60 * 60 #: reload hosters every 12h + + HOSTER_REPLACEMENTS = [("1fichier.com" , "onefichier.com"), + ("2shared.com" , "twoshared.com" ), + ("4shared.com" , "fourshared.com"), + ("cloudnator.com" , "shragle.com" ), + ("easy-share.com" , "crocko.com" ), + ("fileparadox.com", "fileparadox.in"), + ("freakshare.net" , "freakshare.com"), + ("hellshare.com" , "hellshare.cz" ), + ("ifile.it" , "filecloud.io" ), + ("nowdownload.ch" , "nowdownload.sx"), + ("nowvideo.co" , "nowvideo.sx" ), + ("putlocker.com" , "firedrive.com" ), + ("share-rapid.cz" , "multishare.cz" ), + ("sharerapid.cz" , "multishare.cz" ), + ("ul.to" , "uploaded.to" ), + ("uploaded.net" , "uploaded.to" )] + HOSTER_EXCLUDED = [] + + + def setup(self): + self.hosters = [] + self.supported = [] + self.new_supported = [] + + + def getConfig(self, option, default=''): + """getConfig with default value - sublass may not implements all config options""" + try: + return self.getConf(option) + except KeyError: + return default + + + def getHosterCached(self): + if not self.hosters: + try: + hosterSet = self.toHosterSet(self.getHoster()) - set(self.HOSTER_EXCLUDED) + except Exception, e: + self.logError(e) + return [] + + try: + configMode = self.getConfig('hosterListMode', 'all') + if configMode in ("listed", "unlisted"): + configSet = self.toHosterSet(self.getConfig('hosterList', '').replace('|', ',').replace(';', ',').split(',')) + + if configMode == "listed": + hosterSet &= configSet + else: + hosterSet -= configSet + + except Exception, e: + self.logError(e) + + self.hosters = list(hosterSet) + + return self.hosters + + + def toHosterSet(self, hosters): + hosters = set((str(x).strip().lower() for x in hosters)) + + for rep in self.HOSTER_REPLACEMENTS: + if rep[0] in hosters: + hosters.remove(rep[0]) + hosters.add(rep[1]) + + hosters.discard('') + return hosters + + + def getHoster(self): + """Load list of supported hoster + + :return: List of domain names + """ + raise NotImplementedError + + + def coreReady(self): + if self.cb: + self.core.scheduler.removeJob(self.cb) + + self.setConfig("activated", True) #: config not in sync after plugin reload + + cfg_interval = self.getConfig("interval", None) #: reload interval in hours + if cfg_interval is not None: + self.interval = cfg_interval * 60 * 60 + + if self.interval: + self._periodical() + else: + self.periodical() + + + def initPeriodical(self): + pass + + + def periodical(self): + """reload hoster list periodically""" + self.logInfo(_("Reloading supported hoster list")) + + old_supported = self.supported + self.supported = [] + self.new_supported = [] + self.hosters = [] + + self.overridePlugins() + + old_supported = [hoster for hoster in old_supported if hoster not in self.supported] + if old_supported: + self.logDebug("UNLOAD", ", ".join(old_supported)) + for hoster in old_supported: + self.unloadHoster(hoster) + + + def overridePlugins(self): + pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys()) + accountList = [name.lower() for name, data in self.core.accountManager.accounts.iteritems() if data] + excludedList = [] + + for hoster in self.getHosterCached(): + name = remove_chars(hoster, "-.") + + if name in accountList: + excludedList.append(hoster) + else: + if name in pluginMap: + self.supported.append(pluginMap[name]) + else: + self.new_supported.append(hoster) + + if not self.supported and not self.new_supported: + self.logError(_("No Hoster loaded")) + return + + module = self.core.pluginManager.getPlugin(self.__name__) + klass = getattr(module, self.__name__) + + # inject plugin plugin + self.logDebug("Overwritten Hosters", ", ".join(sorted(self.supported))) + for hoster in self.supported: + hdict = self.core.pluginManager.hosterPlugins[hoster] + hdict['new_module'] = module + hdict['new_name'] = self.__name__ + + if excludedList: + self.logInfo(_("The following hosters were not overwritten - account exists"), ", ".join(sorted(excludedList))) + + if self.new_supported: + hosters = sorted(self.new_supported) + + self.logDebug("New Hosters", ", ".join(hosters)) + + # create new regexp + regexp = r'.*(%s).*' % "|".join([x.replace(".", "\.") for x in hosters]) + if hasattr(klass, "__pattern__") and isinstance(klass.__pattern__, basestring) and '://' in klass.__pattern__: + regexp = r'%s|%s' % (klass.__pattern__, regexp) + + self.logDebug("Regexp", regexp) + + hdict = self.core.pluginManager.hosterPlugins[self.__name__] + hdict['pattern'] = regexp + hdict['re'] = re.compile(regexp) + + + def unloadHoster(self, hoster): + hdict = self.core.pluginManager.hosterPlugins[hoster] + if "module" in hdict: + del hdict['module'] + + if "new_module" in hdict: + del hdict['new_module'] + del hdict['new_name'] + + + def unload(self): + """Remove override for all hosters. Scheduler job is removed by hookmanager""" + for hoster in self.supported: + self.unloadHoster(hoster) + + # reset pattern + klass = getattr(self.core.pluginManager.getPlugin(self.__name__), self.__name__) + hdict = self.core.pluginManager.hosterPlugins[self.__name__] + hdict['pattern'] = getattr(klass, "__pattern__", r'^unmatchable$') + hdict['re'] = re.compile(hdict['pattern']) + + + def downloadFailed(self, pyfile): + """remove plugin override if download fails but not if file is offline/temp.offline""" + if pyfile.hasStatus("failed") and self.getConfig("unloadFailing", True): + hdict = self.core.pluginManager.hosterPlugins[pyfile.pluginname] + if "new_name" in hdict and hdict['new_name'] == self.__name__: + self.logDebug("Unload MultiHook", pyfile.pluginname, hdict) + self.unloadHoster(pyfile.pluginname) + pyfile.setStatus("queued") -- cgit v1.2.3 From 87203e996fb42c172b15e29f0e394d5b328d9ac2 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 23 Dec 2014 13:20:53 +0100 Subject: New plugin: MultiHoster --- module/plugins/internal/MultiHoster.py | 226 ++++++--------------------------- 1 file changed, 36 insertions(+), 190 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index 68550a4dd..4425cfce0 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -2,216 +2,62 @@ import re -from module.plugins.Hook import Hook -from module.utils import remove_chars +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies -class MultiHoster(Hook): +class MultiHoster(SimpleHoster): __name__ = "MultiHoster" - __type__ = "hook" - __version__ = "0.22" + __type__ = "hoster" + __version__ = "0.23" - __description__ = """Generic MultiHoster plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - interval = 12 * 60 * 60 #: reload hosters every 12h - - HOSTER_REPLACEMENTS = [("1fichier.com" , "onefichier.com"), - ("2shared.com" , "twoshared.com" ), - ("4shared.com" , "fourshared.com"), - ("cloudnator.com" , "shragle.com" ), - ("easy-share.com" , "crocko.com" ), - ("fileparadox.com", "fileparadox.in"), - ("freakshare.net" , "freakshare.com"), - ("hellshare.com" , "hellshare.cz" ), - ("ifile.it" , "filecloud.io" ), - ("nowdownload.ch" , "nowdownload.sx"), - ("nowvideo.co" , "nowvideo.sx" ), - ("putlocker.com" , "firedrive.com" ), - ("share-rapid.cz" , "multishare.cz" ), - ("sharerapid.cz" , "multishare.cz" ), - ("ul.to" , "uploaded.to" ), - ("uploaded.net" , "uploaded.to" )] - HOSTER_EXCLUDED = [] - - - def setup(self): - self.hosters = [] - self.supported = [] - self.new_supported = [] - - - def getConfig(self, option, default=''): - """getConfig with default value - sublass may not implements all config options""" - try: - return self.getConf(option) - except KeyError: - return default - - - def getHosterCached(self): - if not self.hosters: - try: - hosterSet = self.toHosterSet(self.getHoster()) - set(self.HOSTER_EXCLUDED) - except Exception, e: - self.logError(e) - return [] - - try: - configMode = self.getConfig('hosterListMode', 'all') - if configMode in ("listed", "unlisted"): - configSet = self.toHosterSet(self.getConfig('hosterList', '').replace('|', ',').replace(';', ',').split(',')) - - if configMode == "listed": - hosterSet &= configSet - else: - hosterSet -= configSet + __pattern__ = r'^unmatchable$' - except Exception, e: - self.logError(e) - - self.hosters = list(hosterSet) - - return self.hosters - - - def toHosterSet(self, hosters): - hosters = set((str(x).strip().lower() for x in hosters)) - - for rep in self.HOSTER_REPLACEMENTS: - if rep[0] in hosters: - hosters.remove(rep[0]) - hosters.add(rep[1]) + __description__ = """Multi hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - hosters.discard('') - return hosters + DIRECT_LINK = True + MULTI_HOSTER = True + LOGIN_ACCOUNT = True + LOGIN_PREMIUM = False - def getHoster(self): - """Load list of supported hoster - :return: List of domain names - """ - raise NotImplementedError + def setup(self): + self.chunkLimit = 1 + self.multiDL = self.premium - def coreReady(self): - if self.cb: - self.core.scheduler.removeJob(self.cb) + def prepare(self): + self.info = {} + self.link = "" + self.multihost = False - self.setConfig("activated", True) #: config not in sync after plugin reload + self.req.setOption("timeout", 120) - cfg_interval = self.getConfig("interval", None) #: reload interval in hours - if cfg_interval is not None: - self.interval = cfg_interval * 60 * 60 + if isinstance(self.COOKIES, list): + set_cookies(self.req.cj, self.COOKIES) - if self.interval: - self._periodical() + if self.DIRECT_LINK is None: + self.directDL = bool(self.account) else: - self.periodical() - - - def initPeriodical(self): - pass + self.directDL = self.DIRECT_LINK + if (self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] + or re.match(self.__pattern__, self.pyfile.url) is None): - def periodical(self): - """reload hoster list periodically""" - self.logInfo(_("Reloading supported hoster list")) + if self.LOGIN_ACCOUNT and not self.account: + self.logError(_("Required account not found")) - old_supported = self.supported - self.supported = [] - self.new_supported = [] - self.hosters = [] + elif self.LOGIN_PREMIUM and not self.premium: + self.logError(_("Required premium account not found")) - self.overridePlugins() - - old_supported = [hoster for hoster in old_supported if hoster not in self.supported] - if old_supported: - self.logDebug("UNLOAD", ", ".join(old_supported)) - for hoster in old_supported: - self.unloadHoster(hoster) - - - def overridePlugins(self): - pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys()) - accountList = [name.lower() for name, data in self.core.accountManager.accounts.iteritems() if data] - excludedList = [] - - for hoster in self.getHosterCached(): - name = remove_chars(hoster, "-.") - - if name in accountList: - excludedList.append(hoster) else: - if name in pluginMap: - self.supported.append(pluginMap[name]) - else: - self.new_supported.append(hoster) - - if not self.supported and not self.new_supported: - self.logError(_("No Hoster loaded")) - return - - module = self.core.pluginManager.getPlugin(self.__name__) - klass = getattr(module, self.__name__) - - # inject plugin plugin - self.logDebug("Overwritten Hosters", ", ".join(sorted(self.supported))) - for hoster in self.supported: - hdict = self.core.pluginManager.hosterPlugins[hoster] - hdict['new_module'] = module - hdict['new_name'] = self.__name__ - - if excludedList: - self.logInfo(_("The following hosters were not overwritten - account exists"), ", ".join(sorted(excludedList))) - - if self.new_supported: - hosters = sorted(self.new_supported) + self.multihost = True - self.logDebug("New Hosters", ", ".join(hosters)) + self.pyfile.url = replace_patterns(self.pyfile.url, + self.FILE_URL_REPLACEMENTS if hasattr(self, "FILE_URL_REPLACEMENTS") else self.URL_REPLACEMENTS) #@TODO: Remove FILE_URL_REPLACEMENTS check in 0.4.10 - # create new regexp - regexp = r'.*(%s).*' % "|".join([x.replace(".", "\.") for x in hosters]) - if hasattr(klass, "__pattern__") and isinstance(klass.__pattern__, basestring) and '://' in klass.__pattern__: - regexp = r'%s|%s' % (klass.__pattern__, regexp) - self.logDebug("Regexp", regexp) - - hdict = self.core.pluginManager.hosterPlugins[self.__name__] - hdict['pattern'] = regexp - hdict['re'] = re.compile(regexp) - - - def unloadHoster(self, hoster): - hdict = self.core.pluginManager.hosterPlugins[hoster] - if "module" in hdict: - del hdict['module'] - - if "new_module" in hdict: - del hdict['new_module'] - del hdict['new_name'] - - - def unload(self): - """Remove override for all hosters. Scheduler job is removed by hookmanager""" - for hoster in self.supported: - self.unloadHoster(hoster) - - # reset pattern - klass = getattr(self.core.pluginManager.getPlugin(self.__name__), self.__name__) - hdict = self.core.pluginManager.hosterPlugins[self.__name__] - hdict['pattern'] = getattr(klass, "__pattern__", r'^unmatchable$') - hdict['re'] = re.compile(hdict['pattern']) - - - def downloadFailed(self, pyfile): - """remove plugin override if download fails but not if file is offline/temp.offline""" - if pyfile.hasStatus("failed") and self.getConfig("unloadFailing", True): - hdict = self.core.pluginManager.hosterPlugins[pyfile.pluginname] - if "new_name" in hdict and hdict['new_name'] == self.__name__: - self.logDebug("Unload MultiHoster", pyfile.pluginname, hdict) - self.unloadHoster(pyfile.pluginname) - pyfile.setStatus("queued") + def handleMulti(self): + raise NotImplementedError -- cgit v1.2.3 From e1d4186c62512d8bb76d35b6f8d1828d8d0aa94e Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 23 Dec 2014 13:26:32 +0100 Subject: [SimpleHoster] Improve multi-hoster feature --- module/plugins/internal/SimpleHoster.py | 38 ++++++++++++++++----------------- module/plugins/internal/XFSHoster.py | 5 ++++- 2 files changed, 23 insertions(+), 20 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 784ef8c85..ab114c9ec 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -155,7 +155,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.77" + __version__ = "0.78" __pattern__ = r'^unmatchable$' @@ -214,9 +214,9 @@ class SimpleHoster(Hoster): TEXT_ENCODING = False #: Set to True or encoding name if encoding value in http header is not correct COOKIES = True #: or False or list of tuples [(domain, name, value)] - FORCE_CHECK_TRAFFIC = False #: Set to True to force checking traffic left for premium account - CHECK_DIRECT_LINK = None #: Set to True to check for direct link, set to None to do it only if self.account is True - MULTI_HOSTER = False #: Set to True to leech other hoster link (according its multihoster hook if available) + CHECK_TRAFFIC = False #: Set to True to force checking traffic left for premium account + DIRECT_LINK = None #: Set to True to looking for direct link (as defined in handleDirect method), set to None to do it if self.account is True else False + MULTI_HOSTER = False #: Set to True to leech other hoster link (as defined in handleMulti method) @classmethod @@ -334,17 +334,13 @@ class SimpleHoster(Hoster): if (self.MULTI_HOSTER and (self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] or re.match(self.__pattern__, self.pyfile.url) is None)): + self.multihost = True + return - self.logInfo("Multi hoster detected") - - if self.account: - self.multihost = True - return - else: - self.fail(_("Only registered or premium users can use url leech feature")) - - if self.CHECK_DIRECT_LINK is None: + if self.DIRECT_LINK is None: self.directDL = bool(self.account) + else: + self.directDL = self.DIRECT_LINK self.pyfile.url = replace_patterns(self.pyfile.url, self.FILE_URL_REPLACEMENTS if hasattr(self, "FILE_URL_REPLACEMENTS") else self.URL_REPLACEMENTS) #@TODO: Remove FILE_URL_REPLACEMENTS check in 0.4.10 @@ -360,16 +356,20 @@ class SimpleHoster(Hoster): def process(self, pyfile): self.prepare() - if self.multihost: + if self.directDL: + self.logDebug("Looking for direct download link...") + self.handleDirect() + + if self.multihost and not self.link and not self.lastDownload: self.logDebug("Looking for leeched download link...") self.logDebug("File url: %s" % pyfile.url) self.handleMulti() - elif self.directDL: - self.logDebug("Looking for direct download link...") - self.handleDirect() + if not self.link and not self.lastDownload: + self.MULTI_HOSTER = False + self.retry(1, reason="Multi hoster fails") - if not self.link: + if not self.link and not self.lastDownload: self.preload() if self.html is None: @@ -390,7 +390,7 @@ class SimpleHoster(Hoster): self.checkErrors() - if self.premium and (not self.FORCE_CHECK_TRAFFIC or self.checkTrafficLeft()): + if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): self.logDebug("Handled as premium download") self.handlePremium() diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index 7038743c1..dd2dd2527 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -16,7 +16,7 @@ from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.30" + __version__ = "0.31" __pattern__ = r'^unmatchable$' @@ -142,6 +142,9 @@ class XFSHoster(SimpleHoster): def handleMulti(self): + if not self.account: + self.fail(_("Only registered or premium users can use url leech feature")) + #only tested with easybytez.com self.html = self.load("http://www.%s/" % self.HOSTER_DOMAIN) -- cgit v1.2.3 From badfd177fb3639869441f4738461c7f576e1d078 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 23 Dec 2014 17:22:47 +0100 Subject: [SimpleHoster] Update --- module/plugins/internal/SimpleCrypter.py | 12 +---- module/plugins/internal/SimpleHoster.py | 81 +++++++++++++++----------------- 2 files changed, 38 insertions(+), 55 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py index 53ffaf4a6..e0dd10585 100644 --- a/module/plugins/internal/SimpleCrypter.py +++ b/module/plugins/internal/SimpleCrypter.py @@ -12,7 +12,7 @@ from module.utils import fixup class SimpleCrypter(Crypter, SimpleHoster): __name__ = "SimpleCrypter" __type__ = "crypter" - __version__ = "0.32" + __version__ = "0.33" __pattern__ = r'^unmatchable$' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package'] @@ -120,16 +120,6 @@ class SimpleCrypter(Crypter, SimpleHoster): self.packages = [(self.info['name'], self.links, self.info['folder'])] - def checkStatus(self): - status = self.info['status'] - - if status is 1: - self.offline() - - elif status is 6: - self.tempOffline() - - def checkNameSize(self): name = self.info['name'] url = self.info['url'] diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index ab114c9ec..95833d0cf 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -125,29 +125,34 @@ def timestamp(): #@TODO: Move to hoster class in 0.4.10 -def _isDirectLink(self, url, resumable=True): - header = self.load(url, ref=True, just_header=True, decode=True) +def _isDirectLink(self, url, resumable=False): + link = "" - if not 'location' in header or not header['location']: - return "" + for i in xrange(5 if resumable else 1): + header = self.load(url, ref=True, cookies=True, just_header=True, decode=True) - location = header['location'] + if 'content-disposition' in header: + link = url - resumable = False #@NOTE: Testing... + elif 'location' in header and header['location']: + location = header['location'] - if resumable: #: sometimes http code may be wrong... - if 'location' in self.load(location, ref=True, cookies=True, just_header=True, decode=True): - return "" - else: - if not 'code' in header or header['code'] != 302: - return "" + if not urlparse(location).scheme: + p = urlparse(url) + base = "%s://%s" % (p.scheme, p.netloc) + location = urljoin(base, location) + + if 'code' in header and header['code'] == 302: + link = location + + elif resumable: + url = location + self.logDebug("Redirect #%d to: %s" % (++i, location)) + continue - if urlparse(location).scheme: - link = location + break else: - p = urlparse(url) - base = "%s://%s" % (p.scheme, p.netloc) - link = urljoin(base, location) + self.logError(_("Too many redirects")) return link @@ -155,7 +160,7 @@ def _isDirectLink(self, url, resumable=True): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.78" + __version__ = "0.79" __pattern__ = r'^unmatchable$' @@ -355,6 +360,7 @@ class SimpleHoster(Hoster): def process(self, pyfile): self.prepare() + self.checkInfo() if self.directDL: self.logDebug("Looking for direct download link...") @@ -371,32 +377,15 @@ class SimpleHoster(Hoster): if not self.link and not self.lastDownload: self.preload() + self.checkInfo() if self.html is None: self.fail(_("No html retrieved")) - self.updateInfo(self.getInfo(pyfile.url, self.html)) - - self.checkNameSize() - - if hasattr(self, 'PREMIUM_ONLY_PATTERN'): - premium_only = re.search(self.PREMIUM_ONLY_PATTERN, self.html) - else: - premium_only = False - - #: Usually premium only pages doesn't show any file information - if not premium_only: - self.checkStatus() - - self.checkErrors() - if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): self.logDebug("Handled as premium download") self.handlePremium() - elif premium_only: - self.fail(_("Link require a premium account to be handled")) - else: self.logDebug("Handled as free download") self.handleFree() @@ -432,6 +421,9 @@ class SimpleHoster(Hoster): def checkErrors(self): + if hasattr(self, 'PREMIUM_ONLY_PATTERN') and self.premium and re.search(self.PREMIUM_ONLY_PATTERN, self.html): + self.fail(_("Link require a premium account to be handled")) + if hasattr(self, 'ERROR_PATTERN'): m = re.search(self.ERROR_PATTERN, self.html) if m: @@ -459,9 +451,8 @@ class SimpleHoster(Hoster): self.tempOffline() elif status is not 2: - self.logInfo(_("File status: %s") % statusMap[status], - _("File info: %s") % self.info) - self.error(_("No file info retrieved")) + self.logDebug(_("File status: %s") % statusMap[status], + _("File info: %s") % self.info) def checkNameSize(self): @@ -484,9 +475,14 @@ class SimpleHoster(Hoster): def checkInfo(self): - self.checkErrors() + self.updateInfo(self.getInfo(self.pyfile.url, self.html)) - self.updateInfo(self.getInfo(self.pyfile.url, self.html or "")) + self.checkNameSize() + + if self.html: + self.checkErrors() + + self.updateInfo(self.getInfo(self.pyfile.url, self.html)) self.checkNameSize() self.checkStatus() @@ -512,9 +508,6 @@ class SimpleHoster(Hoster): self.logInfo(_("Direct download link detected")) self.link = link - - self.updateInfo(self.getInfo(self.pyfile.url)) - self.checkNameSize() else: self.logDebug(_("Direct download link not found")) -- cgit v1.2.3 From cc833c564e01971b0a915c2f5343ad683c65b825 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 23 Dec 2014 18:49:39 +0100 Subject: [LinestorageCom] Fix account plugin --- module/plugins/internal/XFSAccount.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/XFSAccount.py b/module/plugins/internal/XFSAccount.py index 2094b1480..2784ecd0b 100644 --- a/module/plugins/internal/XFSAccount.py +++ b/module/plugins/internal/XFSAccount.py @@ -12,7 +12,7 @@ from module.plugins.internal.SimpleHoster import parseHtmlForm, set_cookies class XFSAccount(Account): __name__ = "XFSAccount" __type__ = "account" - __version__ = "0.32" + __version__ = "0.33" __description__ = """XFileSharing account plugin""" __license__ = "GPLv3" @@ -44,11 +44,11 @@ class XFSAccount(Account): def init(self): - # if not self.HOSTER_DOMAIN: - # self.fail(_("Missing HOSTER_DOMAIN")) + if not self.HOSTER_DOMAIN: + self.logError(_("Missing HOSTER_DOMAIN")) if not self.HOSTER_URL: - self.HOSTER_URL = "http://www.%s/" % self.HOSTER_DOMAIN + self.HOSTER_URL = "http://www.%s/" % self.HOSTER_DOMAIN or "" def loadAccountInfo(self, user, req): -- cgit v1.2.3 From 9c9843e6c7681ef52a882033eaabb44afacc5b8e Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 23 Dec 2014 18:51:01 +0100 Subject: [SimpleHoster] Code cosmetics --- module/plugins/internal/SimpleHoster.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 95833d0cf..6726726e1 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -368,7 +368,6 @@ class SimpleHoster(Hoster): if self.multihost and not self.link and not self.lastDownload: self.logDebug("Looking for leeched download link...") - self.logDebug("File url: %s" % pyfile.url) self.handleMulti() if not self.link and not self.lastDownload: @@ -451,8 +450,8 @@ class SimpleHoster(Hoster): self.tempOffline() elif status is not 2: - self.logDebug(_("File status: %s") % statusMap[status], - _("File info: %s") % self.info) + self.logDebug("File status: %s" % statusMap[status], + "File info: %s" % self.info) def checkNameSize(self): @@ -496,9 +495,9 @@ class SimpleHoster(Hoster): def updateInfo(self, info): - self.logDebug(_("File info (before update): %s") % self.info) + self.logDebug(_("File info (BEFORE): %s") % self.info) self.info.update(info) - self.logDebug(_("File info (after update): %s") % self.info) + self.logDebug(_("File info (AFTER): %s") % self.info) def handleDirect(self): -- cgit v1.2.3 From a4786e340993bbfc5d2bf971c9bec18863d3dd80 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 23 Dec 2014 19:29:15 +0100 Subject: [MultiHoster] Update --- module/plugins/internal/MultiHoster.py | 53 +++++++++++++++------------------- 1 file changed, 24 insertions(+), 29 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index 4425cfce0..e5c28d034 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -2,13 +2,13 @@ import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class MultiHoster(SimpleHoster): __name__ = "MultiHoster" __type__ = "hoster" - __version__ = "0.23" + __version__ = "0.24" __pattern__ = r'^unmatchable$' @@ -18,9 +18,6 @@ class MultiHoster(SimpleHoster): DIRECT_LINK = True - MULTI_HOSTER = True - LOGIN_ACCOUNT = True - LOGIN_PREMIUM = False def setup(self): @@ -28,36 +25,34 @@ class MultiHoster(SimpleHoster): self.multiDL = self.premium - def prepare(self): - self.info = {} - self.link = "" - self.multihost = False + def process(self, pyfile): + self.prepare() - self.req.setOption("timeout", 120) + if self.directDL: + self.logDebug("Looking for direct download link...") + self.handleDirect() - if isinstance(self.COOKIES, list): - set_cookies(self.req.cj, self.COOKIES) + if not self.link and not self.lastDownload: + self.preload() - if self.DIRECT_LINK is None: - self.directDL = bool(self.account) - else: - self.directDL = self.DIRECT_LINK + if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): + self.logDebug("Handled as premium download") + self.handlePremium() - if (self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] - or re.match(self.__pattern__, self.pyfile.url) is None): + else: + self.logDebug("Handled as free download") + self.handleFree() - if self.LOGIN_ACCOUNT and not self.account: - self.logError(_("Required account not found")) + self.downloadLink(self.link) + self.checkFile() - elif self.LOGIN_PREMIUM and not self.premium: - self.logError(_("Required premium account not found")) - else: - self.multihost = True + def handlePremium(self): + return self.handleFree() - self.pyfile.url = replace_patterns(self.pyfile.url, - self.FILE_URL_REPLACEMENTS if hasattr(self, "FILE_URL_REPLACEMENTS") else self.URL_REPLACEMENTS) #@TODO: Remove FILE_URL_REPLACEMENTS check in 0.4.10 - - def handleMulti(self): - raise NotImplementedError + def handleFree(self): + if self.premium: + raise NotImplementedError + else: + self.logError(_("Required account not found")) -- cgit v1.2.3 From 29df1397bbbe80eced4674b6fa39e16540c80901 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 24 Dec 2014 01:11:44 +0100 Subject: Extractor rewritten --- module/plugins/internal/UnRar.py | 179 +++++++++++++++++++++++---------------- module/plugins/internal/UnZip.py | 64 ++++++++++---- 2 files changed, 157 insertions(+), 86 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index 4bbd2042c..5633b31f7 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -4,11 +4,11 @@ import os import re from glob import glob -from os.path import basename, join +from os.path import basename, dirname, join from string import digits from subprocess import Popen, PIPE -from module.plugins.internal.AbstractExtractor import AbtractExtractor, WrongPassword, ArchiveError, CRCError +from module.plugins.internal.AbstractExtractor import AbtractExtractor, PasswordError, ArchiveError, CRCError from module.utils import save_join, decode @@ -22,21 +22,25 @@ def renice(pid, value): class UnRar(AbtractExtractor): __name__ = "UnRar" - __version__ = "0.21" + __version__ = "1.00" __description__ = """Rar extractor plugin""" __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com")] + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] CMD = "unrar" + EXTENSIONS = ["rar", "zip", "cab", "arj", "lzh", "tar", "gz", "bz2", "ace", "uue", "jar", "iso", "7z", "xz", "z"] + + #@NOTE: there are some more uncovered rar formats - re_splitfile = re.compile(r'(.*)\.part(\d+)\.rar$', re.I) - re_partfiles = re.compile(r'.*\.(rar|r\d+)', re.I) + re_rarpart = re.compile(r'(.*)\.part(\d+)\.rar$', re.I) + re_rarfile = re.compile(r'.*\.(rar|r\d+)$', re.I) + re_filelist = re.compile(r'(.+)\s+(\d+)\s+(\d+)\s+|(.+)\s+(\d+)\s+\d\d-\d\d-\d\d\s+\d\d:\d\d\s+(.+)') - re_wrongpwd = re.compile(r'(Corrupt file or wrong password|password incorrect)', re.I) + re_wrongpwd = re.compile(r'password', re.I) + re_wrongcrc = re.compile(r'encrypted|damaged|CRC failed|checksum error', re.I) @classmethod @@ -59,70 +63,100 @@ class UnRar(AbtractExtractor): return True + @classmethod + def isArchive(cls, file): + f = basename(file).lower() + return any(f.endswith('.%s' % ext) for ext in cls.EXTENSIONS) + + @classmethod def getTargets(cls, files_ids): - result = [] + targets = [] for file, id in files_ids: - if not file.endswith(".rar"): + if not cls.isArchive(file): continue - match = cls.re_splitfile.findall(file) - if match: + m = cls.re_rarpart.findall(file) + if m: # only add first parts - if int(match[0][1]) == 1: - result.append((file, id)) + if int(m[0][1]) == 1: + targets.append((file, id)) else: - result.append((file, id)) + targets.append((file, id)) - return result + return targets - def init(self): - self.passwordProtected = False - self.headerProtected = False #: list files will not work without password - self.password = "" #: save the correct password + def check(self, out="", err=""): + if not out or not err: + return + if err.strip(): + if self.re_wrongpwd.search(err): + raise PasswordError - def checkArchive(self): - p = self.call_unrar("l", "-v", self.file) - out, err = p.communicate() - if self.re_wrongpwd.search(err): - self.passwordProtected = True - self.headerProtected = True - return True + elif self.re_wrongcrc.search(err): + raise CRCError + + else: #: raise error if anything is on stderr + raise ArchiveError(err.strip()) # output only used to check if passworded files are present for attr in self.re_filelist.findall(out): if attr[0].startswith("*"): - self.passwordProtected = True - return True + raise PasswordError + - self.listContent() - if not self.files: - raise ArchiveError("Empty Archive") + def verify(self): + p = self.call_cmd("l", "-v", self.file, password=self.password) + + self.check(*p.communicate()) + + if p and p.returncode: + raise ArchiveError("Process terminated") + + if not self.list(): + raise ArchiveError("Empty archive") + + + def isPassword(self, password): + if isinstance(password, basestring): + p = self.call_cmd("l", "-v", self.file, password=password) + out, err = p.communicate() + + if not self.re_wrongpwd.search(err): + return True return False - def checkPassword(self, password): - # at this point we can only verify header protected files - if self.headerProtected: - p = self.call_unrar("l", "-v", self.file, password=password) + def repair(self): + p = self.call_cmd("rc", self.file) + out, err = p.communicate() + + if p.returncode or err.strip(): + p = self.call_cmd("r", self.file) out, err = p.communicate() - if self.re_wrongpwd.search(err): + + if p.returncode or err.strip(): return False + else: + self.file = join(dirname(self.file), re.search(r'(fixed|rebuild)\.%s' % basename(self.file), out).group(0)) return True - def extract(self, progress, password=""): + def extract(self, progress=lambda x: None): + self.verify() + + progress(0) + command = "x" if self.fullpath else "e" - p = self.call_unrar(command, self.file, self.out, password=password) - renice(p.pid, self.renice) + p = self.call_cmd(command, self.file, self.out, password=self.password) - progress(0) + renice(p.pid, self.renice) progressstring = "" while True: @@ -131,7 +165,7 @@ class UnRar(AbtractExtractor): if not c: break # reading a percentage sign -> set progress and restart - if c == '%': + if c is '%': progress(int(progressstring)) progressstring = "" # not reading a digit -> therefore restart @@ -139,46 +173,43 @@ class UnRar(AbtractExtractor): progressstring = "" # add digit to progressstring else: - progressstring = progressstring + c + progressstring += c progress(100) - # retrieve stderr - err = p.stderr.read() + self.files = self.list() - if "CRC failed" in err and not password and not self.passwordProtected: - raise CRCError - elif "CRC failed" in err: - raise WrongPassword + # retrieve stderr + self.check(err=p.stderr.read()) - if err.strip(): #: raise error if anything is on stderr - raise ArchiveError(err.strip()) if p.returncode: raise ArchiveError("Process terminated") - if not self.files: - self.password = password - self.listContent() - def getDeleteFiles(self): if ".part" in basename(self.file): return glob(re.sub("(?<=\.part)([01]+)", "*", self.file, re.I)) + # get files which matches .r* and filter unsuited files out parts = glob(re.sub(r"(?<=\.r)ar$", "*", self.file, re.I)) - return filter(lambda x: self.re_partfiles.match(x), parts) + return filter(lambda x: self.re_rarfile.match(x), parts) - def listContent(self): + + def list(self): command = "vb" if self.fullpath else "lb" - p = self.call_unrar(command, "-v", self.file, password=self.password) + + p = self.call_cmd(command, "-v", self.file, password=self.password) out, err = p.communicate() - if "Cannot open" in err: - raise ArchiveError("Cannot open file") + if err.strip(): + self.m.logError(err) + if "Cannot open" in err: + return list() - if err.strip(): #: only log error at this point - self.m.logError(err.strip()) + if p.returncode: + self.m.logError("Process terminated") + return list() result = set() @@ -186,17 +217,22 @@ class UnRar(AbtractExtractor): f = f.strip() result.add(save_join(self.out, f)) - self.files = result + return list(result) - def call_unrar(self, command, *xargs, **kwargs): + def call_cmd(self, command, *xargs, **kwargs): args = [] + # overwrite flag - args.append("-o+") if self.overwrite else args.append("-o-") + if self.overwrite: + args.append("-o+") + else: + args.append("-o-") + if self.delete: + args.append("-or") - if self.excludefiles: - for word in self.excludefiles.split(';'): - args.append("-x%s" % word) + for word in self.excludefiles: + args.append("-x%s" % word.strip()) # assume yes on all queries args.append("-y") @@ -207,10 +243,11 @@ class UnRar(AbtractExtractor): else: args.append("-p-") + if self.keepbroken: + args.append("-kb") + # NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue call = [self.CMD, command] + args + list(xargs) self.m.logDebug(" ".join(call)) - p = Popen(call, stdout=PIPE, stderr=PIPE) - - return p + return Popen(call, stdout=PIPE, stderr=PIPE) diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index 81c298784..b3d54cba0 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -1,19 +1,23 @@ # -*- coding: utf-8 -*- +from __future__ import with_statement + import sys import zipfile -from module.plugins.internal.AbstractExtractor import AbtractExtractor, WrongPassword, ArchiveError +from module.plugins.internal.AbstractExtractor import AbtractExtractor, PasswordError, ArchiveError, CRCError class UnZip(AbtractExtractor): __name__ = "UnZip" - __version__ = "0.12" + __version__ = "1.00" __description__ = """Zip extractor plugin""" __license__ = "GPLv3" - __authors__ = [("RaNaN", "RaNaN@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com")] + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + EXTENSIONS = ["zip", "zip64"] @classmethod @@ -22,31 +26,61 @@ class UnZip(AbtractExtractor): @classmethod - def getTargets(cls, files_ids): - result = [] + def isArchive(cls, file): + return zipfile.is_zipfile(file) - for file, id in files_ids: - if file.endswith(".zip"): - result.append((file, id)) - return result + def verify(self): + try: + with zipfile.ZipFile(self.file, 'r', allowZip64=True) as z: + z.setpassword(self.password) + badcrc = z.testzip() + except (BadZipfile, LargeZipFile), e: + raise ArchiveError(e) - def extract(self, progress, password=""): + except RuntimeError, e: + if 'encrypted' in e: + raise PasswordError + else: + raise ArchiveError(e) + + else: + if badcrc: + raise CRCError + + if not self.list(): + raise ArchiveError("Empty archive") + + + def list(self): try: - z = zipfile.ZipFile(self.file) - self.files = z.namelist() - z.extractall(self.out, pwd=password) + with zipfile.ZipFile(self.file, 'r', allowZip64=True) as z: + z.setpassword(self.password) + return z.namelist() + except Exception: + return list() + + + def extract(self, progress=lambda x: None): + try: + with zipfile.ZipFile(self.file, 'r', allowZip64=True) as z: + progress(0) + z.extractall(self.out, pwd=self.password) + progress(100) except (BadZipfile, LargeZipFile), e: raise ArchiveError(e) except RuntimeError, e: if e is "Bad password for file": - raise WrongPassword + raise PasswordError else: raise ArchiveError(e) + finally: + self.files = self.list() + def getDeleteFiles(self): return [self.file] -- cgit v1.2.3 From deea9c544157037ad8c4c55d61ea92b3696b117b Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 24 Dec 2014 01:12:17 +0100 Subject: Extractor rewritten (2) --- module/plugins/internal/AbstractExtractor.py | 55 ++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 12 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/AbstractExtractor.py b/module/plugins/internal/AbstractExtractor.py index c8a73c861..310897d4e 100644 --- a/module/plugins/internal/AbstractExtractor.py +++ b/module/plugins/internal/AbstractExtractor.py @@ -8,13 +8,13 @@ class CRCError(Exception): pass -class WrongPassword(Exception): +class PasswordError(Exception): pass class AbtractExtractor: __name__ = "AbtractExtractor" - __version__ = "0.11" + __version__ = "0.12" __description__ = """Abtract extractor plugin""" __license__ = "GPLv3" @@ -22,6 +22,9 @@ class AbtractExtractor: ("Walter Purcaro", "vuolter@gmail.com")] + EXTENSIONS = [] + + @classmethod def checkDeps(cls): """ Check if system statisfy dependencies @@ -30,16 +33,27 @@ class AbtractExtractor: return True + @classmethod + def isArchive(cls, file): + raise NotImplementedError + + @classmethod def getTargets(cls, files_ids): """ Filter suited targets from list of filename id tuple list :param files_ids: List of filepathes :return: List of targets, id tuple list """ - raise NotImplementedError + targets = [] + + for file, id in files_ids: + if cls.isArchive(file): + targets.append((file, id)) + + return targets - def __init__(self, m, file, out, fullpath, overwrite, excludefiles, renice): + def __init__(self, m, file, out, password, fullpath, overwrite, excludefiles, renice, delete, keepbroken): """Initialize extractor for specific file :param m: ExtractArchive Hook plugin @@ -52,10 +66,13 @@ class AbtractExtractor: self.m = m self.file = file self.out = out + self.password = password self.fullpath = fullpath self.overwrite = overwrite self.excludefiles = excludefiles self.renice = renice + self.delete = delete + self.keepbroken = keepbroken self.files = [] #: Store extracted files here @@ -64,36 +81,50 @@ class AbtractExtractor: pass - def checkArchive(self): + def verify(self): """Check if password if needed. Raise ArchiveError if integrity is questionable. - :return: boolean :raises ArchiveError """ - return False + pass - def checkPassword(self, password): + def isPassword(self, password): """ Check if the given password is/might be correct. If it can not be decided at this point return true. :param password: :return: boolean """ - return True + if isinstance(password, basestring): + return True + else: + return False + + + def setPassword(self, password): + if self.isPassword(password): + self.password = password + return True + else: + return False + + + def repair(self): + return False - def extract(self, progress, password=""): + def extract(self, progress=lambda x: None): """Extract the archive. Raise specific errors in case of failure. :param progress: Progress function, call this to update status - :param password password to use - :raises WrongPassword + :raises PasswordError :raises CRCError :raises ArchiveError :return: """ + self.setPassword(password) raise NotImplementedError -- cgit v1.2.3 From f71c1ef70a199e42e8a519364d9924e138ffd37c Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 24 Dec 2014 15:48:08 +0100 Subject: [ExtractArchive] Remove empty directory --- module/plugins/internal/UnRar.py | 2 +- module/plugins/internal/UnZip.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index 5633b31f7..b70bf3257 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -8,7 +8,7 @@ from os.path import basename, dirname, join from string import digits from subprocess import Popen, PIPE -from module.plugins.internal.AbstractExtractor import AbtractExtractor, PasswordError, ArchiveError, CRCError +from module.plugins.internal.AbstractExtractor import AbtractExtractor, ArchiveError, CRCError, PasswordError from module.utils import save_join, decode diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index b3d54cba0..875a0ec09 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -5,7 +5,7 @@ from __future__ import with_statement import sys import zipfile -from module.plugins.internal.AbstractExtractor import AbtractExtractor, PasswordError, ArchiveError, CRCError +from module.plugins.internal.AbstractExtractor import AbtractExtractor, ArchiveError, CRCError, PasswordError class UnZip(AbtractExtractor): -- cgit v1.2.3 From 4c63928557398891c30d3e2b7c962a07b3483315 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 26 Dec 2014 04:18:41 +0100 Subject: Rename AbstractExtractor to Extractor --- module/plugins/internal/AbstractExtractor.py | 141 --------------------------- module/plugins/internal/Extractor.py | 140 ++++++++++++++++++++++++++ module/plugins/internal/UnRar.py | 6 +- module/plugins/internal/UnZip.py | 6 +- 4 files changed, 146 insertions(+), 147 deletions(-) delete mode 100644 module/plugins/internal/AbstractExtractor.py create mode 100644 module/plugins/internal/Extractor.py (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/AbstractExtractor.py b/module/plugins/internal/AbstractExtractor.py deleted file mode 100644 index 310897d4e..000000000 --- a/module/plugins/internal/AbstractExtractor.py +++ /dev/null @@ -1,141 +0,0 @@ -# -*- coding: utf-8 -*- - -class ArchiveError(Exception): - pass - - -class CRCError(Exception): - pass - - -class PasswordError(Exception): - pass - - -class AbtractExtractor: - __name__ = "AbtractExtractor" - __version__ = "0.12" - - __description__ = """Abtract extractor plugin""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "ranan@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com")] - - - EXTENSIONS = [] - - - @classmethod - def checkDeps(cls): - """ Check if system statisfy dependencies - :return: boolean - """ - return True - - - @classmethod - def isArchive(cls, file): - raise NotImplementedError - - - @classmethod - def getTargets(cls, files_ids): - """ Filter suited targets from list of filename id tuple list - :param files_ids: List of filepathes - :return: List of targets, id tuple list - """ - targets = [] - - for file, id in files_ids: - if cls.isArchive(file): - targets.append((file, id)) - - return targets - - - def __init__(self, m, file, out, password, fullpath, overwrite, excludefiles, renice, delete, keepbroken): - """Initialize extractor for specific file - - :param m: ExtractArchive Hook plugin - :param file: Absolute filepath - :param out: Absolute path to destination directory - :param fullpath: extract to fullpath - :param overwrite: Overwrite existing archives - :param renice: Renice value - """ - self.m = m - self.file = file - self.out = out - self.password = password - self.fullpath = fullpath - self.overwrite = overwrite - self.excludefiles = excludefiles - self.renice = renice - self.delete = delete - self.keepbroken = keepbroken - self.files = [] #: Store extracted files here - - - def init(self): - """ Initialize additional data structures """ - pass - - - def verify(self): - """Check if password if needed. Raise ArchiveError if integrity is - questionable. - - :raises ArchiveError - """ - pass - - - def isPassword(self, password): - """ Check if the given password is/might be correct. - If it can not be decided at this point return true. - - :param password: - :return: boolean - """ - if isinstance(password, basestring): - return True - else: - return False - - - def setPassword(self, password): - if self.isPassword(password): - self.password = password - return True - else: - return False - - - def repair(self): - return False - - - def extract(self, progress=lambda x: None): - """Extract the archive. Raise specific errors in case of failure. - - :param progress: Progress function, call this to update status - :raises PasswordError - :raises CRCError - :raises ArchiveError - :return: - """ - self.setPassword(password) - raise NotImplementedError - - - def getDeleteFiles(self): - """Return list of files to delete, do *not* delete them here. - - :return: List with paths of files to delete - """ - raise NotImplementedError - - - def getExtractedFiles(self): - """Populate self.files at some point while extracting""" - return self.files diff --git a/module/plugins/internal/Extractor.py b/module/plugins/internal/Extractor.py new file mode 100644 index 000000000..0b2462dac --- /dev/null +++ b/module/plugins/internal/Extractor.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- + +class ArchiveError(Exception): + pass + + +class CRCError(Exception): + pass + + +class PasswordError(Exception): + pass + + +class Extractor: + __name__ = "Extractor" + __version__ = "0.13" + + __description__ = """Base extractor plugin""" + __license__ = "GPLv3" + __authors__ = [("RaNaN", "ranan@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com")] + + + EXTENSIONS = [] + + + @classmethod + def checkDeps(cls): + """ Check if system statisfy dependencies + :return: boolean + """ + return True + + + @classmethod + def isArchive(cls, file): + raise NotImplementedError + + + @classmethod + def getTargets(cls, files_ids): + """ Filter suited targets from list of filename id tuple list + :param files_ids: List of filepathes + :return: List of targets, id tuple list + """ + targets = [] + + for file, id in files_ids: + if cls.isArchive(file): + targets.append((file, id)) + + return targets + + + def __init__(self, m, file, out, password, fullpath, overwrite, excludefiles, renice, delete, keepbroken): + """Initialize extractor for specific file + + :param m: ExtractArchive Hook plugin + :param file: Absolute filepath + :param out: Absolute path to destination directory + :param fullpath: extract to fullpath + :param overwrite: Overwrite existing archives + :param renice: Renice value + """ + self.m = m + self.file = file + self.out = out + self.password = password + self.fullpath = fullpath + self.overwrite = overwrite + self.excludefiles = excludefiles + self.renice = renice + self.delete = delete + self.keepbroken = keepbroken + self.files = [] #: Store extracted files here + + + def init(self): + """ Initialize additional data structures """ + pass + + + def verify(self): + """Check if password if needed. Raise ArchiveError if integrity is + questionable. + + :raises ArchiveError + """ + pass + + + def isPassword(self, password): + """ Check if the given password is/might be correct. + If it can not be decided at this point return true. + + :param password: + :return: boolean + """ + if isinstance(password, basestring): + return True + else: + return False + + + def setPassword(self, password): + if self.isPassword(password): + self.password = password + return True + else: + return False + + + def repair(self): + return False + + + def extract(self, progress=lambda x: None): + """Extract the archive. Raise specific errors in case of failure. + + :param progress: Progress function, call this to update status + :raises PasswordError + :raises CRCError + :raises ArchiveError + :return: + """ + raise NotImplementedError + + + def getDeleteFiles(self): + """Return list of files to delete, do *not* delete them here. + + :return: List with paths of files to delete + """ + raise NotImplementedError + + + def getExtractedFiles(self): + """Populate self.files at some point while extracting""" + return self.files diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index b70bf3257..572fe95b9 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -8,7 +8,7 @@ from os.path import basename, dirname, join from string import digits from subprocess import Popen, PIPE -from module.plugins.internal.AbstractExtractor import AbtractExtractor, ArchiveError, CRCError, PasswordError +from module.plugins.internal.Extractor import Extractor, ArchiveError, CRCError, PasswordError from module.utils import save_join, decode @@ -20,9 +20,9 @@ def renice(pid, value): print "Renice failed" -class UnRar(AbtractExtractor): +class UnRar(Extractor): __name__ = "UnRar" - __version__ = "1.00" + __version__ = "1.01" __description__ = """Rar extractor plugin""" __license__ = "GPLv3" diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index 875a0ec09..5ec56cbdf 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -5,12 +5,12 @@ from __future__ import with_statement import sys import zipfile -from module.plugins.internal.AbstractExtractor import AbtractExtractor, ArchiveError, CRCError, PasswordError +from module.plugins.internal.Extractor import Extractor, ArchiveError, CRCError, PasswordError -class UnZip(AbtractExtractor): +class UnZip(Extractor): __name__ = "UnZip" - __version__ = "1.00" + __version__ = "1.01" __description__ = """Zip extractor plugin""" __license__ = "GPLv3" -- cgit v1.2.3 From f37514e315e076379ab73539ffa36e48671976cc Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 26 Dec 2014 04:19:57 +0100 Subject: [MultiHoster] Improve --- module/plugins/internal/MultiHoster.py | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index e5c28d034..6bfff171b 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -2,13 +2,13 @@ import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies class MultiHoster(SimpleHoster): __name__ = "MultiHoster" __type__ = "hoster" - __version__ = "0.24" + __version__ = "0.25" __pattern__ = r'^unmatchable$' @@ -17,7 +17,7 @@ class MultiHoster(SimpleHoster): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - DIRECT_LINK = True + LOGIN_ACCOUNT = True def setup(self): @@ -25,6 +25,28 @@ class MultiHoster(SimpleHoster): self.multiDL = self.premium + def prepare(self): + self.info = {} + self.link = "" #@TODO: Move to hoster class in 0.4.10 + self.directDL = False #@TODO: Move to hoster class in 0.4.10 + + if self.LOGIN_ACCOUNT and not self.account: + self.fail(_("Required account not found")) + + self.req.setOption("timeout", 120) + + if isinstance(self.COOKIES, list): + set_cookies(self.req.cj, self.COOKIES) + + if self.DIRECT_LINK is None: + self.directDL = self.__pattern__ != r'^unmatchable$' + else: + self.directDL = self.DIRECT_LINK + + self.pyfile.url = replace_patterns(self.pyfile.url, + self.FILE_URL_REPLACEMENTS if hasattr(self, "FILE_URL_REPLACEMENTS") else self.URL_REPLACEMENTS) #@TODO: Remove FILE_URL_REPLACEMENTS check in 0.4.10 + + def process(self, pyfile): self.prepare() @@ -35,7 +57,7 @@ class MultiHoster(SimpleHoster): if not self.link and not self.lastDownload: self.preload() - if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): + if self.premium and not self.CHECK_TRAFFIC or self.checkTrafficLeft(): self.logDebug("Handled as premium download") self.handlePremium() @@ -55,4 +77,4 @@ class MultiHoster(SimpleHoster): if self.premium: raise NotImplementedError else: - self.logError(_("Required account not found")) + self.fail(_("Required premium account not found")) -- cgit v1.2.3 From 6d3b96012ba64343586ba53041650d93493a335c Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 26 Dec 2014 04:23:45 +0100 Subject: [MultiHook] Overwrites account if not premium --- module/plugins/internal/MultiHook.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py index dcf1c3383..caac6c258 100644 --- a/module/plugins/internal/MultiHook.py +++ b/module/plugins/internal/MultiHook.py @@ -9,7 +9,7 @@ from module.utils import remove_chars class MultiHook(Hook): __name__ = "MultiHook" __type__ = "hook" - __version__ = "0.22" + __version__ = "0.23" __description__ = """Hook plugin for MultiHoster""" __license__ = "GPLv3" @@ -130,14 +130,14 @@ class MultiHook(Hook): old_supported = [hoster for hoster in old_supported if hoster not in self.supported] if old_supported: - self.logDebug("UNLOAD", ", ".join(old_supported)) + self.logDebug("Unload: %s" % ", ".join(old_supported)) for hoster in old_supported: self.unloadHoster(hoster) def overridePlugins(self): pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys()) - accountList = [name.lower() for name, data in self.core.accountManager.accounts.iteritems() if data] + accountList = [account.type.lower() for account in self.core.api.getAccounts(False) if account.valid and account.premium] excludedList = [] for hoster in self.getHosterCached(): @@ -159,26 +159,26 @@ class MultiHook(Hook): klass = getattr(module, self.__name__) # inject plugin plugin - self.logDebug("Overwritten Hosters", ", ".join(sorted(self.supported))) + self.logDebug("Overwritten Hosters: %s" % ", ".join(sorted(self.supported))) for hoster in self.supported: hdict = self.core.pluginManager.hosterPlugins[hoster] hdict['new_module'] = module hdict['new_name'] = self.__name__ if excludedList: - self.logInfo(_("The following hosters were not overwritten - account exists"), ", ".join(sorted(excludedList))) + self.logInfo(_("Hosters not overwritten: %s" % ", ".join(sorted(excludedList)))) if self.new_supported: hosters = sorted(self.new_supported) - self.logDebug("New Hosters", ", ".join(hosters)) + self.logDebug("New Hosters: %s" % ", ".join(hosters)) # create new regexp regexp = r'.*(%s).*' % "|".join([x.replace(".", "\.") for x in hosters]) if hasattr(klass, "__pattern__") and isinstance(klass.__pattern__, basestring) and '://' in klass.__pattern__: regexp = r'%s|%s' % (klass.__pattern__, regexp) - self.logDebug("Regexp", regexp) + self.logDebug("Regexp: %s" % regexp) hdict = self.core.pluginManager.hosterPlugins[self.__name__] hdict['pattern'] = regexp -- cgit v1.2.3 From 873f1bc17733148163829e23a456a6e724c486e3 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 26 Dec 2014 04:26:20 +0100 Subject: [SimpleHoster] Improve --- module/plugins/internal/SimpleHoster.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 6726726e1..56c25e0d9 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -160,7 +160,7 @@ def _isDirectLink(self, url, resumable=False): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.79" + __version__ = "0.80" __pattern__ = r'^unmatchable$' @@ -381,7 +381,7 @@ class SimpleHoster(Hoster): if self.html is None: self.fail(_("No html retrieved")) - if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): + if self.premium and not self.CHECK_TRAFFIC or self.checkTrafficLeft(): self.logDebug("Handled as premium download") self.handlePremium() @@ -405,7 +405,11 @@ class SimpleHoster(Hoster): self.retry(10, reason=_("Wrong captcha")) elif not self.lastDownload or not exists(fs_encode(self.lastDownload)): - self.fail(_("No file downloaded")) + errmsg = _("No file downloaded") + if 'error' in self.info: + self.fail(errmsg, self.info['error']) + else: + self.fail(errmsg) else: rules = {'empty file': re.compile(r"^$")} -- cgit v1.2.3 From 136f63dc39603814b215606f888fb2e639021277 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 26 Dec 2014 04:27:41 +0100 Subject: Spare code fixes --- module/plugins/internal/SimpleCrypter.py | 10 +++++----- module/plugins/internal/XFSHoster.py | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py index e0dd10585..6596828b3 100644 --- a/module/plugins/internal/SimpleCrypter.py +++ b/module/plugins/internal/SimpleCrypter.py @@ -12,7 +12,7 @@ from module.utils import fixup class SimpleCrypter(Crypter, SimpleHoster): __name__ = "SimpleCrypter" __type__ = "crypter" - __version__ = "0.33" + __version__ = "0.34" __pattern__ = r'^unmatchable$' __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package'] @@ -82,14 +82,14 @@ class SimpleCrypter(Crypter, SimpleHoster): def prepare(self): - if self.LOGIN_ACCOUNT and not self.account: - self.fail(_("Required account not found")) + self.info = {} + self.links = [] #@TODO: Move to hoster class in 0.4.10 if self.LOGIN_PREMIUM and not self.premium: self.fail(_("Required premium account not found")) - self.info = {} - self.links = [] + if self.LOGIN_ACCOUNT and not self.account: + self.fail(_("Required account not found")) self.req.setOption("timeout", 120) diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index dd2dd2527..7c6ae5725 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -16,7 +16,7 @@ from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.31" + __version__ = "0.32" __pattern__ = r'^unmatchable$' @@ -32,7 +32,7 @@ class XFSHoster(SimpleHoster): TEXT_ENCODING = False COOKIES = [(HOSTER_DOMAIN, "lang", "english")] - CHECK_DIRECT_LINK = None + DIRECT_LINK = None MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy... NAME_PATTERN = r'(Filename[ ]*:[ ]*()?|name="fname"[ ]+value="|<[\w^_]+ class="(file)?name">)\s*(?P.+?)(\s*<|")' @@ -45,7 +45,7 @@ class XFSHoster(SimpleHoster): PREMIUM_ONLY_PATTERN = r'>This file is available for Premium Users only' ERROR_PATTERN = r'(?:class=["\']err["\'].*?>|<[Cc]enter>|>Error|>\(ERROR:)(?:\s*<.+?>\s*)*(.+?)(?:["\']|<|\))' - LEECH_LINK_PATTERN = r'

Download Link

\s*]*>([^<]+)' + LINK_LEECH_PATTERN = r'

Download Link

\s*]*>([^<]+)' LINK_PATTERN = None #: final download url pattern CAPTCHA_PATTERN = r'(https?://[^"\']+?/captchas?/[^"\']+)' @@ -58,7 +58,7 @@ class XFSHoster(SimpleHoster): def setup(self): - self.chunkLimit = 1 + self.chunkLimit = 1 self.resumeDownload = self.multiDL = self.premium @@ -80,7 +80,7 @@ class XFSHoster(SimpleHoster): super(XFSHoster, self).prepare() - if self.CHECK_DIRECT_LINK is None: + if self.DIRECT_LINK is None: self.directDL = bool(self.premium) @@ -189,9 +189,9 @@ class XFSHoster(SimpleHoster): self.fail(stmsg) #get easybytez.com link for uploaded file - m = re.search(self.LEECH_LINK_PATTERN, self.html) + m = re.search(self.LINK_LEECH_PATTERN, self.html) if m is None: - self.error(_("LEECH_LINK_PATTERN not found")) + self.error(_("LINK_LEECH_PATTERN not found")) header = self.load(m.group(1), just_header=True, decode=True) -- cgit v1.2.3 From c7187f2142c6e06be961bb3be45ea3b61ce31651 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 26 Dec 2014 17:24:41 +0100 Subject: [SimpleHoster] getInfo handle direct link error --- module/plugins/internal/MultiHoster.py | 4 ++-- module/plugins/internal/SimpleHoster.py | 23 +++++++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index 6bfff171b..9d218c3b2 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -8,7 +8,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, r class MultiHoster(SimpleHoster): __name__ = "MultiHoster" __type__ = "hoster" - __version__ = "0.25" + __version__ = "0.26" __pattern__ = r'^unmatchable$' @@ -57,7 +57,7 @@ class MultiHoster(SimpleHoster): if not self.link and not self.lastDownload: self.preload() - if self.premium and not self.CHECK_TRAFFIC or self.checkTrafficLeft(): + if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): self.logDebug("Handled as premium download") self.handlePremium() diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 56c25e0d9..89d2e629c 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -160,7 +160,7 @@ def _isDirectLink(self, url, resumable=False): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "0.80" + __version__ = "0.81" __pattern__ = r'^unmatchable$' @@ -233,7 +233,13 @@ class SimpleHoster(Hoster): @classmethod def getInfo(cls, url="", html=""): - info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3, 'url': url} + info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3, 'url': url} + online = False + + try: + info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: pattern groups will be saved here, please save api stuff to info['api'] + except Exception: + pass if not html: try: @@ -242,6 +248,11 @@ class SimpleHoster(Hoster): info['status'] = 1 raise + if _isDirectLink(url): + info['error'] = "direct link" + info['status'] = 2 + raise + try: html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING) @@ -261,8 +272,6 @@ class SimpleHoster(Hoster): except: return info - online = False - if hasattr(cls, "OFFLINE_PATTERN") and re.search(cls.OFFLINE_PATTERN, html): info['status'] = 1 @@ -273,9 +282,7 @@ class SimpleHoster(Hoster): info['status'] = 6 else: - try: - info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: pattern groups will be saved here, please save api stuff to info['api'] - except: + if not 'pattern' in info: info['pattern'] = {} for pattern in ("FILE_INFO_PATTERN", "INFO_PATTERN", @@ -381,7 +388,7 @@ class SimpleHoster(Hoster): if self.html is None: self.fail(_("No html retrieved")) - if self.premium and not self.CHECK_TRAFFIC or self.checkTrafficLeft(): + if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): self.logDebug("Handled as premium download") self.handlePremium() -- cgit v1.2.3 From ff42cec46274b0f2019272424c1a57ec4b413507 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 26 Dec 2014 17:58:54 +0100 Subject: [PremiumTo] Fixup --- module/plugins/internal/MultiHook.py | 1 + 1 file changed, 1 insertion(+) (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py index caac6c258..78de1ed0a 100644 --- a/module/plugins/internal/MultiHook.py +++ b/module/plugins/internal/MultiHook.py @@ -47,6 +47,7 @@ class MultiHook(Hook): """getConfig with default value - sublass may not implements all config options""" try: return self.getConf(option) + except KeyError: return default -- cgit v1.2.3 From 4f287a307dd61afbbf1029065dcd6d1b9c304a15 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 27 Dec 2014 13:39:25 +0100 Subject: New plugin: SimpleDereferer --- module/plugins/internal/SimpleDereferer.py | 96 ++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 module/plugins/internal/SimpleDereferer.py (limited to 'module/plugins/internal') diff --git a/module/plugins/internal/SimpleDereferer.py b/module/plugins/internal/SimpleDereferer.py new file mode 100644 index 000000000..0ad1098f4 --- /dev/null +++ b/module/plugins/internal/SimpleDereferer.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- + +import re + +from urllib import unquote + +from module.plugins.Crypter import Crypter +from module.plugins.internal.SimpleHoster import _isDirectLink, set_cookies + + +class SimpleDereferer(Crypter): + __name__ = "SimpleDereferer" + __type__ = "crypter" + __version__ = "0.01" + + __pattern__ = r'^unmatchable$' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """Simple dereferer plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + """ + Following patterns should be defined by each crypter: + + LINK_PATTERN: Regex to catch the redirect url in group(1) + example: LINK_PATTERN = r'