summaryrefslogtreecommitdiffstats
path: root/module/plugins
diff options
context:
space:
mode:
authorGravatar Walter Purcaro <vuolter@gmail.com> 2014-12-02 00:08:42 +0100
committerGravatar Walter Purcaro <vuolter@gmail.com> 2014-12-02 00:08:42 +0100
commit2a8d0af88b07e62eeb316a8dfbb7cd8d7dbfdcac (patch)
tree4324ec7c224724156ee9897e8689135f85e2e804 /module/plugins
parentMerge pull request #920 from chris-19/stable (diff)
parent[SimpleHoster] Force _isDirectLink to old style (diff)
downloadpyload-2a8d0af88b07e62eeb316a8dfbb7cd8d7dbfdcac.tar.xz
Merge branch 'stable-next' into stable
Diffstat (limited to 'module/plugins')
-rw-r--r--module/plugins/accounts/EasybytezCom.py8
-rw-r--r--module/plugins/accounts/SafesharingEu.py11
-rwxr-xr-xmodule/plugins/hooks/Captcha9kw.py2
-rw-r--r--module/plugins/hooks/Checksum.py9
-rw-r--r--module/plugins/hooks/UpdateManager.py15
-rw-r--r--module/plugins/hoster/BasePlugin.py33
-rw-r--r--module/plugins/hoster/DataHu.py7
-rw-r--r--module/plugins/hoster/DateiTo.py4
-rw-r--r--module/plugins/hoster/FastshareCz.py1
-rw-r--r--module/plugins/hoster/FilecloudIo.py8
-rw-r--r--module/plugins/hoster/FilepostCom.py11
-rw-r--r--module/plugins/hoster/FilerNet.py1
-rw-r--r--module/plugins/hoster/Keep2shareCc.py117
-rw-r--r--module/plugins/hoster/KingfilesNet.py6
-rw-r--r--module/plugins/hoster/LetitbitNet.py5
-rw-r--r--module/plugins/hoster/LuckyShareNet.py7
-rw-r--r--module/plugins/hoster/NowVideoAt.py4
-rw-r--r--module/plugins/hoster/OneFichierCom.py4
-rw-r--r--module/plugins/hoster/PromptfileCom.py5
-rw-r--r--module/plugins/hoster/SafesharingEu.py25
-rw-r--r--module/plugins/hoster/ShareonlineBiz.py184
-rw-r--r--module/plugins/hoster/TurbobitNet.py6
-rw-r--r--module/plugins/hoster/UploadingCom.py8
-rw-r--r--module/plugins/hoster/WebshareCz.py7
-rw-r--r--module/plugins/hoster/ZippyshareCom.py15
-rw-r--r--module/plugins/internal/DeadCrypter.py5
-rw-r--r--module/plugins/internal/DeadHoster.py5
-rw-r--r--module/plugins/internal/SimpleHoster.py126
-rw-r--r--module/plugins/internal/XFSAccount.py8
-rw-r--r--module/plugins/internal/XFSHoster.py20
30 files changed, 342 insertions, 325 deletions
diff --git a/module/plugins/accounts/EasybytezCom.py b/module/plugins/accounts/EasybytezCom.py
index 0afd93d3b..93d3e2c19 100644
--- a/module/plugins/accounts/EasybytezCom.py
+++ b/module/plugins/accounts/EasybytezCom.py
@@ -8,7 +8,7 @@ from module.plugins.internal.XFSAccount import XFSAccount
class EasybytezCom(XFSAccount):
__name__ = "EasybytezCom"
__type__ = "account"
- __version__ = "0.11"
+ __version__ = "0.12"
__description__ = """EasyBytez.com account plugin"""
__license__ = "GPLv3"
@@ -17,9 +17,3 @@ class EasybytezCom(XFSAccount):
HOSTER_DOMAIN = "easybytez.com"
-
-
- def loadAccountInfo(self, *args, **kwargs):
- info = super(EasybytezCom, self).loadAccountInfo(*args, **kwargs)
- info['leechtraffic'] = 26214400
- return info
diff --git a/module/plugins/accounts/SafesharingEu.py b/module/plugins/accounts/SafesharingEu.py
index a2b964cba..2e58d33b3 100644
--- a/module/plugins/accounts/SafesharingEu.py
+++ b/module/plugins/accounts/SafesharingEu.py
@@ -4,16 +4,13 @@ from module.plugins.internal.XFSAccount import XFSAccount
class SafesharingEu(XFSAccount):
- __name__ = "SafesharingEu"
- __type__ = "account"
+ __name__ = "SafesharingEu"
+ __type__ = "account"
__version__ = "0.02"
__description__ = """Safesharing.eu account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("guidobelix", "guidobelix@hotmail.it")]
+ __license__ = "GPLv3"
+ __authors__ = [("guidobelix", "guidobelix@hotmail.it")]
HOSTER_DOMAIN = "safesharing.eu"
-
- VALID_UNTIL_PATTERN = r'> Premium.[Aa]ccount expire:(.+?)</div>'
- TRAFFIC_LEFT_PATTERN = r'> Traffic available today:\s*?(?P<S>[\d.,]+)\s*?(?:(?P<U>[\w^_]+)\s*)?</div>'
diff --git a/module/plugins/hooks/Captcha9kw.py b/module/plugins/hooks/Captcha9kw.py
index 38b39b2af..ead8aec9a 100755
--- a/module/plugins/hooks/Captcha9kw.py
+++ b/module/plugins/hooks/Captcha9kw.py
@@ -56,7 +56,7 @@ class Captcha9kw(Hook):
if res.isdigit():
self.logInfo(_("%s credits left") % res)
- credits = self.info["credits"] = int(res)
+ credits = self.info['credits'] = int(res)
return credits
else:
self.logError(res)
diff --git a/module/plugins/hooks/Checksum.py b/module/plugins/hooks/Checksum.py
index b746fce5f..eeda2d849 100644
--- a/module/plugins/hooks/Checksum.py
+++ b/module/plugins/hooks/Checksum.py
@@ -81,10 +81,15 @@ class Checksum(Hook):
a) if known, the exact filesize in bytes (e.g. "size": 123456789)
b) hexadecimal hash string with algorithm name as key (e.g. "md5": "d76505d0869f9f928a17d42d66326307")
"""
- if hasattr(pyfile.plugin, "check_data") and (isinstance(pyfile.plugin.check_data, dict)):
+ if hasattr(pyfile.plugin, "check_data") and isinstance(pyfile.plugin.check_data, dict):
data = pyfile.plugin.check_data.copy()
- elif hasattr(pyfile.plugin, "api_data") and (isinstance(pyfile.plugin.api_data, dict)):
+
+ elif hasattr(pyfile.plugin, "api_data") and isinstance(pyfile.plugin.api_data, dict):
data = pyfile.plugin.api_data.copy()
+
+ # elif hasattr(pyfile.plugin, "info") and isinstance(pyfile.plugin.info, dict):
+ # data = pyfile.plugin.info.copy()
+
else:
return
diff --git a/module/plugins/hooks/UpdateManager.py b/module/plugins/hooks/UpdateManager.py
index 3fda0b5e8..9c26cf5d9 100644
--- a/module/plugins/hooks/UpdateManager.py
+++ b/module/plugins/hooks/UpdateManager.py
@@ -14,13 +14,14 @@ from module.utils import save_join
class UpdateManager(Hook):
__name__ = "UpdateManager"
__type__ = "hook"
- __version__ = "0.39"
+ __version__ = "0.40"
- __config__ = [("activated", "bool", "Activated", True),
- ("mode", "pyLoad + plugins;plugins only", "Check updates for", "pyLoad + plugins"),
- ("interval", "int", "Check interval in hours", 8),
- ("reloadplugins", "bool", "Monitor plugins for code changes (debug mode only)", True),
- ("nodebugupdate", "bool", "Don't check for updates in debug mode", True)]
+ __config__ = [("activated" , "bool" , "Activated" , True ),
+ ("mode" , "pyLoad + plugins;plugins only", "Check updates for" , "pyLoad + plugins"),
+ ("interval" , "int" , "Check interval in hours" , 8 ),
+ ("autorestart" , "bool" , "Automatically restart pyLoad when required" , True ),
+ ("reloadplugins", "bool" , "Monitor plugins for code changes in debug mode", True ),
+ ("nodebugupdate", "bool" , "Don't check for updates in debug mode" , True )]
__description__ = """ Check for updates """
__license__ = "GPLv3"
@@ -123,7 +124,7 @@ class UpdateManager(Hook):
status = self.update(onlyplugin=self.getConfig("mode") == "plugins only")
- if status == 2:
+ if status is 2 and self.getConfig("autorestart"):
self.core.api.restart()
else:
self.updating = False
diff --git a/module/plugins/hoster/BasePlugin.py b/module/plugins/hoster/BasePlugin.py
index 01a234d3b..0b1888e3b 100644
--- a/module/plugins/hoster/BasePlugin.py
+++ b/module/plugins/hoster/BasePlugin.py
@@ -3,7 +3,7 @@
import re
from urllib import unquote
-from urlparse import urlparse
+from urlparse import urljoin, urlparse
from module.network.HTTPRequest import BadHeader
from module.plugins.internal.SimpleHoster import create_getInfo
@@ -13,7 +13,7 @@ from module.plugins.Hoster import Hoster
class BasePlugin(Hoster):
__name__ = "BasePlugin"
__type__ = "hoster"
- __version__ = "0.24"
+ __version__ = "0.25"
__pattern__ = r'^unmatchable$'
@@ -25,7 +25,7 @@ class BasePlugin(Hoster):
@classmethod
def getInfo(cls, url="", html=""): #@TODO: Move to hoster class in 0.4.10
- return {'name': urlparse(url).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3 if url else 1, 'url': url or ""}
+ return {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3 if url else 1, 'url': unquote(url) or ""}
def setup(self):
@@ -50,7 +50,7 @@ class BasePlugin(Hoster):
self.offline()
elif e.code in (401, 403):
- self.logDebug("Auth required")
+ self.logDebug("Auth required", "Received HTTP status code: %d" % e.code)
account = self.core.accountManager.getAccountPlugin('Http')
servers = [x['login'] for x in account.getAllAccounts()]
@@ -65,16 +65,16 @@ class BasePlugin(Hoster):
self.req.addAuth(pwd.strip())
break
else:
- self.fail(_("Authorization required (username:password)"))
+ self.fail(_("Authorization required"))
else:
self.fail(e)
else:
break
else:
- self.fail(_("No file downloaded")) #@TODO: Move to hoster class (check if self.lastDownload) in 0.4.10
+ self.fail(_("No file downloaded")) #@TODO: Move to hoster class in 0.4.10
- # if self.checkDownload({'empty': re.compile(r"^$")}) is "empty":
- # self.fail(_("Empty file"))
+ if self.checkDownload({'empty': re.compile(r"^$")}) is "empty": #@TODO: Move to hoster in 0.4.10
+ self.fail(_("Empty file"))
def downloadFile(self, pyfile):
@@ -85,7 +85,8 @@ class BasePlugin(Hoster):
if 'location' not in header or not header['location']:
if 'code' in header and header['code'] not in (200, 201, 203, 206):
- self.fail(_("File not found"), _("HTTP status code: %d") % header['code'])
+ self.logDebug("Received HTTP status code: %d" % header['code'])
+ self.fail(_("File not found"))
else:
break
@@ -93,17 +94,13 @@ class BasePlugin(Hoster):
self.logDebug("Redirect #%d to: %s" % (i, location))
- base = re.match(r'https?://[^/]+', url).group(0)
-
- if location.startswith("http"):
+ if urlparse(location).scheme:
url = location
-
- elif location.startswith("/"):
- url = base + unquote(location)
-
else:
- url = "%s/%s" % (base, unquote(location))
+ p = urlparse(url)
+ base = "%s://%s" % (p.scheme, p.netloc)
+ url = urljoin(base, location)
else:
self.fail(_("Too many redirects"))
- self.download(url, disposition=True)
+ self.download(unquote(url), disposition=True)
diff --git a/module/plugins/hoster/DataHu.py b/module/plugins/hoster/DataHu.py
index fd6a01135..74d631e7b 100644
--- a/module/plugins/hoster/DataHu.py
+++ b/module/plugins/hoster/DataHu.py
@@ -33,13 +33,10 @@ class DataHu(SimpleHoster):
def handleFree(self):
m = re.search(self.LINK_PATTERN, self.html)
- if m:
- url = m.group(1)
- self.logDebug("Direct link: " + url)
- else:
+ if m is None:
self.error(_("LINK_PATTERN not found"))
- self.download(url, disposition=True)
+ self.download(m.group(1), disposition=True)
getInfo = create_getInfo(DataHu)
diff --git a/module/plugins/hoster/DateiTo.py b/module/plugins/hoster/DateiTo.py
index 9d51b5036..683c6b75d 100644
--- a/module/plugins/hoster/DateiTo.py
+++ b/module/plugins/hoster/DateiTo.py
@@ -9,7 +9,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class DateiTo(SimpleHoster):
__name__ = "DateiTo"
__type__ = "hoster"
- __version__ = "0.04"
+ __version__ = "0.05"
__pattern__ = r'http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html'
@@ -29,7 +29,7 @@ class DateiTo(SimpleHoster):
def handleFree(self):
url = 'http://datei.to/ajax/download.php'
- data = {'P': 'I', 'ID': self.info['ID']}
+ data = {'P': 'I', 'ID': self.info['pattern']['ID']}
recaptcha = ReCaptcha(self)
for _i in xrange(10):
diff --git a/module/plugins/hoster/FastshareCz.py b/module/plugins/hoster/FastshareCz.py
index 1467a0909..14931f681 100644
--- a/module/plugins/hoster/FastshareCz.py
+++ b/module/plugins/hoster/FastshareCz.py
@@ -75,7 +75,6 @@ class FastshareCz(SimpleHoster):
else:
self.error(_("PREMIUM_URL_PATTERN not found"))
- self.logDebug("PREMIUM URL: " + url)
self.download(url, disposition=True)
check = self.checkDownload({"credit": re.compile(self.CREDIT_PATTERN)})
diff --git a/module/plugins/hoster/FilecloudIo.py b/module/plugins/hoster/FilecloudIo.py
index 819a7faf3..85ea3dae4 100644
--- a/module/plugins/hoster/FilecloudIo.py
+++ b/module/plugins/hoster/FilecloudIo.py
@@ -10,7 +10,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class FilecloudIo(SimpleHoster):
__name__ = "FilecloudIo"
__type__ = "hoster"
- __version__ = "0.04"
+ __version__ = "0.05"
__pattern__ = r'http://(?:www\.)?(?:filecloud\.io|ifile\.it|mihd\.net)/(?P<ID>\w+).*'
@@ -39,7 +39,7 @@ class FilecloudIo(SimpleHoster):
def handleFree(self):
- data = {"ukey": self.info['ID']}
+ data = {"ukey": self.info['pattern']['ID']}
m = re.search(self.AB1_PATTERN, self.html)
if m is None:
@@ -94,7 +94,7 @@ class FilecloudIo(SimpleHoster):
if res['dl']:
self.html = self.load('http://filecloud.io/download.html')
- m = re.search(self.LINK_PATTERN % self.info['ID'], self.html)
+ m = re.search(self.LINK_PATTERN % self.info['pattern']['ID'], self.html)
if m is None:
self.error(_("LINK_PATTERN not found"))
@@ -109,7 +109,7 @@ class FilecloudIo(SimpleHoster):
def handlePremium(self):
akey = self.account.getAccountData(self.user)['akey']
- ukey = self.info['ID']
+ ukey = self.info['pattern']['ID']
self.logDebug("Akey: %s | Ukey: %s" % (akey, ukey))
rep = self.load("http://api.filecloud.io/api-fetch_download_url.api",
post={"akey": akey, "ukey": ukey})
diff --git a/module/plugins/hoster/FilepostCom.py b/module/plugins/hoster/FilepostCom.py
index 314ad449c..db5ea20d3 100644
--- a/module/plugins/hoster/FilepostCom.py
+++ b/module/plugins/hoster/FilepostCom.py
@@ -12,9 +12,9 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class FilepostCom(SimpleHoster):
__name__ = "FilepostCom"
__type__ = "hoster"
- __version__ = "0.29"
+ __version__ = "0.30"
- __pattern__ = r'https?://(?:www\.)?(?:filepost\.com/files|fp\.io)/([^/]+).*'
+ __pattern__ = r'https?://(?:www\.)?(?:filepost\.com/files|fp\.io)/(?P<ID>[^/]+)'
__description__ = """Filepost.com hoster plugin"""
__license__ = "GPLv3"
@@ -30,9 +30,6 @@ class FilepostCom(SimpleHoster):
def handleFree(self):
- # Find token and captcha key
- file_id = re.match(self.__pattern__, self.pyfile.url).group(1)
-
m = re.search(self.FLP_TOKEN_PATTERN, self.html)
if m is None:
self.error(_("Token"))
@@ -45,13 +42,13 @@ class FilepostCom(SimpleHoster):
# Get wait time
get_dict = {'SID': self.req.cj.getCookie('SID'), 'JsHttpRequest': str(int(time() * 10000)) + '-xml'}
- post_dict = {'action': 'set_download', 'token': flp_token, 'code': file_id}
+ post_dict = {'action': 'set_download', 'token': flp_token, 'code': self.info['pattern']['ID']}
wait_time = int(self.getJsonResponse(get_dict, post_dict, 'wait_time'))
if wait_time > 0:
self.wait(wait_time)
- post_dict = {"token": flp_token, "code": file_id, "file_pass": ''}
+ post_dict = {"token": flp_token, "code": self.info['pattern']['ID'], "file_pass": ''}
if 'var is_pass_exists = true;' in self.html:
# Solve password
diff --git a/module/plugins/hoster/FilerNet.py b/module/plugins/hoster/FilerNet.py
index c91729730..3bfafc675 100644
--- a/module/plugins/hoster/FilerNet.py
+++ b/module/plugins/hoster/FilerNet.py
@@ -92,7 +92,6 @@ class FilerNet(SimpleHoster):
self.error(_("LINK_PATTERN not found"))
dl = 'http://filer.net' + m.group(1)
- self.logDebug("Direct link: " + dl)
self.download(dl, disposition=True)
diff --git a/module/plugins/hoster/Keep2shareCc.py b/module/plugins/hoster/Keep2shareCc.py
index fd8a5524d..7ca29701a 100644
--- a/module/plugins/hoster/Keep2shareCc.py
+++ b/module/plugins/hoster/Keep2shareCc.py
@@ -2,16 +2,16 @@
import re
-from urlparse import urlparse, urljoin
+from urlparse import urljoin, urlparse
from module.plugins.internal.CaptchaService import ReCaptcha
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.plugins.internal.SimpleHoster import _isDirectLink, SimpleHoster, create_getInfo
class Keep2shareCc(SimpleHoster):
__name__ = "Keep2shareCc"
__type__ = "hoster"
- __version__ = "0.15"
+ __version__ = "0.16"
__pattern__ = r'https?://(?:www\.)?(keep2share|k2s|keep2s)\.cc/file/(?P<ID>\w+)'
@@ -21,75 +21,98 @@ class Keep2shareCc(SimpleHoster):
("Walter Purcaro", "vuolter@gmail.com")]
+ URL_REPLACEMENTS = [(__pattern__ + ".*", "http://k2s.cc/file/\g<ID>")]
+
+ CONTENT_DISPOSITION = True
+
NAME_PATTERN = r'File: <span>(?P<N>.+)</span>'
SIZE_PATTERN = r'Size: (?P<S>[^<]+)</div>'
- OFFLINE_PATTERN = r'File not found or deleted|Sorry, this file is blocked or deleted|Error 404'
- LINK_PATTERN = r'To download this file with slow speed, use <a href="([^"]+)">this link</a>'
+ OFFLINE_PATTERN = r'File not found or deleted|Sorry, this file is blocked or deleted|Error 404'
+ TEMP_OFFLINE_PATTERN = r'Downloading blocked due to'
+
+ LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'"([^"]+url.html?file=.+?)"|window\.location\.href = \'(.+?)\';'
+
CAPTCHA_PATTERN = r'src="(/file/captcha\.html.+?)"'
- WAIT_PATTERN = r'Please wait ([\d:]+) to download this file'
- MULTIDL_ERROR = r'Free account does not allow to download more than one file at the same time'
+ WAIT_PATTERN = r'Please wait ([\d:]+) to download this file'
+ TEMP_ERROR_PATTERN = r'>\s*(Download count files exceed|Traffic limit exceed|Free account does not allow to download more than one file at the same time)'
+ ERROR_PATTERN = r'>\s*(Free user can\'t download large files|You no can access to this file|This download available only for premium users|This is private file)'
- def handleFree(self):
- self.sanitize_url()
- self.html = self.load(self.pyfile.url)
- self.fid = re.search(r'<input type="hidden" name="slow_id" value="([^"]+)">', self.html).group(1)
+ def checkErrors(self):
+ m = re.search(self.TEMP_ERROR_PATTERN, self.html)
+ if m:
+ self.info['error'] = m.group(1)
+ self.wantReconnect = True
+ self.retry(wait_time=30 * 60, reason=m.group(0))
+
+ m = re.search(self.ERROR_PATTERN, self.html)
+ if m:
+ e = self.info['error'] = m.group(1)
+ self.error(e)
+
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ self.logDebug("Hoster told us to wait for %s" % m.group(1))
+
+ # string to time convert courtesy of https://stackoverflow.com/questions/10663720
+ ftr = [3600, 60, 1]
+ wait_time = sum([a * b for a, b in zip(ftr, map(int, m.group(1).split(':')))])
+
+ self.wantReconnect = True
+ self.retry(wait_time=wait_time, reason="Please wait to download this file")
+
+ self.info.pop('error', None)
+
+
+ def handleFree(self):
+ self.fid = re.search(r'<input type="hidden" name="slow_id" value="([^"]+)">', self.html).group(1)
self.html = self.load(self.pyfile.url, post={'yt0': '', 'slow_id': self.fid})
- if ">Downloading is not possible" in self.html:
- self.fail("Free user can't download large files")
+ self.checkErrors()
- m = re.search(r"function download\(\){.*window\.location\.href = '([^']+)';", self.html, re.S)
- if m: # Direct mode
- self.startDownload(m.group(1))
- else:
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+
+ if m is None:
self.handleCaptcha()
self.wait(30)
self.html = self.load(self.pyfile.url, post={'uniqueId': self.fid, 'free': 1})
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- self.logDebug("Hoster told us to wait for %s" % m.group(1))
- # string to time convert courtesy of https://stackoverflow.com/questions/10663720
- ftr = [3600, 60, 1]
- wait_time = sum([a * b for a, b in zip(ftr, map(int, m.group(1).split(':')))])
- self.wait(wait_time, True)
- self.retry()
-
- m = re.search(self.MULTIDL_ERROR, self.html)
- if m:
- # if someone is already downloading on our line, wait 30min and retry
- self.logDebug("Already downloading, waiting for 30 minutes")
- self.wait(30 * 60, True)
- self.retry()
+ self.checkErrors()
- m = re.search(self.LINK_PATTERN, self.html)
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
if m is None:
- self.error(_("LINK_PATTERN not found"))
- self.startDownload(m.group(1))
+ self.error(_("LINK_FREE_PATTERN not found"))
+
+ self.link = self._getDownloadLink(m.group(1))
+
+
+ def handlePremium(self):
+ super(Keep2shareCc, self).handlePremium()
+ if self.link:
+ self.link = self._getDownloadLink(self.link)
def handleCaptcha(self):
recaptcha = ReCaptcha(self)
for _i in xrange(5):
- post_data = {'free': 1,
+ post_data = {'free' : 1,
'freeDownloadRequest': 1,
- 'uniqueId': self.fid,
- 'yt0': ''}
+ 'uniqueId' : self.fid,
+ 'yt0' : ''}
m = re.search(self.CAPTCHA_PATTERN, self.html)
if m:
- captcha_url = urljoin(self.base_url, m.group(1))
+ captcha_url = urljoin(self.base, m.group(1))
post_data['CaptchaForm[code]'] = self.decryptCaptcha(captcha_url)
else:
challenge, response = recaptcha.challenge()
post_data.update({'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field': response})
+ 'recaptcha_response_field' : response})
self.html = self.load(self.pyfile.url, post=post_data)
@@ -102,17 +125,11 @@ class Keep2shareCc(SimpleHoster):
self.fail(_("All captcha attempts failed"))
- def startDownload(self, url):
- d = urljoin(self.base_url, url)
- self.download(d, disposition=True)
-
-
- def sanitize_url(self):
- header = self.load(self.pyfile.url, just_header=True)
- if 'location' in header:
- self.pyfile.url = header['location']
+ def _getDownloadLink(self, url):
p = urlparse(self.pyfile.url)
- self.base_url = "%s://%s" % (p.scheme, p.hostname)
+ base = "%s://%s" % (p.scheme, p.netloc)
+ link = _isDirectLink(self, url, self.premium)
+ return urljoin(base, link) if link else ""
getInfo = create_getInfo(Keep2shareCc)
diff --git a/module/plugins/hoster/KingfilesNet.py b/module/plugins/hoster/KingfilesNet.py
index ce34da38f..202ab4a77 100644
--- a/module/plugins/hoster/KingfilesNet.py
+++ b/module/plugins/hoster/KingfilesNet.py
@@ -9,7 +9,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class KingfilesNet(SimpleHoster):
__name__ = "KingfilesNet"
__type__ = "hoster"
- __version__ = "0.04"
+ __version__ = "0.05"
__pattern__ = r'http://(?:www\.)?kingfiles\.net/(?P<ID>\w{12})'
@@ -38,7 +38,7 @@ class KingfilesNet(SimpleHoster):
# Click the free user button
post_data = {'op': "download1",
'usr_login': "",
- 'id': self.info['ID'],
+ 'id': self.info['pattern']['ID'],
'fname': self.pyfile.name,
'referer': "",
'method_free': "+"}
@@ -57,7 +57,7 @@ class KingfilesNet(SimpleHoster):
self.logDebug("rand = ", rand)
post_data = {'op': "download2",
- 'id': self.info['ID'],
+ 'id': self.info['pattern']['ID'],
'rand': rand,
'referer': self.pyfile.url,
'method_free': "+",
diff --git a/module/plugins/hoster/LetitbitNet.py b/module/plugins/hoster/LetitbitNet.py
index a1a812de4..ed8d4a39d 100644
--- a/module/plugins/hoster/LetitbitNet.py
+++ b/module/plugins/hoster/LetitbitNet.py
@@ -139,7 +139,4 @@ class LetitbitNet(SimpleHoster):
if api_rep['status'] == 'FAIL':
self.fail(api_rep['data'])
- direct_link = api_rep['data'][0][0]
- self.logDebug("Direct Link: " + direct_link)
-
- self.download(direct_link, disposition=True)
+ self.download(api_rep['data'][0][0], disposition=True)
diff --git a/module/plugins/hoster/LuckyShareNet.py b/module/plugins/hoster/LuckyShareNet.py
index aeab46d3d..2c33b57e7 100644
--- a/module/plugins/hoster/LuckyShareNet.py
+++ b/module/plugins/hoster/LuckyShareNet.py
@@ -11,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class LuckyShareNet(SimpleHoster):
__name__ = "LuckyShareNet"
__type__ = "hoster"
- __version__ = "0.03"
+ __version__ = "0.04"
__pattern__ = r'https?://(?:www\.)?luckyshare\.net/(?P<ID>\d{10,})'
@@ -42,9 +42,7 @@ class LuckyShareNet(SimpleHoster):
# TODO: There should be a filesize limit for free downloads
# TODO: Some files could not be downloaded in free mode
def handleFree(self):
- file_id = re.match(self.__pattern__, self.pyfile.url).group('ID')
- self.logDebug("File ID: " + file_id)
- rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + file_id, decode=True)
+ rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + self.info['pattern']['ID'], decode=True)
self.logDebug("JSON: " + rep)
json = self.parseJson(rep)
@@ -69,7 +67,6 @@ class LuckyShareNet(SimpleHoster):
if not json['link']:
self.fail(_("No Download url retrieved/all captcha attempts failed"))
- self.logDebug("Direct URL: " + json['link'])
self.download(json['link'])
diff --git a/module/plugins/hoster/NowVideoAt.py b/module/plugins/hoster/NowVideoAt.py
index c0b49c6f4..3d9b706d3 100644
--- a/module/plugins/hoster/NowVideoAt.py
+++ b/module/plugins/hoster/NowVideoAt.py
@@ -8,7 +8,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class NowVideoAt(SimpleHoster):
__name__ = "NowVideoAt"
__type__ = "hoster"
- __version__ = "0.06"
+ __version__ = "0.07"
__pattern__ = r'http://(?:www\.)?nowvideo\.(at|ch|co|eu|sx)/(video|mobile/#/videos)/(?P<ID>\w+)'
@@ -32,7 +32,7 @@ class NowVideoAt(SimpleHoster):
def handleFree(self):
- self.html = self.load("http://www.nowvideo.at/mobile/video.php", get={'id': self.info['ID']})
+ self.html = self.load("http://www.nowvideo.at/mobile/video.php", get={'id': self.info['pattern']['ID']})
m = re.search(self.LINK_FREE_PATTERN, self.html)
if m is None:
diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py
index 7847a11e9..977d45b6f 100644
--- a/module/plugins/hoster/OneFichierCom.py
+++ b/module/plugins/hoster/OneFichierCom.py
@@ -8,7 +8,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class OneFichierCom(SimpleHoster):
__name__ = "OneFichierCom"
__type__ = "hoster"
- __version__ = "0.73"
+ __version__ = "0.74"
__pattern__ = r'https?://(?:www\.)?(?:(?P<ID1>\w+)\.)?(?P<HOST>1fichier\.com|alterupload\.com|cjoint\.net|d(es)?fichiers\.com|dl4free\.com|megadl\.fr|mesfichiers\.org|piecejointe\.net|pjointe\.com|tenvoi\.com)(?:/\?(?P<ID2>\w+))?'
@@ -46,7 +46,7 @@ class OneFichierCom(SimpleHoster):
self.wait(wait_time, reconnect)
self.retry(reason="You have to wait been each free download")
- id = self.info['ID1'] or self.info['ID2']
+ id = self.info['pattern']['ID1'] or self.info['pattern']['ID2']
url, inputs = self.parseHtmlForm('action="https://1fichier.com/\?%s' % id)
if not url:
diff --git a/module/plugins/hoster/PromptfileCom.py b/module/plugins/hoster/PromptfileCom.py
index 22fea09ea..af38c4e15 100644
--- a/module/plugins/hoster/PromptfileCom.py
+++ b/module/plugins/hoster/PromptfileCom.py
@@ -38,9 +38,8 @@ class PromptfileCom(SimpleHoster):
m = re.search(self.LINK_PATTERN, self.html)
if m is None:
self.error(_("LINK_PATTERN not found"))
- direct = m.group(1)
- self.logDebug("Found direct link: " + direct)
- self.download(direct, disposition=True)
+
+ self.download(m.group(1), disposition=True)
getInfo = create_getInfo(PromptfileCom)
diff --git a/module/plugins/hoster/SafesharingEu.py b/module/plugins/hoster/SafesharingEu.py
index 92a0ff932..f0936b9e8 100644
--- a/module/plugins/hoster/SafesharingEu.py
+++ b/module/plugins/hoster/SafesharingEu.py
@@ -4,31 +4,20 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo
class SafesharingEu(XFSHoster):
- __name__ = "SafesharingEu"
- __type__ = "hoster"
- __version__ = "0.04"
+ __name__ = "SafesharingEu"
+ __type__ = "hoster"
+ __version__ = "0.05"
- __pattern__ = r'https?://(?:\w+\.)?safesharing.eu/\w+'
+ __pattern__ = r'https?://(?:www\.)?safesharing\.eu/\w{12}'
__description__ = """Safesharing.eu hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
- HOSTER_DOMAIN = "safesharing.eu"
-
- FILE_NAME_PATTERN = r'Filename:</b></td><td nowrap>(?P<N>.*)</td></tr>'
- FILE_SIZE_PATTERN = r'Size:</b></td><td>(?P<S>.*) (?P<U>[kKmMbB]*) <small>'
-
- FILE_ID_PATTERN = r'<input type="hidden" name="id" value="(.*)">'
- OFFLINE_PATTERN = r'<b>File Not Found</b>'
- TEMP_OFFLINE_PATTERN = r'This server is in maintenance mode'
+ HOSTER_DOMAIN = "safesharing.eu"
WAIT_PATTERN = r'You have to wait (\d+) minutes'
- COUNTDOWN_PATTERN = r'<br><span id="countdown_str">Wait <span id=".*">(\d+)</span> seconds</span>'
-
- RECAPTCHA_KEY_PATTERN = r'<script type="text/javascript" src="http://www.google.com/recaptcha/api/challenge\?k=(.*)"></script>'
- RANDOM_STRING_PATTERN = r'<input type="hidden" name="rand" value="(.*)">'
ERROR_PATTERN = r'(?:<div class="alert alert-danger">)(.+?)(?:</div>)'
diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py
index 78a27558b..91fc989c9 100644
--- a/module/plugins/hoster/ShareonlineBiz.py
+++ b/module/plugins/hoster/ShareonlineBiz.py
@@ -3,43 +3,18 @@
import re
from time import time
+from urllib import unquote
+from urlparse import urlparse
from module.network.RequestFactory import getURL
-from module.plugins.Hoster import Hoster
-from module.plugins.Plugin import chunks
from module.plugins.internal.CaptchaService import ReCaptcha
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-def getInfo(urls):
- api_url_base = "http://api.share-online.biz/linkcheck.php"
-
- urls = [url.replace("https://", "http://") for url in urls]
-
- for chunk in chunks(urls, 90):
- api_param_file = {"links": "\n".join(x.replace("http://www.share-online.biz/dl/", "").rstrip("/") for x in
- chunk)} # api only supports old style links
- html = getURL(api_url_base, post=api_param_file, decode=True)
- result = []
- for i, res in enumerate(html.split("\n")):
- if not res:
- continue
- fields = res.split(";")
-
- if fields[1] == "OK":
- status = 2
- elif fields[1] in ("DELETED", "NOT FOUND"):
- status = 1
- else:
- status = 3
-
- result.append((fields[2], int(fields[3]), status, chunk[i]))
- yield result
-
-
-class ShareonlineBiz(Hoster):
+class ShareonlineBiz(SimpleHoster):
__name__ = "ShareonlineBiz"
__type__ = "hoster"
- __version__ = "0.41"
+ __version__ = "0.42"
__pattern__ = r'https?://(?:www\.)?(share-online\.biz|egoshare\.com)/(download\.php\?id=|dl/)(?P<ID>\w+)'
@@ -51,110 +26,118 @@ class ShareonlineBiz(Hoster):
("Walter Purcaro", "vuolter@gmail.com")]
- ERROR_INFO_PATTERN = r'<p class="b">Information:</p>\s*<div>\s*<strong>(.*?)</strong>'
+ URL_REPLACEMENTS = [(__pattern__ + ".*", "http://www.share-online.biz/dl/\g<ID>")]
+ ERROR_INFO_PATTERN = r'<p class="b">Information:</p>\s*<div>\s*<strong>(.*?)</strong>'
- def setup(self):
- self.file_id = re.match(self.__pattern__, self.pyfile.url).group("ID")
- self.pyfile.url = "http://www.share-online.biz/dl/" + self.file_id
- self.resumeDownload = self.premium
- self.multiDL = False
+ @classmethod
+ def getInfo(cls, url="", html=""):
+ info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3 if url else 1, 'url': url}
- self.check_data = None
+ if url:
+ info.update(re.match(cls.__pattern__, url).groupdict())
+ api_url = "http://api.share-online.biz/linkcheck.php?md5=1"
+ html = getURL(api_url, cookies=False, post={"links": self.info['pattern']['ID']}, decode=True)
+ field = html.split(";")
- def process(self, pyfile):
- if self.premium:
- self.handlePremium()
- else:
- self.handleFree()
+ if field[1] is "OK":
+ info['fileid'] = field[0]
+ info['status'] = 2
+ info['filename'] = field[2]
+ info['size'] = field[3] #: in bytes
+ info['md5'] = field[4].strip().lower().replace("\n\n", "") #: md5
- if self.api_data:
- self.check_data = {"size": int(self.api_data['size']), "md5": self.api_data['md5']}
+ elif field[1] in ("DELETED", "NOT FOUND"):
+ info['status'] = 1
+ return info
- def loadAPIData(self):
- api_url_base = "http://api.share-online.biz/linkcheck.php?md5=1"
- api_param_file = {"links": self.file_id} #: api only supports old style links
- html = self.load(api_url_base, cookies=False, post=api_param_file, decode=True)
-
- fields = html.split(";")
- self.api_data = {"fileid": fields[0],
- "status": fields[1]}
- if not self.api_data['status'] == "OK":
- self.offline()
- else:
- self.api_data['filename'] = fields[2]
- self.api_data['size'] = fields[3] #: in bytes
- self.api_data['md5'] = fields[4].strip().lower().replace("\n\n", "") #: md5
+ def setup(self):
+ self.resumeDownload = self.premium
+ self.multiDL = False
- def handleFree(self):
- self.loadAPIData()
- self.pyfile.name = self.api_data['filename']
- self.pyfile.size = int(self.api_data['size'])
-
- self.html = self.load(self.pyfile.url, cookies=True) #: refer, stuff
- self.setWait(3)
- self.wait()
-
- self.html = self.load("%s/free/" % self.pyfile.url, post={"dl_free": "1", "choice": "free"}, decode=True)
- self.checkErrors()
-
- m = re.search(r'var wait=(\d+);', self.html)
+ def handleCaptcha(self):
recaptcha = ReCaptcha(self)
+
for _i in xrange(5):
- challenge, response = recaptcha.challenge("6LdatrsSAAAAAHZrB70txiV5p-8Iv8BtVxlTtjKX")
+ challenge, response = recaptcha.challenge()
+
+ m = re.search(r'var wait=(\d+);', self.html)
self.setWait(int(m.group(1)) if m else 30)
+
res = self.load("%s/free/captcha/%d" % (self.pyfile.url, int(time() * 1000)),
- post={'dl_free': '1',
+ post={'dl_free' : "1",
'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field': response})
-
+ 'recaptcha_response_field' : response})
if not res == '0':
self.correctCaptcha()
- break
+ return res
else:
self.invalidCaptcha()
else:
self.invalidCaptcha()
self.fail(_("No valid captcha solution received"))
+
+ def handleFree(self):
+ self.html = self.load(self.pyfile.url, cookies=True) #: refer, stuff
+
+ self.wait(3)
+
+ self.html = self.load("%s/free/" % self.pyfile.url, post={"dl_free": "1", "choice": "free"}, decode=True)
+
+ self.checkErrors()
+
+ res = self.handleCaptcha()
+
download_url = res.decode("base64")
+
if not download_url.startswith("http://"):
self.error(_("Wrong download url"))
self.wait()
+
self.download(download_url)
+
+ def checkFile(self):
# check download
check = self.checkDownload({
- "cookie": re.compile(r'<div id="dl_failure"'),
- "fail": re.compile(r"<title>Share-Online")
+ 'empty' : re.compile(r"^$"),
+ 'cookie': re.compile(r'<div id="dl_failure"'),
+ 'fail' : re.compile(r"<title>Share-Online")
})
- if check == "cookie":
+
+ if check == "empty":
+ self.fail(_("Empty file"))
+
+ elif check == "cookie":
self.invalidCaptcha()
- self.retry(5, 60, "Cookie failure")
+ self.retry(5, 60, _("Cookie failure"))
+
elif check == "fail":
self.invalidCaptcha()
- self.retry(5, 5 * 60, "Download failed")
- else:
- self.correctCaptcha()
+ self.retry(5, 5 * 60, _("Download failed"))
def handlePremium(self): #: should be working better loading (account) api internally
self.account.getAccountInfo(self.user, True)
+
html = self.load("http://api.share-online.biz/account.php",
{"username": self.user, "password": self.account.accounts[self.user]['password'],
- "act": "download", "lid": self.file_id})
+ "act": "download", "lid": self.info['fileid']})
self.api_data = dlinfo = {}
+
for line in html.splitlines():
key, value = line.split(": ")
dlinfo[key.lower()] = value
self.logDebug(dlinfo)
+
if not dlinfo['status'] == "online":
self.offline()
else:
@@ -162,6 +145,7 @@ class ShareonlineBiz(Hoster):
self.pyfile.size = int(dlinfo['size'])
dlLink = dlinfo['url']
+
if dlLink == "server_under_maintenance":
self.tempOffline()
else:
@@ -174,23 +158,29 @@ class ShareonlineBiz(Hoster):
if m is None:
return
- err = m.group(1)
+ errmsg = m.group(1).lower()
+
try:
- self.logError(err, re.search(self.ERROR_INFO_PATTERN, self.html).group(1))
+ self.logError(errmsg, re.search(self.ERROR_INFO_PATTERN, self.html).group(1))
except:
- self.logError(err, "Unknown error occurred")
+ self.logError("Unknown error occurred", errmsg)
- if err == "invalid":
+ if errmsg is "invalid":
self.fail(_("File not available"))
- elif err in ("freelimit", "size", "proxy"):
+
+ elif errmsg in ("freelimit", "size", "proxy"):
self.fail(_("Premium account needed"))
+
+ elif errmsg in ("expired", "server"):
+ self.retry(wait_time=600, reason=errmsg)
+
+ elif 'slot' in errmsg:
+ self.wantReconnect = True
+ self.retry(24, 3600, errmsg)
+
else:
- if err in 'server':
- self.setWait(600, False)
- elif err in 'expired':
- self.setWait(30, False)
- else:
- self.setWait(300, True)
+ self.wantReconnect = True
+ self.retry(wait_time=60, reason=errmsg)
+
- self.wait()
- self.retry(max_tries=25, reason=err)
+getInfo = create_getInfo(ShareonlineBiz)
diff --git a/module/plugins/hoster/TurbobitNet.py b/module/plugins/hoster/TurbobitNet.py
index 7426ea35c..9d7dcc67b 100644
--- a/module/plugins/hoster/TurbobitNet.py
+++ b/module/plugins/hoster/TurbobitNet.py
@@ -17,7 +17,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, t
class TurbobitNet(SimpleHoster):
__name__ = "TurbobitNet"
__type__ = "hoster"
- __version__ = "0.15"
+ __version__ = "0.16"
__pattern__ = r'http://(?:www\.)?turbobit\.net/(?:download/free/)?(?P<ID>\w+)'
@@ -42,7 +42,7 @@ class TurbobitNet(SimpleHoster):
def handleFree(self):
- self.url = "http://turbobit.net/download/free/%s" % self.info['ID']
+ self.url = "http://turbobit.net/download/free/%s" % self.info['pattern']['ID']
self.html = self.load(self.url, ref=True, decode=True)
rtUpdate = self.getRtUpdate()
@@ -130,7 +130,7 @@ class TurbobitNet(SimpleHoster):
for b in [1, 3]:
self.jscode = "var id = \'%s\';var b = %d;var inn = \'%s\';%sout" % (
- self.info['ID'], b, quote(fun), rtUpdate)
+ self.info['pattern']['ID'], b, quote(fun), rtUpdate)
try:
out = self.js.eval(self.jscode)
diff --git a/module/plugins/hoster/UploadingCom.py b/module/plugins/hoster/UploadingCom.py
index 2b11e3bf4..b163f2252 100644
--- a/module/plugins/hoster/UploadingCom.py
+++ b/module/plugins/hoster/UploadingCom.py
@@ -11,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, t
class UploadingCom(SimpleHoster):
__name__ = "UploadingCom"
__type__ = "hoster"
- __version__ = "0.38"
+ __version__ = "0.39"
__pattern__ = r'http://(?:www\.)?uploading\.com/files/(?:get/)?(?P<ID>\w+)'
@@ -47,7 +47,7 @@ class UploadingCom(SimpleHoster):
def handlePremium(self):
postData = {'action': 'get_link',
- 'code': self.info['ID'],
+ 'code': self.info['pattern']['ID'],
'pass': 'undefined'}
self.html = self.load('http://uploading.com/files/get/?JsHttpRequest=%d-xml' % timestamp(), post=postData)
@@ -70,7 +70,7 @@ class UploadingCom(SimpleHoster):
self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
self.req.http.lastURL = self.pyfile.url
- res = json_loads(self.load(ajax_url, post={'action': 'second_page', 'code': self.info['ID']}))
+ res = json_loads(self.load(ajax_url, post={'action': 'second_page', 'code': self.info['pattern']['ID']}))
if 'answer' in res and 'wait_time' in res['answer']:
wait_time = int(res['answer']['wait_time'])
@@ -79,7 +79,7 @@ class UploadingCom(SimpleHoster):
else:
self.error(_("No AJAX/WAIT"))
- res = json_loads(self.load(ajax_url, post={'action': 'get_link', 'code': self.info['ID'], 'pass': 'false'}))
+ res = json_loads(self.load(ajax_url, post={'action': 'get_link', 'code': self.info['pattern']['ID'], 'pass': 'false'}))
if 'answer' in res and 'link' in res['answer']:
url = res['answer']['link']
diff --git a/module/plugins/hoster/WebshareCz.py b/module/plugins/hoster/WebshareCz.py
index cd43de2bb..17aaff37c 100644
--- a/module/plugins/hoster/WebshareCz.py
+++ b/module/plugins/hoster/WebshareCz.py
@@ -35,13 +35,14 @@ class WebshareCz(SimpleHoster):
def handleFree(self):
api_data = self.load('https://webshare.cz/api/file_link/', post={'ident': self.fid})
+
self.logDebug("API data: " + api_data)
+
m = re.search('<link>(.+)</link>', api_data)
if m is None:
self.error(_("Unable to detect direct link"))
- direct = m.group(1)
- self.logDebug("Direct link: " + direct)
- self.download(direct, disposition=True)
+
+ self.download(m.group(1), disposition=True)
def getFileInfo(self):
diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py
index 8bf5aa942..3edf3c5c1 100644
--- a/module/plugins/hoster/ZippyshareCom.py
+++ b/module/plugins/hoster/ZippyshareCom.py
@@ -2,8 +2,7 @@
import re
-from os import path
-from urllib import unquote
+from os.path import join
from urlparse import urljoin
from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
@@ -12,7 +11,7 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class ZippyshareCom(SimpleHoster):
__name__ = "ZippyshareCom"
__type__ = "hoster"
- __version__ = "0.60"
+ __version__ = "0.62"
__pattern__ = r'(?P<HOST>http://www\d{0,2}\.zippyshare\.com)/v(?:/|iew\.jsp.*key=)(?P<KEY>\d+)'
@@ -40,12 +39,6 @@ class ZippyshareCom(SimpleHoster):
self.download(url)
- def getFileInfo(self):
- info = super(ZippyshareCom, self).getFileInfo()
- self.pyfile.name = info['name'] = unquote(info['name'])
- return info
-
-
def get_checksum(self):
try:
m = re.search(r'\+[ ]*\((\d+)[ ]*\%[ ]*(\d+)[ ]*\+[ ]*(\d+)[ ]*\%[ ]*(\d+)\)[ ]*\+', self.html)
@@ -64,8 +57,8 @@ class ZippyshareCom(SimpleHoster):
def get_link(self):
checksum = self.get_checksum()
- p_url = path.join("d", self.info['KEY'], str(checksum), self.pyfile.name)
- dl_link = urljoin(self.info['HOST'], p_url)
+ p_url = join("d", self.info['pattern']['KEY'], str(checksum), self.pyfile.name)
+ dl_link = urljoin(self.info['pattern']['HOST'], p_url)
return dl_link
diff --git a/module/plugins/internal/DeadCrypter.py b/module/plugins/internal/DeadCrypter.py
index c721c8390..07c5c3881 100644
--- a/module/plugins/internal/DeadCrypter.py
+++ b/module/plugins/internal/DeadCrypter.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
+from urllib import unquote
from urlparse import urlparse
from module.plugins.internal.SimpleCrypter import create_getInfo
@@ -9,7 +10,7 @@ from module.plugins.Crypter import Crypter as _Crypter
class DeadCrypter(_Crypter):
__name__ = "DeadCrypter"
__type__ = "crypter"
- __version__ = "0.03"
+ __version__ = "0.04"
__pattern__ = r'^unmatchable$'
@@ -20,7 +21,7 @@ class DeadCrypter(_Crypter):
@classmethod
def getInfo(cls, url="", html=""):
- return {'name': urlparse(url).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 1, 'url': url or ""}
+ return {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 1, 'url': url}
def setup(self):
diff --git a/module/plugins/internal/DeadHoster.py b/module/plugins/internal/DeadHoster.py
index b85aea3f9..6f3252f70 100644
--- a/module/plugins/internal/DeadHoster.py
+++ b/module/plugins/internal/DeadHoster.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
+from urllib import unquote
from urlparse import urlparse
from module.plugins.internal.SimpleHoster import create_getInfo
@@ -9,7 +10,7 @@ from module.plugins.Hoster import Hoster as _Hoster
class DeadHoster(_Hoster):
__name__ = "DeadHoster"
__type__ = "hoster"
- __version__ = "0.13"
+ __version__ = "0.14"
__pattern__ = r'^unmatchable$'
@@ -20,7 +21,7 @@ class DeadHoster(_Hoster):
@classmethod
def getInfo(cls, url="", html=""):
- return {'name': urlparse(url).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 1, 'url': url or ""}
+ return {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 1, 'url': url}
def setup(self):
diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py
index 24a2fa6b0..ba718950d 100644
--- a/module/plugins/internal/SimpleHoster.py
+++ b/module/plugins/internal/SimpleHoster.py
@@ -3,7 +3,8 @@
import re
from time import time
-from urlparse import urlparse
+from urllib import unquote
+from urlparse import urljoin, urlparse
from module.PyFile import statusMap as _statusMap
from module.network.CookieJar import CookieJar
@@ -32,7 +33,7 @@ def _error(self, reason, type):
#@TODO: Remove in 0.4.10
def _wait(self, seconds, reconnect):
if seconds:
- self.setWait(seconds)
+ self.setWait(seconds + 1)
if reconnect is not None:
self.wantReconnect = reconnect
@@ -113,25 +114,37 @@ def timestamp():
#@TODO: Move to hoster class in 0.4.10
-def _getDirectLink(self, url):
+def _isDirectLink(self, url, resumable=True):
header = self.load(url, ref=True, just_header=True, decode=True)
- if not 'code' in header or header['code'] != 302:
- return ""
-
if not 'location' in header or not header['location']:
return ""
- # if 'content-type' in header and "text/plain" not in header['content-type']:
- # return ""
+ 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 ""
+ else:
+ if not 'code' in header or header['code'] != 302:
+ return ""
+
+ if urlparse(location).scheme:
+ link = location
+ else:
+ p = urlparse(url)
+ base = "%s://%s" % (p.scheme, p.netloc)
+ link = urljoin(base, location)
- return header['location']
+ return link
class SimpleHoster(Hoster):
__name__ = "SimpleHoster"
__type__ = "hoster"
- __version__ = "0.67"
+ __version__ = "0.69"
__pattern__ = r'^unmatchable$'
@@ -153,6 +166,9 @@ class SimpleHoster(Hoster):
SIZE_PATTERN: (optional) Size that will be checked for the file
example: SIZE_PATTERN = r'(?P<S>file_size) (?P<U>size_unit)'
+ HASHSUM_PATTERN: (optional) Hash code and type of the file
+ example: HASHSUM_PATTERN = r'(?P<H>hash_code) (?P<T>MD5)'
+
OFFLINE_PATTERN: (optional) Check if the file is yet available online
example: OFFLINE_PATTERN = r'File (deleted|not found)'
@@ -188,9 +204,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 #: when None self-set to True if self.account else False
- MULTI_HOSTER = False #: Set to True to leech other hoster link
- CONTENT_DISPOSITION = False #: Set to True to replace file name with content-disposition value in http header
+ 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
@@ -202,14 +218,32 @@ class SimpleHoster(Hoster):
@classmethod
def getInfo(cls, url="", html=""):
- info = {'name': urlparse(url).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3 if url else 1, 'url': url or ""}
+ info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3, 'url': url}
if not html:
- if url:
- html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING)
- if isinstance(cls.TEXT_ENCODING, basestring):
- html = unicode(html, cls.TEXT_ENCODING)
- else:
+ try:
+ if not url:
+ info['error'] = "missing url"
+ info['status'] = 1
+ raise
+
+ try:
+ html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING)
+
+ if isinstance(cls.TEXT_ENCODING, basestring):
+ html = unicode(html, cls.TEXT_ENCODING)
+
+ except BadHeader, e:
+ info['error'] = "%d: %s" % (e.code, e.content)
+
+ if e.code is 404:
+ info['status'] = 1
+ raise
+
+ if e.code is 503:
+ info['status'] = 6
+ raise
+ except:
return info
online = False
@@ -225,19 +259,20 @@ class SimpleHoster(Hoster):
else:
try:
- info.update(re.match(cls.__pattern__, url).groupdict())
+ info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: pattern groups will be saved here, please save api stuff to info['api']
except:
pass
for pattern in ("FILE_INFO_PATTERN", "INFO_PATTERN",
"FILE_NAME_PATTERN", "NAME_PATTERN",
- "FILE_SIZE_PATTERN", "SIZE_PATTERN"): #@TODO: Remove old patterns starting with "FILE_" in 0.4.10
+ "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()
- if all(True for k in dict if k not in info):
- info.update(dict)
+ if all(True for k in dict if k not in info['pattern']):
+ info['pattern'].update(dict)
except AttributeError:
continue
@@ -248,12 +283,12 @@ class SimpleHoster(Hoster):
if online:
info['status'] = 2
- if 'N' in info:
- info['name'] = replace_patterns(info['N'].strip(),
+ if 'N' in info['pattern']:
+ info['name'] = replace_patterns(unquote(info['pattern']['N'].strip()),
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:
- size = replace_patterns(info['S'] + info['U'] if 'U' in info else info['S'],
+ if 'S' in info['pattern']:
+ size = replace_patterns(info['pattern']['S'] + info['pattern']['U'] if 'U' in info 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)
@@ -261,6 +296,10 @@ class SimpleHoster(Hoster):
unit = info['units'] if 'units' in info else None
info['size'] = parseFileSize(info['size'], unit)
+ if 'H' in info['pattern']:
+ hashtype = info['pattern']['T'] if 'T' in info['pattern'] else "hash"
+ info[hashtype] = info['pattern']['H']
+
return info
@@ -348,15 +387,20 @@ class SimpleHoster(Hoster):
if self.link:
self.download(self.link, disposition=self.CONTENT_DISPOSITION)
+ self.checkFile()
+
+
+ def checkFile(self):
+ if self.checkDownload({'empty': re.compile(r"^$")}) is "empty": #@TODO: Move to hoster in 0.4.10
+ self.fail(_("Empty file"))
+
def checkErrors(self):
- if hasattr(self, 'WAIT_PATTERN'):
- m = re.search(self.WAIT_PATTERN, self.html)
+ if hasattr(self, 'ERROR_PATTERN'):
+ m = re.search(self.ERROR_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)])
- self.wait(wait_time, False)
- return
+ e = self.info['error'] = m.group(1)
+ self.error(e)
if hasattr(self, 'PREMIUM_ONLY_PATTERN'):
m = re.search(self.PREMIUM_ONLY_PATTERN, self.html)
@@ -364,11 +408,13 @@ class SimpleHoster(Hoster):
self.info['error'] = "premium-only"
return
- if hasattr(self, 'ERROR_PATTERN'):
- m = re.search(self.ERROR_PATTERN, self.html)
+ if hasattr(self, 'WAIT_PATTERN'):
+ m = re.search(self.WAIT_PATTERN, self.html)
if m:
- e = self.info['error'] = m.group(1)
- self.error(e)
+ 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)])
+ self.wait(wait_time, False)
+ return
self.info.pop('error', None)
@@ -430,7 +476,7 @@ class SimpleHoster(Hoster):
def handleDirect(self):
- link = _getDirectLink(self, self.pyfile.url)
+ link = _isDirectLink(self, self.pyfile.url, self.resumeDownload)
if link:
self.logInfo(_("Direct download link detected"))
@@ -459,7 +505,7 @@ class SimpleHoster(Hoster):
self.link = m.group(1)
except Exception, e:
- self.fail(str(e))
+ self.fail(e)
def handlePremium(self):
@@ -474,7 +520,7 @@ class SimpleHoster(Hoster):
self.link = m.group(1)
except Exception, e:
- self.fail(str(e))
+ self.fail(e)
def longWait(self, wait_time=None, max_tries=3):
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:.*?<b>\s*(?P<S>[\d.,]+|[Uu]nlimited)\s*(?:(?P<U>[\w^_]+)\s*)?</b>'
+ TRAFFIC_LEFT_PATTERN = r'Traffic available today:.*?<b>\s*(?P<S>[\d.,]+|[Uu]nlimited)\s*(?:(?P<U>[\w^_]+)\s*)?</b>'
TRAFFIC_LEFT_UNIT = "MB" #: used only if no group <U> was found
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'>(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 2aaf18b1a..c3db3f335 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.26"
+ __version__ = "0.27"
__pattern__ = r'^unmatchable$'
@@ -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'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>'
NAME_PATTERN = r'(>Filename:</b></td><td nowrap>|name="fname" value="|<span class="name">)(?P<N>.+?)(\s*<|")'
SIZE_PATTERN = r'(>Size:</b></td><td>|>File:.*>|<span class="size">)(?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)'
@@ -49,10 +48,10 @@ class XFSHoster(SimpleHoster):
LEECH_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)'
LINK_PATTERN = None #: final download url pattern
- CAPTCHA_PATTERN = r'(https?://[^"\']+?/captchas?/[^"\']+)'
- CAPTCHA_DIV_PATTERN = r'>Enter code.*?<div.*?>(.+?)</div>'
- RECAPTCHA_PATTERN = None
- SOLVEMEDIA_PATTERN = None
+ CAPTCHA_PATTERN = r'(https?://[^"\']+?/captchas?/[^"\']+)'
+ CAPTCHA_BLOCK_PATTERN = r'>Enter code.*?<div.*?>(.+?)</div>'
+ RECAPTCHA_PATTERN = None
+ SOLVEMEDIA_PATTERN = None
FORM_PATTERN = None
FORM_INPUTS_MAP = None #: dict passed as input_names to parseHtmlForm
@@ -234,10 +233,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 +248,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 +311,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'<span.*?padding-left\s*:\s*(\d+).*?>(\d)</span>', html_unescape(captcha_div))