summaryrefslogtreecommitdiffstats
path: root/module/plugins/internal
diff options
context:
space:
mode:
authorGravatar Walter Purcaro <vuolter@gmail.com> 2015-01-08 22:58:32 +0100
committerGravatar Walter Purcaro <vuolter@gmail.com> 2015-01-08 22:58:32 +0100
commitdf143e902d00903f16cf32174948f636bda56e4c (patch)
tree7aab8bc13369c22b1d9486fdee44f96b7b393391 /module/plugins/internal
parentMerge pull request #1013 from smoozed/stable (diff)
downloadpyload-df143e902d00903f16cf32174948f636bda56e4c.tar.xz
"New Year" Update: internal plugins
Diffstat (limited to 'module/plugins/internal')
-rw-r--r--module/plugins/internal/CaptchaService.py49
-rw-r--r--module/plugins/internal/MultiHook.py158
-rw-r--r--module/plugins/internal/MultiHoster.py15
-rw-r--r--module/plugins/internal/SimpleCrypter.py4
-rw-r--r--module/plugins/internal/SimpleDereferer.py6
-rw-r--r--module/plugins/internal/SimpleHoster.py55
-rw-r--r--module/plugins/internal/XFSAccount.py8
-rw-r--r--module/plugins/internal/XFSCrypter.py1
-rw-r--r--module/plugins/internal/XFSHoster.py26
9 files changed, 197 insertions, 125 deletions
diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py
index 965799e8e..b429fd6e0 100644
--- a/module/plugins/internal/CaptchaService.py
+++ b/module/plugins/internal/CaptchaService.py
@@ -2,6 +2,7 @@
import re
+from base64 import urlsafe_b64encode
from random import random
from module.common.json_layer import json_loads
@@ -54,14 +55,14 @@ class CaptchaService:
class ReCaptcha(CaptchaService):
__name__ = "ReCaptcha"
- __version__ = "0.08"
+ __version__ = "0.09"
__description__ = """ReCaptcha captcha service plugin"""
__license__ = "GPLv3"
__authors__ = [("pyLoad Team", "admin@pyload.org")]
- KEY_PATTERN = r'recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=([\w-]+)'
+ KEY_PATTERN = r'(?:class="g-recaptcha"\s+data-sitekey="|recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=)([\w-]+)'
KEY_AJAX_PATTERN = r'Recaptcha\.create\s*\(\s*["\']([\w-]+)'
@@ -84,7 +85,7 @@ class ReCaptcha(CaptchaService):
return None
- def challenge(self, key=None):
+ def challenge(self, key=None, userverify=False):
if not key:
if self.detect_key():
key = self.key
@@ -97,14 +98,30 @@ class ReCaptcha(CaptchaService):
try:
challenge = re.search("challenge : '(.+?)',", html).group(1)
server = re.search("server : '(.+?)',", html).group(1)
- except:
+
+ except AttributeError:
errmsg = _("ReCaptcha challenge pattern not found")
self.plugin.fail(errmsg)
- raise ValueError(errmsg)
+ raise AttributeError(errmsg)
self.plugin.logDebug("ReCaptcha challenge: %s" % challenge)
- return challenge, self.result(server, challenge)
+ response = challenge, self.result(server, challenge)
+
+ return self.userverify(*response) if userverify else response
+
+
+ def userverify(self, challenge, result):
+ response = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify",
+ post={'c' : challenge,
+ 'response': urlsafe_b64encode('{"response":"%s"}' % result)})
+ try:
+ return re.search(r'"uvresp","(.+?)"', response).group(1)
+
+ except AttributeError:
+ errmsg = _("ReCaptcha userverify response not found")
+ self.plugin.fail(errmsg)
+ raise AttributeError(errmsg)
def result(self, server, challenge):
@@ -167,10 +184,11 @@ class AdsCaptcha(CaptchaService):
try:
challenge = re.search("challenge: '(.+?)',", html).group(1)
server = re.search("server: '(.+?)',", html).group(1)
- except:
+
+ except AttributeError:
errmsg = _("AdsCaptcha challenge pattern not found")
self.plugin.fail(errmsg)
- raise ValueError(errmsg)
+ raise AttributeError(errmsg)
self.plugin.logDebug("AdsCaptcha challenge: %s" % challenge)
@@ -214,10 +232,11 @@ class SolveMedia(CaptchaService):
challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">',
html).group(1)
server = "http://api.solvemedia.com/papi/media"
- except:
+
+ except AttributeError:
errmsg = _("SolveMedia challenge pattern not found")
self.plugin.fail(errmsg)
- raise ValueError(errmsg)
+ raise AttributeError(errmsg)
self.plugin.logDebug("SolveMedia challenge: %s" % challenge)
@@ -286,10 +305,11 @@ class AdYouLike(CaptchaService):
'callback': callback})
try:
challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1))
- except:
+
+ except AttributeError:
errmsg = _("AdYouLike challenge pattern not found")
self.plugin.fail(errmsg)
- raise ValueError(errmsg)
+ raise AttributeError(errmsg)
self.plugin.logDebug("AdYouLike challenge: %s" % challenge)
@@ -316,10 +336,11 @@ class AdYouLike(CaptchaService):
try:
instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual']
result = re.search(u'«(.+?)»', instructions_visual).group(1).strip()
- except:
+
+ except AttributeError:
errmsg = _("AdYouLike result not found")
self.plugin.fail(errmsg)
- raise ValueError(errmsg)
+ raise AttributeError(errmsg)
result = {'_ayl_captcha_engine' : "adyoulike",
'_ayl_env' : server['all']['env'],
diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py
index ea9f32673..202868175 100644
--- a/module/plugins/internal/MultiHook.py
+++ b/module/plugins/internal/MultiHook.py
@@ -9,12 +9,15 @@ from module.utils import remove_chars
class MultiHook(Hook):
__name__ = "MultiHook"
__type__ = "hook"
- __version__ = "0.29"
+ __version__ = "0.30"
- __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed", "bool" , "Revert to standard download if download fails", False),
- ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )]
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
__description__ = """Hook plugin for multi hoster/crypter"""
__license__ = "GPLv3"
@@ -22,45 +25,68 @@ class MultiHook(Hook):
("Walter Purcaro", "vuolter@gmail.com")]
- MIN_INTERVAL = 12 * 60 * 60 #: reload plugins every 12h
+ MIN_INTERVAL = 1 * 60 * 60
- PLUGIN_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" )]
+ DOMAIN_REPLACEMENTS = [(r'\d+.+' , "_\0" ),
+ (r'bayfiles\.net' , "bayfiles.com" ),
+ (r'cloudnator\.com' , "shragle.com" ),
+ (r'dfiles\.eu' , "depositfiles.com"),
+ (r'easy-share\.com' , "crocko.com" ),
+ (r'freakshare\.net' , "freakshare.com" ),
+ (r'hellshare\.com' , "hellshare.cz" ),
+ (r'ifile\.it' , "filecloud.io" ),
+ (r'nowdownload\.\w+', "nowdownload.sx" ),
+ (r'nowvideo\.\w+' , "nowvideo.sx" ),
+ (r'putlocker\.com' , "firedrive.com" ),
+ (r'share-?rapid\.cz', "multishare.cz" ),
+ (r'ul\.to' , "uploaded.to" ),
+ (r'uploaded\.net' , "uploaded.to" ),
+ (r'uploadhero\.co' , "uploadhero.com" ),
+ (r'zshares\.net' , "zshare.net" )]
def setup(self):
- self.account = None
- self.type = self.core.pluginManager.findPlugin(self.__name__)[1] or "hoster"
self.plugins = []
self.supported = []
self.new_supported = []
+ self.account = None
+ self.pluginclass = None
+ self.pluginmodule = None
+ self.pluginname = None
+ self.plugintype = None
- def coreReady(self):
- self.account = self.core.accountManager.getAccountPlugin(self.__name__)
+ self._initPlugin()
+
+
+ def _initPlugin(self):
+ plugin, type = self.core.pluginManager.findPlugin(self.__name__)
+
+ if not plugin:
+ self.logWarning("Hook plugin will be deactivated due missing plugin reference")
+ self.setConfig('activated', False)
+ else:
+ self.pluginname = self.__name__
+ self.plugintype = type
+ self.pluginmodule = self.core.pluginManager.loadModule(type, self.__name__)
+ self.pluginclass = getattr(self.pluginmodule, self.__name__)
+
+
+ def _loadAccount(self):
+ self.account = self.core.accountManager.getAccountPlugin(self.pluginname)
if self.account and not self.account.canUse():
self.account = None
- if not self.account:
- self.logWarning("MultiHook will be deactivated due missing account reference")
+ if not self.account and hasattr(self.pluginclass, "LOGIN_ACCOUNT") and not self.pluginclass.LOGIN_ACCOUNT:
+ self.logWarning("Hook plugin will be deactivated due missing account reference")
self.setConfig('activated', False)
+ def coreReady(self):
+ self._loadAccount()
+
+
def getURL(self, *args, **kwargs): #@TODO: Remove in 0.4.10
""" see HTTPRequest for argument list """
h = pyreq.getHTTPRequest(timeout=120)
@@ -81,19 +107,19 @@ class MultiHook(Hook):
return default
- def pluginCached(self):
+ def pluginsCached(self):
if not self.plugins:
try:
- pluginset = self.pluginSet(self.getHosters() if self.type == "hoster" else self.getCrypters())
+ pluginset = self._pluginSet(self.getHosters() if self.plugintype == "hoster" else self.getCrypters())
except Exception, e:
self.logError(e)
return []
try:
- configmode = self.getConfig("mode", 'all')
+ configmode = self.getConfig("pluginmode", 'all')
if configmode in ("listed", "unlisted"):
pluginlist = self.getConfig("pluginlist", '').replace('|', ',').replace(';', ',').split(',')
- configset = self.pluginSet(pluginlist)
+ configset = self._pluginSet(pluginlist)
if configmode == "listed":
pluginset &= configset
@@ -108,13 +134,14 @@ class MultiHook(Hook):
return self.plugins
- def pluginSet(self, plugins):
+ def _pluginSet(self, plugins):
plugins = set((str(x).strip().lower() for x in plugins))
- for rep in self.PLUGIN_REPLACEMENTS:
- if rep[0] in plugins:
- plugins.remove(rep[0])
- plugins.add(rep[1])
+ for rf, rt in self.DOMAIN_REPLACEMENTS:
+ regex = re.compile(rf)
+ for p in filter(lambda x: regex.match(x), plugins):
+ plugins.remove(p)
+ plugins.add(re.sub(rf, rt, p))
plugins.discard('')
@@ -139,9 +166,7 @@ class MultiHook(Hook):
def periodical(self):
"""reload plugin list periodically"""
- self.interval = max(self.getConfig("interval", 0), self.MIN_INTERVAL)
-
- self.logInfo(_("Reloading supported %s list") % self.type)
+ self.logInfo(_("Reloading supported %s list") % self.plugintype)
old_supported = self.supported
@@ -158,18 +183,24 @@ class MultiHook(Hook):
for plugin in old_supported:
self.unloadPlugin(plugin)
+ if self.getConfig("reload", True):
+ self.interval = max(self.getConfig("reloadinterval", 12), self.MIN_INTERVAL)
+ else:
+ self.core.scheduler.removeJob(self.cb)
+ self.cb = None
+
def overridePlugins(self):
excludedList = []
- if self.type == "hoster":
+ if self.plugintype == "hoster":
pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys())
accountList = [account.type.lower() for account in self.core.api.getAccounts(False) if account.valid and account.premium]
else:
pluginMap = {}
accountList = [name[::-1].replace("Folder"[::-1], "", 1).lower()[::-1] for name in self.core.pluginManager.crypterPlugins.iterkeys()]
- for plugin in self.pluginCached():
+ for plugin in self.pluginsCached():
name = remove_chars(plugin, "-.")
if name in accountList:
@@ -181,42 +212,39 @@ class MultiHook(Hook):
self.new_supported.append(plugin)
if not self.supported and not self.new_supported:
- self.logError(_("No %s loaded") % self.type)
+ self.logError(_("No %s loaded") % self.plugintype)
return
- module = self.core.pluginManager.getPlugin(self.__name__)
- klass = getattr(module, self.__name__)
-
# inject plugin plugin
- self.logDebug("Overwritten %ss: %s" % (self.type, ", ".join(sorted(self.supported))))
+ self.logDebug("Overwritten %ss: %s" % (self.plugintype, ", ".join(sorted(self.supported))))
for plugin in self.supported:
- hdict = self.core.pluginManager.plugins[self.type][plugin]
- hdict['new_module'] = module
- hdict['new_name'] = self.__name__
+ hdict = self.core.pluginManager.plugins[self.plugintype][plugin]
+ hdict['new_module'] = self.pluginmodule
+ hdict['new_name'] = self.pluginname
if excludedList:
- self.logInfo(_("%ss not overwritten: %s") % (self.type.capitalize(), ", ".join(sorted(excludedList))))
+ self.logInfo(_("%ss not overwritten: %s") % (self.plugintype.capitalize(), ", ".join(sorted(excludedList))))
if self.new_supported:
plugins = sorted(self.new_supported)
- self.logDebug("New %ss: %s" % (self.type, ", ".join(plugins)))
+ self.logDebug("New %ss: %s" % (self.plugintype, ", ".join(plugins)))
# create new regexp
regexp = r'.*(%s).*' % "|".join([x.replace(".", "\.") for x in plugins])
- if hasattr(klass, "__pattern__") and isinstance(klass.__pattern__, basestring) and '://' in klass.__pattern__:
- regexp = r'%s|%s' % (klass.__pattern__, regexp)
+ if hasattr(self.pluginclass, "__pattern__") and isinstance(self.pluginclass.__pattern__, basestring) and '://' in self.pluginclass.__pattern__:
+ regexp = r'%s|%s' % (self.pluginclass.__pattern__, regexp)
self.logDebug("Regexp: %s" % regexp)
- hdict = self.core.pluginManager.plugins[self.type][self.__name__]
+ hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname]
hdict['pattern'] = regexp
hdict['re'] = re.compile(regexp)
def unloadPlugin(self, plugin):
- hdict = self.core.pluginManager.plugins[self.type][plugin]
+ hdict = self.core.pluginManager.plugins[self.plugintype][plugin]
if "module" in hdict:
del hdict['module']
@@ -231,18 +259,24 @@ class MultiHook(Hook):
self.unloadPlugin(plugin)
# reset pattern
- klass = getattr(self.core.pluginManager.getPlugin(self.__name__), self.__name__)
- hdict = self.core.pluginManager.plugins[self.type][self.__name__]
+ hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname]
- hdict['pattern'] = getattr(klass, "__pattern__", r'^unmatchable$')
+ hdict['pattern'] = getattr(self.pluginclass, "__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("revertfailed", True):
- hdict = self.core.pluginManager.plugins[self.type][pyfile.pluginname]
- if "new_name" in hdict and hdict['new_name'] == self.__name__:
+ if pyfile.status != 8 or not self.getConfig("revertfailed", True):
+ return
+
+ hdict = self.core.pluginManager.plugins[self.plugintype][pyfile.pluginname]
+ if "new_name" in hdict and hdict['new_name'] == self.pluginname:
+ if pyfile.error == "MultiHook":
self.logDebug("Unload MultiHook", pyfile.pluginname, hdict)
self.unloadPlugin(pyfile.pluginname)
pyfile.setStatus("queued")
+ else:
+ retries = max(self.getConfig("retry", 10), 0)
+ wait_time = max(self.getConfig("retryinterval", 1), 0)
+ pyfile.plugin.retry(retries, wait_time, "MultiHook")
diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py
index 60320399a..ae06eaf4b 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.29"
+ __version__ = "0.30"
__pattern__ = r'^unmatchable$'
@@ -17,12 +17,14 @@ class MultiHoster(SimpleHoster):
__authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+ CHECK_TRAFFIC = True
LOGIN_ACCOUNT = True
def setup(self):
- self.chunkLimit = 1
- self.multiDL = self.premium
+ self.chunkLimit = 1
+ self.multiDL = bool(self.account)
+ self.resumeDownload = self.premium
def prepare(self):
@@ -76,7 +78,8 @@ class MultiHoster(SimpleHoster):
if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
self.logDebug("Handled as premium download")
self.handlePremium()
- else:
+
+ elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
self.logDebug("Handled as free download")
self.handleFree()
@@ -84,11 +87,11 @@ class MultiHoster(SimpleHoster):
self.checkFile()
- def handlePremium(self, pyfile=None):
+ def handlePremium(self, pyfile):
return self.handleFree(pyfile)
- def handleFree(self, pyfile=None):
+ def handleFree(self, pyfile):
if self.premium:
raise NotImplementedError
else:
diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py
index bfc473801..e16e45405 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.37"
+ __version__ = "0.38"
__pattern__ = r'^unmatchable$'
__config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package']
@@ -82,6 +82,8 @@ class SimpleCrypter(Crypter, SimpleHoster):
def prepare(self):
+ self.pyfile.error = "" #@TODO: Remove in 0.4.10
+
self.info = {}
self.links = [] #@TODO: Move to hoster class in 0.4.10
diff --git a/module/plugins/internal/SimpleDereferer.py b/module/plugins/internal/SimpleDereferer.py
index 04d63658e..53b80f827 100644
--- a/module/plugins/internal/SimpleDereferer.py
+++ b/module/plugins/internal/SimpleDereferer.py
@@ -5,13 +5,13 @@ import re
from urllib import unquote
from module.plugins.Crypter import Crypter
-from module.plugins.internal.SimpleHoster import _isDirectLink, set_cookies
+from module.plugins.internal.SimpleHoster import directLink, set_cookies
class SimpleDereferer(Crypter):
__name__ = "SimpleDereferer"
__type__ = "crypter"
- __version__ = "0.02"
+ __version__ = "0.03"
__pattern__ = r'^unmatchable$'
__config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
@@ -45,7 +45,7 @@ class SimpleDereferer(Crypter):
def decrypt(self, pyfile):
- link = _isDirectLink(pyfile.url)
+ link = directLink(self, pyfile.url)
if not link:
try:
diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py
index c87a6160f..991dc6240 100644
--- a/module/plugins/internal/SimpleHoster.py
+++ b/module/plugins/internal/SimpleHoster.py
@@ -10,6 +10,7 @@ from urlparse import urljoin, urlparse
from module.PyFile import statusMap as _statusMap
from module.network.CookieJar import CookieJar
+from module.network.HTTPRequest import BadHeader
from module.network.RequestFactory import getURL
from module.plugins.Hoster import Hoster
from module.plugins.Plugin import Fail
@@ -126,7 +127,7 @@ def timestamp():
#@TODO: Move to hoster class in 0.4.10
-def _isDirectLink(self, url, resumable=False):
+def directLink(self, url, resumable=False):
link = ""
for i in xrange(5 if resumable else 1):
@@ -182,7 +183,7 @@ def secondsToMidnight(gmt=0):
class SimpleHoster(Hoster):
__name__ = "SimpleHoster"
__type__ = "hoster"
- __version__ = "0.90"
+ __version__ = "0.91"
__pattern__ = r'^unmatchable$'
@@ -244,18 +245,32 @@ class SimpleHoster(Hoster):
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)
+ LOGIN_ACCOUNT = False #: Set to True to require account login
+
+ directLink = directLink #@TODO: Remove in 0.4.10
@classmethod
- def parseInfos(cls, urls):
+ def parseInfos(cls, urls): #@TODO: Built-in in 0.4.10 core, then remove from plugins
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)
@classmethod
+ def apiInfo(cls, url="", get={}, post={}):
+ url = unquote(url)
+ return {'name' : (urlparse(url).path.split('/')[-1]
+ or urlparse(url).query.split('&', 1)[0].split('=', 1)[1]
+ or _("Unknown")),
+ 'size' : 0,
+ 'status': 3,
+ 'url' : url}
+
+
+ @classmethod
def getInfo(cls, url="", html=""):
- info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3, 'url': url}
+ info = cls.apiInfo(url)
online = False
try:
@@ -268,7 +283,7 @@ class SimpleHoster(Hoster):
info['error'] = "missing url"
info['status'] = 1
- else:
+ elif info['status'] is 3:
try:
html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING)
@@ -343,11 +358,16 @@ class SimpleHoster(Hoster):
def prepare(self):
+ self.pyfile.error = "" #@TODO: Remove in 0.4.10
+
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
self.multihost = 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):
@@ -399,7 +419,7 @@ class SimpleHoster(Hoster):
self.logDebug("Handled as premium download")
self.handlePremium()
- else:
+ elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
self.logDebug("Handled as free download")
self.handleFree()
@@ -420,15 +440,12 @@ class SimpleHoster(Hoster):
elif not self.lastDownload or not exists(fs_encode(self.lastDownload)):
self.lastDownload = ""
-
- errmsg = _("No file downloaded")
- if 'error' in self.info:
- self.fail(errmsg, self.info['error'])
- else:
- self.fail(errmsg)
+ self.fail(errmsg, self.pyfile.error or _("No file downloaded"))
else:
- rules = {'empty file': re.compile(r"^$")}
+ rules = {'empty file': re.compile(r'\A\Z'),
+ 'html file' : re.compile(r'\A\s*<!DOCTYPE html'),
+ 'html error': re.compile(r'\A\s*(<.+>)?\d{3}[^\d]*')}
if hasattr(self, 'ERROR_PATTERN'):
rules['error'] = re.compile(self.ERROR_PATTERN)
@@ -529,7 +546,7 @@ class SimpleHoster(Hoster):
def handleDirect(self, pyfile):
- link = _isDirectLink(self, pyfile.url, self.resumeDownload)
+ link = self.directLink(pyfile.url, self.resumeDownload)
if link:
self.logInfo(_("Direct download link detected"))
@@ -543,9 +560,9 @@ class SimpleHoster(Hoster):
pass
- def handleFree(self, pyfile=None):
+ def handleFree(self, pyfile):
if not hasattr(self, 'LINK_FREE_PATTERN'):
- self.fail(_("Free download not implemented"))
+ self.logError(_("Free download not implemented"))
try:
m = re.search(self.LINK_FREE_PATTERN, self.html)
@@ -558,9 +575,11 @@ class SimpleHoster(Hoster):
self.fail(e)
- def handlePremium(self, pyfile=None):
+ def handlePremium(self, pyfile):
if not hasattr(self, 'LINK_PREMIUM_PATTERN'):
- self.fail(_("Premium download not implemented"))
+ self.logError(_("Premium download not implemented"))
+ self.logDebug("Handled as free download")
+ self.handleFree()
try:
m = re.search(self.LINK_PREMIUM_PATTERN, self.html)
diff --git a/module/plugins/internal/XFSAccount.py b/module/plugins/internal/XFSAccount.py
index 2784ecd0b..263d78ff8 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.33"
+ __version__ = "0.34"
__description__ = """XFileSharing account plugin"""
__license__ = "GPLv3"
@@ -35,7 +35,7 @@ class XFSAccount(Account):
LEECH_TRAFFIC_PATTERN = r'Leech Traffic left:<b>.*?(?P<S>[\d.,]+|[Uu]nlimited)\s*(?:(?P<U>[\w^_]+)\s*)?</b>'
LEECH_TRAFFIC_UNIT = "MB" #: used only if no group <U> was found
- LOGIN_FAIL_PATTERN = r'>\s*(Incorrect Login or Password|Error<)'
+ LOGIN_FAIL_PATTERN = r'Incorrect Login or Password|account was banned|Error<'
def __init__(self, manager, accounts): #@TODO: remove in 0.4.10
@@ -76,10 +76,10 @@ class XFSAccount(Account):
self.logDebug("Valid until: %s" % validuntil)
if validuntil > mktime(gmtime()):
- premium = True
+ premium = True
trafficleft = -1
else:
- premium = False
+ premium = False
validuntil = None #: registered account type (not premium)
else:
self.logDebug("VALID_UNTIL_PATTERN not found")
diff --git a/module/plugins/internal/XFSCrypter.py b/module/plugins/internal/XFSCrypter.py
index 4b57dab90..3cb837aac 100644
--- a/module/plugins/internal/XFSCrypter.py
+++ b/module/plugins/internal/XFSCrypter.py
@@ -16,7 +16,6 @@ class XFSCrypter(SimpleCrypter):
HOSTER_DOMAIN = None
- HOSTER_NAME = None
URL_REPLACEMENTS = [(r'&?per_page=\d+', ""), (r'[?/&]+$', ""), (r'(.+/[^?]+)$', r'\1?'), (r'$', r'&per_page=10000')]
diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py
index e15504d16..873df8989 100644
--- a/module/plugins/internal/XFSHoster.py
+++ b/module/plugins/internal/XFSHoster.py
@@ -15,7 +15,7 @@ from module.utils import html_unescape
class XFSHoster(SimpleHoster):
__name__ = "XFSHoster"
__type__ = "hoster"
- __version__ = "0.34"
+ __version__ = "0.35"
__pattern__ = r'^unmatchable$'
@@ -27,7 +27,6 @@ class XFSHoster(SimpleHoster):
HOSTER_DOMAIN = None
- HOSTER_NAME = None
TEXT_ENCODING = False
COOKIES = [(HOSTER_DOMAIN, "lang", "english")]
@@ -66,9 +65,6 @@ class XFSHoster(SimpleHoster):
if not self.HOSTER_DOMAIN:
self.fail(_("Missing HOSTER_DOMAIN"))
- if not self.HOSTER_NAME:
- self.HOSTER_NAME = "".join([str.capitalize() for str in self.HOSTER_DOMAIN.split('.')])
-
if not self.LINK_PATTERN:
pattern = r'(https?://(www\.)?([^/]*?%s|\d+\.\d+\.\d+\.\d+)(\:\d+)?(/d/|(/files)?/\d+/\w+/).+?)["\'<]'
self.LINK_PATTERN = pattern % self.HOSTER_DOMAIN.replace('.', '\.')
@@ -82,10 +78,8 @@ class XFSHoster(SimpleHoster):
self.directDL = bool(self.premium)
- def handleFree(self, pyfile=None):
- link = self.getDownloadLink()
-
- if link:
+ def downloadLink(self, link):
+ if link and isinstance(link, basestring):
if self.captcha:
self.correctCaptcha()
@@ -101,11 +95,7 @@ class XFSHoster(SimpleHoster):
self.fail(_("Download link not found"))
- def handlePremium(self, pyfile=None):
- return self.handleFree(pyfile)
-
-
- def getDownloadLink(self):
+ def handleFree(self, pyfile):
for i in xrange(1, 6):
self.logDebug("Getting download link: #%d" % i)
@@ -119,7 +109,7 @@ class XFSHoster(SimpleHoster):
self.req.http.c.setopt(FOLLOWLOCATION, 0)
- self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True)
+ self.html = self.load(pyfile.url, post=data, ref=True, decode=True)
self.req.http.c.setopt(FOLLOWLOCATION, 1)
@@ -136,7 +126,11 @@ class XFSHoster(SimpleHoster):
self.errmsg = None
- return m.group(1).strip() #@TODO: Remove .strip() in 0.4.10
+ self.link = m.group(1).strip() #@TODO: Remove .strip() in 0.4.10
+
+
+ def handlePremium(self, pyfile):
+ return self.handleFree(pyfile)
def handleMulti(self, pyfile):