From 50ef18bfb7ced07dfacc8db28aa11dd376be65da Mon Sep 17 00:00:00 2001 From: Leon Bergmann Date: Sat, 4 Jan 2014 01:49:16 +0100 Subject: [PATCH 0001/3774] Update StreamcloudEu.py update DIRECT_LINK_PATTERN streamcloud uses flv files and mp4 --- module/plugins/hoster/StreamcloudEu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/plugins/hoster/StreamcloudEu.py b/module/plugins/hoster/StreamcloudEu.py index dd9bf9429c..b9ff37052d 100644 --- a/module/plugins/hoster/StreamcloudEu.py +++ b/module/plugins/hoster/StreamcloudEu.py @@ -16,7 +16,7 @@ class StreamcloudEu(XFileSharingPro): __author_mail__ = ("seoester@googlemail.com") HOSTER_NAME = "streamcloud.eu" - DIRECT_LINK_PATTERN = r'file: "(http://(stor|cdn)\d+\.streamcloud.eu:?\d*/.*/video\.mp4)",' + DIRECT_LINK_PATTERN = r'file: "(http://(stor|cdn)\d+\.streamcloud.eu:?\d*/.*/video\.(mp4|flv))",' def setup(self): super(StreamcloudEu, self).setup() From 9f6eddf1799f372f21a4dbdc44adf669d3e1fdc0 Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sat, 4 Jan 2014 09:11:24 +0100 Subject: [PATCH 0002/3774] Update AlldebridCom.py Fixed wrong description --- module/plugins/hooks/AlldebridCom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/plugins/hooks/AlldebridCom.py b/module/plugins/hooks/AlldebridCom.py index d0e9b1f779..775e6adc3a 100644 --- a/module/plugins/hooks/AlldebridCom.py +++ b/module/plugins/hooks/AlldebridCom.py @@ -18,7 +18,7 @@ class AlldebridCom(MultiHoster): ("unloadFailing", "bool", "Revert to stanard download if download fails", "False"), ("interval", "int", "Reload interval in hours (0 to disable)", "24")] - __description__ = """Real-Debrid.com hook plugin""" + __description__ = """Alldebrid.com hook plugin""" __author_name__ = ("Andy, Voigt") __author_mail__ = ("spamsales@online.de") From 952fbd8638916555145ff1965b8e961b350a59ca Mon Sep 17 00:00:00 2001 From: Maximilian Berger Date: Sat, 4 Jan 2014 09:13:36 +0100 Subject: [PATCH 0003/3774] Update README Updated repo link. --- README | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README b/README index 7f3c4f4c83..be6200ead9 100644 --- a/README +++ b/README @@ -1,4 +1,3 @@ - Description =========== @@ -11,7 +10,7 @@ pyLoad is written entirely in Python and is currently under heavy development. For news, downloads, wiki, forum and further information visit http://pyload.org/ To report bugs, suggest features, ask a question, get the developer version -or help us out, visit http://bitbucket.org/spoob/pyload/ +or help us out, visit http://github.com/pyload/pyload Documentation about extending pyLoad can be found at http://docs.pyload.org or join us at #pyload on irc.freenode.net From 22048007abb2df02ee4ac97f61bd6d615c68a529 Mon Sep 17 00:00:00 2001 From: Stefano Date: Sat, 4 Jan 2014 17:24:08 +0100 Subject: [PATCH 0004/3774] StreamcloudEu: increased version number after 50ef18bfb7ced07dfacc8db28aa11dd376be65da --- module/plugins/hoster/StreamcloudEu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/plugins/hoster/StreamcloudEu.py b/module/plugins/hoster/StreamcloudEu.py index b9ff37052d..dea2781d53 100644 --- a/module/plugins/hoster/StreamcloudEu.py +++ b/module/plugins/hoster/StreamcloudEu.py @@ -10,7 +10,7 @@ class StreamcloudEu(XFileSharingPro): __name__ = "StreamcloudEu" __type__ = "hoster" __pattern__ = r"http://(www\.)?streamcloud\.eu/\S+" - __version__ = "0.02" + __version__ = "0.03" __description__ = """Streamcloud.eu hoster plugin""" __author_name__ = ("seoester") __author_mail__ = ("seoester@googlemail.com") From 561ed2890ec6c4512badcf5ffd3758bc6dafb48d Mon Sep 17 00:00:00 2001 From: Stefano Date: Sat, 4 Jan 2014 18:28:45 +0100 Subject: [PATCH 0005/3774] CloudzerNet: improved getInfo See #185 --- module/plugins/hoster/CloudzerNet.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/module/plugins/hoster/CloudzerNet.py b/module/plugins/hoster/CloudzerNet.py index e95f907923..28c4dc6b1b 100644 --- a/module/plugins/hoster/CloudzerNet.py +++ b/module/plugins/hoster/CloudzerNet.py @@ -13,10 +13,8 @@ def getInfo(urls): if 'Location: http://cloudzer.net/404' in header: file_info = (url, 0, 1, url) else: - if url.endswith('/'): - api_data = getURL(url + 'status') - else: - api_data = getURL(url + '/status') + fid = re.search(CloudzerNet.__pattern__, url).group('ID') + api_data = getURL('http://cloudzer.net/file/%s/status' % fid) name, size = api_data.splitlines() size = parseFileSize(size) file_info = (name, size, 2, url) @@ -27,7 +25,7 @@ class CloudzerNet(SimpleHoster): __name__ = "CloudzerNet" __type__ = "hoster" __pattern__ = r"http://(www\.)?(cloudzer\.net/file/|clz\.to/(file/)?)(?P\w+).*" - __version__ = "0.03" + __version__ = "0.04" __description__ = """Cloudzer.net hoster plugin""" __author_name__ = ("gs", "z00nx", "stickell") __author_mail__ = ("I-_-I-_-I@web.de", "z00nx0@gmail.com", "l.stickell@yahoo.it") From b7cff12cef8a0c1843a6214aa3f1b4a3a91d9123 Mon Sep 17 00:00:00 2001 From: Stefano Date: Sat, 4 Jan 2014 20:39:24 +0100 Subject: [PATCH 0006/3774] CloudzerNet: fixed #185 --- module/plugins/hoster/CloudzerNet.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/module/plugins/hoster/CloudzerNet.py b/module/plugins/hoster/CloudzerNet.py index 28c4dc6b1b..8253c35b9b 100644 --- a/module/plugins/hoster/CloudzerNet.py +++ b/module/plugins/hoster/CloudzerNet.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import re + from module.plugins.internal.SimpleHoster import SimpleHoster from module.common.json_layer import json_loads from module.plugins.internal.CaptchaService import ReCaptcha @@ -30,9 +31,7 @@ class CloudzerNet(SimpleHoster): __author_name__ = ("gs", "z00nx", "stickell") __author_mail__ = ("I-_-I-_-I@web.de", "z00nx0@gmail.com", "l.stickell@yahoo.it") - FILE_SIZE_PATTERN = '(?P[^<]+)' WAIT_PATTERN = '' - FILE_OFFLINE_PATTERN = r'Please check the URL for typing errors, respectively' CAPTCHA_KEY = '6Lcqz78SAAAAAPgsTYF3UlGf2QFQCNuPMenuyHF3' def handleFree(self): @@ -69,3 +68,18 @@ def handleFree(self): url = response["url"] self.logDebug("Download link", url) self.download(url, disposition=True) + + def getFileInfo(self): + self.logDebug("URL: %s" % self.pyfile.url) + + header = getURL(self.pyfile.url, just_header=True) + + if 'Location: http://cloudzer.net/404' in header: + self.offline() + else: + self.fid = re.search(self.__pattern__, self.pyfile.url).group('ID') + api_data = getURL('http://cloudzer.net/file/%s/status' % self.fid) + self.pyfile.name, size = api_data.splitlines() + self.pyfile.size = parseFileSize(size) + + self.logDebug("FILE NAME: %s FILE SIZE: %s" % (self.pyfile.name, self.pyfile.size)) From 2429e9666fb849236126d310791f3eed3a622442 Mon Sep 17 00:00:00 2001 From: Stefano Date: Sat, 4 Jan 2014 21:25:59 +0100 Subject: [PATCH 0007/3774] WebshareCz: rewritten Fixes #452 --- module/plugins/hoster/WebshareCz.py | 86 +++++++++++++++++++---------- 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/module/plugins/hoster/WebshareCz.py b/module/plugins/hoster/WebshareCz.py index 1c9ddb290b..1a3aabaaa5 100644 --- a/module/plugins/hoster/WebshareCz.py +++ b/module/plugins/hoster/WebshareCz.py @@ -1,46 +1,72 @@ # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. +############################################################################ +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU Affero General Public License as # +# published by the Free Software Foundation, either version 3 of the # +# License, or (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Affero General Public License for more details. # +# # +# You should have received a copy of the GNU Affero General Public License # +# along with this program. If not, see . # +############################################################################ - You should have received a copy of the GNU General Public License - along with this program; if not, see . +import re - @author: zoidberg -""" +from module.plugins.internal.SimpleHoster import SimpleHoster +from module.network.RequestFactory import getRequest -import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + +def getInfo(urls): + h = getRequest() + for url in urls: + h.load(url) + fid = re.search(WebshareCz.__pattern__, url).group('ID') + api_data = h.load('https://webshare.cz/api/file_info/', post={'ident': fid}) + if 'File not found' in api_data: + file_info = (url, 0, 1, url) + else: + name = re.search('(.+)', api_data).group(1) + size = re.search('(.+)', api_data).group(1) + file_info = (name, size, 2, url) + yield file_info class WebshareCz(SimpleHoster): __name__ = "WebshareCz" __type__ = "hoster" - __pattern__ = r"http://(\w+\.)?webshare.cz/(stahnout/)?(?P\w{10})-.+" - __version__ = "0.12" - __description__ = """WebShare.cz""" - __author_name__ = ("zoidberg") + __pattern__ = r"https?://(?:www\.)?webshare.cz/(?:#/)?file/(?P\w+)" + __version__ = "0.13" + __description__ = """WebShare.cz hoster plugin""" + __author_name__ = ("stickell") + __author_mail__ = ("l.stickell@yahoo.it") - FILE_NAME_PATTERN = r'

Stahujete soubor:

\s*
(?P[^<]+)
' - FILE_SIZE_PATTERN = r'

Velikost souboru je:

\s*
(?P[^<]+)
' - FILE_OFFLINE_PATTERN = r'

Soubor ".*?" nebyl nalezen.

' + 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('(.+)', api_data) + if not m: + self.parseError('Unable to detect direct link') + direct = m.group(1) + self.logDebug("Direct link: " + direct) + self.download(direct, disposition=True) - DOWNLOAD_LINK_PATTERN = r'id="download_link" href="(?P.*?)"' + def getFileInfo(self): + self.logDebug("URL: %s" % self.pyfile.url) - def handleFree(self): - url_a = re.search(r"(var l.*)", self.html).group(1) - url_b = re.search(r"(var keyStr.*)", self.html).group(1) - url = self.js.eval("%s\n%s\ndec(l)" % (url_a, url_b)) + self.fid = re.search(self.__pattern__, self.pyfile.url).group('ID') - self.logDebug('Download link: ' + url) - self.download(url) + self.load(self.pyfile.url) + api_data = self.load('https://webshare.cz/api/file_info/', post={'ident': self.fid}) + if 'File not found' in api_data: + self.offline() + else: + self.pyfile.name = re.search('(.+)', api_data).group(1) + self.pyfile.size = re.search('(.+)', api_data).group(1) -getInfo = create_getInfo(WebshareCz) + self.logDebug("FILE NAME: %s FILE SIZE: %s" % (self.pyfile.name, self.pyfile.size)) From d664484a466f1b9c53b1f2b5ff9a5ffa9a80440b Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Thu, 9 Jan 2014 11:47:51 +0100 Subject: [PATCH 0008/3774] ShareonlineBiz: Https fix + code cosmetics Merged #459 --- module/plugins/hoster/ShareonlineBiz.py | 116 ++++++++++-------------- 1 file changed, 49 insertions(+), 67 deletions(-) diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py index 5b7a0e913c..d51935d338 100644 --- a/module/plugins/hoster/ShareonlineBiz.py +++ b/module/plugins/hoster/ShareonlineBiz.py @@ -10,12 +10,14 @@ from module.plugins.Hoster import Hoster from module.network.RequestFactory import getURL from module.plugins.Plugin import chunks -from module.plugins.internal.CaptchaService import ReCaptcha as _ReCaptcha +from module.plugins.internal.CaptchaService import ReCaptcha 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 @@ -37,21 +39,14 @@ def getInfo(urls): yield result -#suppress ocr plugin -class ReCaptcha(_ReCaptcha): - def result(self, server, challenge): - return self.plugin.decryptCaptcha("%simage" % server, get={"c": challenge}, - cookies=True, forceUser=True, imgtype="jpg") - - class ShareonlineBiz(Hoster): __name__ = "ShareonlineBiz" __type__ = "hoster" - __pattern__ = r"https?://[\w\.]*?(share\-online\.biz|egoshare\.com)/(download.php\?id\=|dl/)[\w]+" - __version__ = "0.37" + __pattern__ = r"https?://(?:www\.)?(share-online\.biz|egoshare\.com)/(download.php\?id=|dl/)(?P\w+)" + __version__ = "0.38" __description__ = """Shareonline.biz Download Hoster""" - __author_name__ = ("spoob", "mkaay", "zoidberg") - __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de", "zoidberg@mujmail.cz") + __author_name__ = ("spoob", "mkaay", "zoidberg", "Walter Purcaro") + __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de", "zoidberg@mujmail.cz", "vuolter@gmail.com") ERROR_INFO_PATTERN = r'

Information:

\s*
\s*(.*?)' @@ -59,7 +54,7 @@ def setup(self): # range request not working? # api supports resume, only one chunk # website isn't supporting resuming in first place - self.file_id = re.search(r"(id\=|/dl/)([a-zA-Z0-9]+)", self.pyfile.url).group(2) + 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 @@ -70,7 +65,7 @@ def setup(self): def process(self, pyfile): if self.premium: - self.handleAPIPremium() + self.handlePremium() #web-download fallback removed - didn't work anyway else: self.handleFree() @@ -85,10 +80,9 @@ def process(self, pyfile): if self.api_data: self.check_data = {"size": int(self.api_data['size']), "md5": self.api_data['md5']} - def downloadAPIData(self): + def loadAPIData(self): api_url_base = "http://api.share-online.biz/linkcheck.php?md5=1" - api_param_file = {"links": self.pyfile.url.replace( - "http://www.share-online.biz/dl/", "")} # api only supports old style links + api_param_file = {"links": self.file_id} # api only supports old style links src = self.load(api_url_base, cookies=False, post=api_param_file, decode=True) fields = src.split(";") @@ -96,12 +90,13 @@ def downloadAPIData(self): "status": fields[1]} if not self.api_data["status"] == "OK": self.offline() - 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 + 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 handleFree(self): - self.downloadAPIData() + self.loadAPIData() self.pyfile.name = self.api_data["filename"] self.pyfile.size = int(self.api_data["size"]) @@ -115,7 +110,7 @@ def handleFree(self): found = re.search(r'var wait=(\d+);', self.html) recaptcha = ReCaptcha(self) - for i in range(5): + for _ in xrange(5): challenge, response = recaptcha.challenge("6LdatrsSAAAAAHZrB70txiV5p-8Iv8BtVxlTtjKX") self.setWait(int(found.group(1)) if found else 30) response = self.load("%s/free/captcha/%d" % (self.pyfile.url, int(time() * 1000)), post={ @@ -125,7 +120,6 @@ def handleFree(self): if not response == '0': break - else: self.fail("No valid captcha solution received") @@ -146,29 +140,7 @@ def handleFree(self): elif check == "fail": self.retry(5, 300, "Download failed") - def checkErrors(self): - found = re.search(r"/failure/(.*?)/1", self.req.lastEffectiveURL) - if found: - err = found.group(1) - found = re.search(self.ERROR_INFO_PATTERN, self.html) - msg = found.group(1) if found else "" - self.logError(err, msg or "Unknown error occurred") - - if err in ('freelimit', 'size', 'proxy'): - self.fail(msg or "Premium account needed") - if err in 'invalid': - self.fail(msg or "File not available") - elif err in 'server': - self.setWait(600, False) - elif err in 'expired': - self.setWait(30, False) - else: - self.setWait(300, True) - - self.wait() - self.retry(max_tries=25, reason=msg) - - def handleAPIPremium(self): # should be working better + def handlePremium(self): # should be working better loading (account) api internally self.account.getAccountInfo(self.user, True) src = self.load("http://api.share-online.biz/account.php", {"username": self.user, "password": self.account.accounts[self.user]["password"], @@ -182,28 +154,38 @@ def handleAPIPremium(self): # should be working better self.logDebug(dlinfo) if not dlinfo["status"] == "online": self.offline() + else: + self.pyfile.name = dlinfo["name"] + self.pyfile.size = int(dlinfo["size"]) - self.pyfile.name = dlinfo["name"] - self.pyfile.size = int(dlinfo["size"]) + dlLink = dlinfo["url"] + if dlLink == "server_under_maintenance": + self.tempOffline() + else: + self.multiDL = True + self.download(dlLink) - dlLink = dlinfo["url"] - if dlLink == "server_under_maintenance": - self.tempoffline() + def checkErrors(self): + found = re.search(r"/failure/(.*?)/1", self.req.lastEffectiveURL) + if not found: + return + + err = found.group(1) + found = re.search(self.ERROR_INFO_PATTERN, self.html) + msg = found.group(1) if found else "" + self.logError(err, msg or "Unknown error occurred") + + if err in ('invalid'): + self.fail(msg or "File not available") + elif err in ('freelimit', 'size', 'proxy'): + self.fail(msg or "Premium account needed") else: - self.multiDL = True - self.download(dlLink) - - def checksum(self, local_file): - if self.api_data and "md5" in self.api_data and self.api_data["md5"]: - h = hashlib.md5() - f = open(local_file, "rb") - h.update(f.read()) - f.close() - hexd = h.hexdigest() - if hexd == self.api_data["md5"]: - return True, 0 + if err in 'server': + self.setWait(600, False) + elif err in 'expired': + self.setWait(30, False) else: - return False, 1 - else: - self.logWarning("MD5 checksum missing") - return True, 5 + self.setWait(300, True) + + self.wait() + self.retry(max_tries=25, reason=msg) From 41382d0151d7ce2ac89129717c9dc6d66cb384c3 Mon Sep 17 00:00:00 2001 From: Stefano Date: Thu, 9 Jan 2014 12:03:28 +0100 Subject: [PATCH 0009/3774] Uptobox: fixed premium expire detection See #423 --- module/plugins/accounts/UptoboxCom.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/plugins/accounts/UptoboxCom.py b/module/plugins/accounts/UptoboxCom.py index 7fc62694a2..92807439ee 100644 --- a/module/plugins/accounts/UptoboxCom.py +++ b/module/plugins/accounts/UptoboxCom.py @@ -11,3 +11,5 @@ class UptoboxCom(XFSPAccount): __author_mail__ = ("zoidberg@mujmail.cz") MAIN_PAGE = "http://uptobox.com/" + + VALID_UNTIL_PATTERN = r'>Premium.[Aa]ccount expire: ([^<]+)' From b1ef1518028f264cf3429f0fb490f7eaf27dffd3 Mon Sep 17 00:00:00 2001 From: Stefano Date: Thu, 9 Jan 2014 12:04:24 +0100 Subject: [PATCH 0010/3774] Uptobox: version increased after 41382d0 --- module/plugins/accounts/UptoboxCom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/plugins/accounts/UptoboxCom.py b/module/plugins/accounts/UptoboxCom.py index 92807439ee..17ca81f68a 100644 --- a/module/plugins/accounts/UptoboxCom.py +++ b/module/plugins/accounts/UptoboxCom.py @@ -4,7 +4,7 @@ class UptoboxCom(XFSPAccount): __name__ = "UptoboxCom" - __version__ = "0.01" + __version__ = "0.02" __type__ = "account" __description__ = """DDLStorage.com account plugin""" __author_name__ = ("zoidberg") From 5a8697f05355fde265337784804a81a60365c33e Mon Sep 17 00:00:00 2001 From: Stefano Date: Thu, 9 Jan 2014 12:22:31 +0100 Subject: [PATCH 0011/3774] XFileSharingPro: improved DIRECT_LINK_PATTERN to fix #423 --- module/plugins/hoster/XFileSharingPro.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py index d6fb313078..1fb0cf96c6 100644 --- a/module/plugins/hoster/XFileSharingPro.py +++ b/module/plugins/hoster/XFileSharingPro.py @@ -36,7 +36,7 @@ class XFileSharingPro(SimpleHoster): __name__ = "XFileSharingPro" __type__ = "hoster" __pattern__ = r"^unmatchable$" - __version__ = "0.23" + __version__ = "0.24" __description__ = """XFileSharingPro common hoster base""" __author_name__ = ("zoidberg", "stickell") __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -101,7 +101,7 @@ def prepare(self): if not hasattr(self, "HOSTER_NAME"): self.HOSTER_NAME = re.search(self.__pattern__, self.pyfile.url).group(1) if not hasattr(self, "DIRECT_LINK_PATTERN"): - self.DIRECT_LINK_PATTERN = r'(http://([^/]*?%s|\d+\.\d+\.\d+\.\d+)(:\d+/d/|(?:/files)?/\d+/\w+/)[^"\'<]+)' % self.HOSTER_NAME + self.DIRECT_LINK_PATTERN = r'(http://([^/]*?%s|\d+\.\d+\.\d+\.\d+)(:\d+)?(/d/|(?:/files)?/\d+/\w+/)[^"\'<]+)' % self.HOSTER_NAME self.captcha = self.errmsg = None self.passwords = self.getPassword().splitlines() From fb630e7ffcc3d36dedcae7e14bc77b4a8098f03e Mon Sep 17 00:00:00 2001 From: Stefano Date: Thu, 9 Jan 2014 12:23:00 +0100 Subject: [PATCH 0012/3774] Uptobox: fixed file info retrieve See #423 --- module/plugins/hoster/UptoboxCom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/plugins/hoster/UptoboxCom.py b/module/plugins/hoster/UptoboxCom.py index fe05bf9162..420610ee40 100644 --- a/module/plugins/hoster/UptoboxCom.py +++ b/module/plugins/hoster/UptoboxCom.py @@ -6,12 +6,12 @@ class UptoboxCom(XFileSharingPro): __name__ = "UptoboxCom" __type__ = "hoster" __pattern__ = r"http://(?:\w*\.)*?uptobox.com/\w{12}" - __version__ = "0.06" + __version__ = "0.07" __description__ = """Uptobox.com hoster plugin""" __author_name__ = ("zoidberg") __author_mail__ = ("zoidberg@mujmail.cz") - FILE_INFO_PATTERN = r'

\s*Download File\s*]*>(?P[^>]+)

\s*[^\(]*\((?P[^\)]+)\)' + FILE_INFO_PATTERN = r'
(?P.+) \((?P[^)]+)\)
' FILE_OFFLINE_PATTERN = r'
File Not Found
' HOSTER_NAME = "uptobox.com" From 83ef7f55716ff7fe5b067c6109e51d2e6a82b499 Mon Sep 17 00:00:00 2001 From: Stefano Date: Thu, 9 Jan 2014 13:53:55 +0100 Subject: [PATCH 0013/3774] Depositfiles: added dfiles.ru domain May fix #461 --- module/plugins/hoster/DepositfilesCom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/plugins/hoster/DepositfilesCom.py b/module/plugins/hoster/DepositfilesCom.py index 99c0d13a19..81458ac629 100644 --- a/module/plugins/hoster/DepositfilesCom.py +++ b/module/plugins/hoster/DepositfilesCom.py @@ -10,8 +10,8 @@ class DepositfilesCom(SimpleHoster): __name__ = "DepositfilesCom" __type__ = "hoster" - __pattern__ = r"https?://[\w\.]*?(depositfiles\.com|dfiles\.eu)(/\w{1,3})?/files/[\w]+" - __version__ = "0.45" + __pattern__ = r"https?://[\w\.]*?(depositfiles\.com|dfiles\.(eu|ru))(/\w{1,3})?/files/[\w]+" + __version__ = "0.46" __description__ = """Depositfiles.com Download Hoster""" __author_name__ = ("spoob", "zoidberg") __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz") From c2886928e0e17d2e6252d0af500dea7e27eea53c Mon Sep 17 00:00:00 2001 From: Stefano Date: Thu, 9 Jan 2014 17:12:34 +0100 Subject: [PATCH 0014/3774] Filefactory: added offline pattern --- module/plugins/hoster/FilefactoryCom.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/plugins/hoster/FilefactoryCom.py b/module/plugins/hoster/FilefactoryCom.py index 8d98140070..b12f1b9df3 100644 --- a/module/plugins/hoster/FilefactoryCom.py +++ b/module/plugins/hoster/FilefactoryCom.py @@ -24,13 +24,14 @@ class FilefactoryCom(SimpleHoster): __name__ = "FilefactoryCom" __type__ = "hoster" __pattern__ = r"https?://(?:www\.)?filefactory\.com/file/(?P[a-zA-Z0-9]+)" - __version__ = "0.44" + __version__ = "0.45" __description__ = """Filefactory.Com File Download Hoster""" __author_name__ = ("stickell") __author_mail__ = ("l.stickell@yahoo.it") FILE_INFO_PATTERN = r'
]*>\s*

(?P[^<]+)

\s*
\s*(?P[\d.]+) (?P\w+) uploaded' DIRECT_LINK_PATTERN = r'' + FILE_OFFLINE_PATTERN = r'

File Removed

' def handleFree(self): self.html = self.load(self.pyfile.url, decode=True) From 97f1a5ddabdb168fcacd36cfca2ca9f89c8d5bb0 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 10 Jan 2014 00:12:55 +0100 Subject: [PATCH 0015/3774] Hoster: ExtabitCom: Fix offline pattern + code cosmetics --- module/plugins/hoster/ExtabitCom.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/plugins/hoster/ExtabitCom.py b/module/plugins/hoster/ExtabitCom.py index f68627b561..0678185ed9 100644 --- a/module/plugins/hoster/ExtabitCom.py +++ b/module/plugins/hoster/ExtabitCom.py @@ -26,14 +26,14 @@ class ExtabitCom(SimpleHoster): __name__ = "ExtabitCom" __type__ = "hoster" - __pattern__ = r"http://(\w+\.)*extabit\.com/(file|go|fid)/(?P\w+)" - __version__ = "0.4" + __pattern__ = r"http://(?:www\.)?extabit\.com/(file|go|fid)/(?P\w+)" + __version__ = "0.5" __description__ = """Extabit.com""" __author_name__ = ("zoidberg") FILE_NAME_PATTERN = r'File:\s*\s*
' FILE_SIZE_PATTERN = r'Size:\s*(?P[^<]+)' - FILE_OFFLINE_PATTERN = r'

File not found

' + FILE_OFFLINE_PATTERN = r'>File not found<' TEMP_OFFLINE_PATTERN = r">(File is temporary unavailable|No download mirror)<" DOWNLOAD_LINK_PATTERN = r'[\'"](http://guest\d+\.extabit\.com/[a-z0-9]+/.*?)[\'"]' @@ -59,7 +59,7 @@ def handleFree(self): recaptcha = ReCaptcha(self) captcha_key = m.group(1) - for i in range(5): + for _ in xrange(5): get_data = {"type": "recaptcha"} get_data["challenge"], get_data["capture"] = recaptcha.challenge(captcha_key) response = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get=get_data)) From 6deb27fdf190191160eab39c682d3acf472edb97 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 10 Jan 2014 11:10:00 +0100 Subject: [PATCH 0016/3774] New crypter: TnyCz Merged #466 --- module/plugins/crypter/TnyCz.py | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 module/plugins/crypter/TnyCz.py diff --git a/module/plugins/crypter/TnyCz.py b/module/plugins/crypter/TnyCz.py new file mode 100644 index 0000000000..d393507c7f --- /dev/null +++ b/module/plugins/crypter/TnyCz.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: Walter Purcaro +""" + +from module.plugins.internal.SimpleCrypter import SimpleCrypter + +import re + + +class TnyCz(SimpleCrypter): + __name__ = "TnyCz" + __type__ = "crypter" + __pattern__ = r"http://(?:www\.)?tny\.cz/\w+" + __version__ = "0.01" + __description__ = """Tny.cz Plugin""" + __author_name__ = ("Walter Purcaro") + __author_mail__ = ("vuolter@gmail.com") + + TITLE_PATTERN = r'(?P<title>.+) - .+' + + def getLinks(self): + m = re.search(r'', self.html) + return re.findall(".+", self.load(m.group(1), decode=True)) if m else None From 119af0fdf45ad12995ddda9a7b7410c1d62db211 Mon Sep 17 00:00:00 2001 From: Stefano Date: Fri, 10 Jan 2014 11:56:33 +0100 Subject: [PATCH 0017/3774] Keep2share: fixed #450 --- module/plugins/hoster/Keep2shareCC.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/module/plugins/hoster/Keep2shareCC.py b/module/plugins/hoster/Keep2shareCC.py index 29e40bc7f9..323ee09caf 100644 --- a/module/plugins/hoster/Keep2shareCC.py +++ b/module/plugins/hoster/Keep2shareCC.py @@ -19,6 +19,7 @@ # http://k2s.cc/file/527111edfb9ba/random.bin import re +from urlparse import urlparse, urljoin from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo from module.plugins.internal.CaptchaService import ReCaptcha @@ -28,7 +29,7 @@ class Keep2shareCC(SimpleHoster): __name__ = "Keep2shareCC" __type__ = "hoster" __pattern__ = r"https?://(?:www\.)?(keep2share|k2s|keep2s)\.cc/file/(?P\w+)" - __version__ = "0.07" + __version__ = "0.08" __description__ = """Keep2share.cc hoster plugin""" __author_name__ = ("stickell") __author_mail__ = ("l.stickell@yahoo.it") @@ -42,27 +43,27 @@ class Keep2shareCC(SimpleHoster): RECAPTCHA_KEY = '6LcYcN0SAAAAABtMlxKj7X0hRxOY8_2U86kI1vbb' - FILE_URL_REPLACEMENTS = [(__pattern__, r"http://keep2share.cc/file/\g")] - def handleFree(self): + self.sanitize_url() + self.html = self.load(self.pyfile.url) + self.fid = re.search(r'', self.html).group(1) self.html = self.load(self.pyfile.url, post={'yt0': '', 'slow_id': self.fid}) m = re.search(r"function download\(\){.*window\.location\.href = '([^']+)';", self.html, re.DOTALL) if m: # Direct mode - self.startDownload("http://www.keep2share.cc" + m.group(1)) + self.startDownload(m.group(1)) else: self.handleCaptcha() - self.setWait(30) - self.wait() + self.wait(30) self.html = self.load(self.pyfile.url, post={'uniqueId': self.fid, 'free': 1}) m = re.search(self.DIRECT_LINK_PATTERN, self.html) if not m: self.parseError("Unable to detect direct link") - self.startDownload('http://keep2share.cc' + m.group(1)) + self.startDownload(m.group(1)) def handleCaptcha(self): recaptcha = ReCaptcha(self) @@ -88,8 +89,16 @@ def handleCaptcha(self): self.fail("All captcha attempts failed") def startDownload(self, url): - self.logDebug('Direct Link: ' + url) - self.download(url, disposition=True) + d = urljoin(self.base_url, url) + self.logDebug('Direct Link: ' + d) + 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'] + p = urlparse(self.pyfile.url) + self.base_url = "%s://%s" % (p.scheme, p.hostname) getInfo = create_getInfo(Keep2shareCC) From 22fe027409eb639d7a3494dd7d1ab7d4ea4a14e9 Mon Sep 17 00:00:00 2001 From: Stefano Date: Sat, 11 Jan 2014 14:44:13 +0100 Subject: [PATCH 0018/3774] TurbobitNetFolder: fixed #471 Merged with fixes #472 --- module/plugins/crypter/TurbobitNetFolder.py | 39 +++++++++------------ 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/module/plugins/crypter/TurbobitNetFolder.py b/module/plugins/crypter/TurbobitNetFolder.py index e172f8037a..bec5a44803 100644 --- a/module/plugins/crypter/TurbobitNetFolder.py +++ b/module/plugins/crypter/TurbobitNetFolder.py @@ -15,7 +15,7 @@ # along with this program. If not, see . # ############################################################################ -import math +from math import ceil import re from module.plugins.internal.SimpleCrypter import SimpleCrypter @@ -29,32 +29,27 @@ def format_links(fid): class TurbobitNetFolder(SimpleCrypter): __name__ = "TurbobitNetFolder" __type__ = "crypter" - __pattern__ = r"http://(?:w{3}.)?turbobit\.net/download/folder/(?P\w+)" - __version__ = "0.01" + __pattern__ = r"http://(?:www\.)?turbobit\.net/download/folder/(?P\w+)" + __version__ = "0.02" __description__ = """Turbobit.net Folder Plugin""" - __author_name__ = ("stickell") - __author_mail__ = ("l.stickell@yahoo.it") + __author_name__ = ("stickell", "Walter Purcaro") + __author_mail__ = ("l.stickell@yahoo.it", "vuolter@gmail.com") - TITLE_PATTERN = r"(?P.+)</div>" + TITLE_PATTERN = r"src='/js/lib/grid/icon/folder.png'> <span>(?P<title>.+?)</span>" - def getLinks(self): - folder_id = re.search(self.__pattern__, self.pyfile.url).group('id') - grid = self.load('http://turbobit.net/downloadfolder/gridFile', - get={'id_folder': folder_id, 'rows': 200}, decode=True) - grid = json_loads(grid) + def _getLinks(self, id, page=1): + gridFile = self.load('http://turbobit.net/downloadfolder/gridFile', + get={'rootId': id, 'rows': 200, 'page': page}, decode=True) + grid = json_loads(gridFile) - links_count = grid["records"] - pages = int(math.ceil(links_count / 200.0)) + pages = int(ceil(grid["records"] / 200.0)) - ids = list() for i in grid['rows']: - ids.append(i['id']) + yield i['id'] - for p in range(2, pages + 1): - grid = self.load('http://turbobit.net/downloadfolder/gridFile', - get={'id_folder': folder_id, 'rows': 200, 'page': p}, decode=True) - grid = json_loads(grid) - for i in grid['rows']: - ids.append(i['id']) + if page < pages: + self._getLinks(id, page + 1) - return map(format_links, ids) + def getLinks(self): + folder_id = re.match(self.__pattern__, self.pyfile.url).group('ID') + return map(format_links, self._getLinks(folder_id)) From 48deeb026f024dc68f11bd951bf586d5f0ffb0cf Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Wed, 15 Jan 2014 10:57:27 +0100 Subject: [PATCH 0019/3774] New hoster: FileStoreTo Fixes #129 Merges #480 --- module/plugins/hoster/FileStoreTo.py | 48 ++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 module/plugins/hoster/FileStoreTo.py diff --git a/module/plugins/hoster/FileStoreTo.py b/module/plugins/hoster/FileStoreTo.py new file mode 100644 index 0000000000..1a314947ba --- /dev/null +++ b/module/plugins/hoster/FileStoreTo.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: Walter Purcaro +""" + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class FileStoreTo(SimpleHoster): + __name__ = "FileStoreTo" + __type__ = "hoster" + __pattern__ = r"http://(www\.)?filestore\.to/\?d=(?P<ID>\w+)" + __version__ = "0.01" + __description__ = """FileStore.to download hoster""" + __author_name__ = ("Walter Purcaro", "stickell") + __author_mail__ = ("vuolter@gmail.com", "l.stickell@yahoo.it") + + FILE_INFO_PATTERN = r'File: <span[^>]*>(?P<N>.+)</span><br />Size: (?P<S>[\d,.]+) (?P<U>\w+)' + FILE_OFFLINE_PATTERN = r'>Download-Datei wurde nicht gefunden<' + + def setup(self): + self.resumeDownload = self.multiDL = True + + def handleFree(self): + self.wait(10) + ldc = re.search(r'wert="(\w+)"', self.html).group(1) + link = self.load("http://filestore.to/ajax/download.php", get={"LDC": ldc}) + self.logDebug("Download link = " + link) + self.download(link) + + +getInfo = create_getInfo(FileStoreTo) From 0512d40e3810aa654a5db89e021b2466e7a6c162 Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Wed, 15 Jan 2014 11:23:05 +0100 Subject: [PATCH 0020/3774] Filefactory: fixed premium (without direct) mode. --- module/plugins/hoster/FilefactoryCom.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/module/plugins/hoster/FilefactoryCom.py b/module/plugins/hoster/FilefactoryCom.py index b12f1b9df3..90b844b9f8 100644 --- a/module/plugins/hoster/FilefactoryCom.py +++ b/module/plugins/hoster/FilefactoryCom.py @@ -24,13 +24,13 @@ class FilefactoryCom(SimpleHoster): __name__ = "FilefactoryCom" __type__ = "hoster" __pattern__ = r"https?://(?:www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+)" - __version__ = "0.45" + __version__ = "0.46" __description__ = """Filefactory.Com File Download Hoster""" __author_name__ = ("stickell") __author_mail__ = ("l.stickell@yahoo.it") FILE_INFO_PATTERN = r'<div id="file_name"[^>]*>\s*<h2>(?P<N>[^<]+)</h2>\s*<div id="file_info">\s*(?P<S>[\d.]+) (?P<U>\w+) uploaded' - DIRECT_LINK_PATTERN = r'<section id="downloadLink">\s*<p class="textAlignCenter">\s*<a href="([^"]+)">[^<]+</a>\s*</p>\s*</section>' + DIRECT_LINK_PATTERN = r'<a href="(https?://[^"]+)"[^>]*><i[^>]*></i> Download with FileFactory Premium</a>' FILE_OFFLINE_PATTERN = r'<h2>File Removed</h2>' def handleFree(self): @@ -92,6 +92,7 @@ def handlePremium(self): elif 'content-disposition' in header: url = self.pyfile.url else: + self.logInfo('You could enable "Direct Downloads" on http://filefactory.com/account/') html = self.load(self.pyfile.url) found = re.search(self.DIRECT_LINK_PATTERN, html) if found: From 834fffc4baa7379a21ab7d10712d1360f236c7ed Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Wed, 15 Jan 2014 11:30:39 +0100 Subject: [PATCH 0021/3774] YoutubeBatch: Completed rewriting Fixes #458 Merges #479 --- module/plugins/crypter/YoutubeBatch.py | 166 +++++++++++++++---------- 1 file changed, 101 insertions(+), 65 deletions(-) diff --git a/module/plugins/crypter/YoutubeBatch.py b/module/plugins/crypter/YoutubeBatch.py index ee84f05280..696f3927e8 100644 --- a/module/plugins/crypter/YoutubeBatch.py +++ b/module/plugins/crypter/YoutubeBatch.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- """ @@ -18,98 +17,135 @@ @author: Walter Purcaro """ +from urlparse import urljoin import re -import json +from module.common.json_layer import json_loads from module.plugins.Crypter import Crypter -from os.path import join +from module.utils import save_join API_KEY = "AIzaSyCKnWLNlkX-L4oD1aEzqqhRw1zczeD6_k0" class YoutubeBatch(Crypter): __name__ = "YoutubeBatch" - __type__ = "container" - __pattern__ = r"https?://(?:[^/]*?)youtube\.com/(?:(view_play_list|playlist|.*?feature=PlayList|user)(?:.*?[?&](?:list|p)=|/))([a-zA-Z0-9-_]+)" - __version__ = "0.94" - __description__ = """Youtube.com Channel Download Plugin""" - __author_name__ = ("RaNaN", "Spoob", "zoidberg", "roland", "Walter Purcaro") - __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org", "zoidberg@mujmail.cz", "roland@enkore.de", "vuolter@gmail.com") - - def json_response(self, api, req): + __type__ = "crypter" + __pattern__ = r"https?://(?:www\.)?(m\.)?youtube\.com/(?P<TYPE>user|playlist|view_play_list)(/|.*?[?&](?:list|p)=)(?P<ID>[\w-]+)" + __version__ = "1.00" + __description__ = """Youtube.com channel & playlist decrypter""" + __config__ = [("likes", "bool", "Grab user (channel) liked videos", "False"), + ("favorites", "bool", "Grab user (channel) favorite videos", "False"), + ("uploads", "bool", "Grab channel unplaylisted videos", "True")] + __author_name__ = ("Walter Purcaro") + __author_mail__ = ("vuolter@gmail.com") + + def api_response(self, ref, req): req.update({"key": API_KEY}) - url = "https://www.googleapis.com/youtube/v3/" + api + url = urljoin("https://www.googleapis.com/youtube/v3/", ref) page = self.load(url, get=req) - return json.loads(page) - - def get_playlist_baseinfos(self, playlist_id): - res = self.json_response("playlists", {"part": "snippet", "id": playlist_id}) - - snippet = res["items"][0]["snippet"] - playlist_name = snippet["title"] - channel_title = snippet["channelTitle"] - return playlist_name, channel_title - - def get_channel_id(self, user_name): - res = self.json_response("channels", {"part": "id", "forUsername": user_name}) - return res["items"][0]["id"] - - def get_playlists(self, user_name, token=None): - channel_id = self.get_channel_id(user_name) - req = {"part": "id", "maxResults": "50", "channelId": channel_id} + return json_loads(page) + + def getChannel(self, user): + channels = self.api_response("channels", {"part": "id,snippet,contentDetails", "forUsername": user, "maxResults": "50"}) + if channels["items"]: + channel = channels["items"][0] + return {"id": channel["id"], + "title": channel["snippet"]["title"], + "relatedPlaylists": channel["contentDetails"]["relatedPlaylists"], + "user": user} # One lone channel for user? + + def getPlaylist(self, p_id): + playlists = self.api_response("playlists", {"part": "snippet", "id": p_id}) + if playlists["items"]: + playlist = playlists["items"][0] + return {"id": p_id, + "title": playlist["snippet"]["title"], + "channelId": playlist["snippet"]["channelId"], + "channelTitle": playlist["snippet"]["channelTitle"]} + + def _getPlaylists(self, id, token=None): + req = {"part": "id", "maxResults": "50", "channelId": id} if token: req.update({"pageToken": token}) - res = self.json_response("playlists", req) - for item in res["items"]: - yield item["id"] + playlists = self.api_response("playlists", req) + + for playlist in playlists["items"]: + yield playlist["id"] - if "nextPageToken" in res: - for item in self.get_playlists(user_name, res["nextPageToken"]): + if "nextPageToken" in playlists: + for item in self._getPlaylists(id, playlists["nextPageToken"]): yield item - def get_videos(self, playlist_id, token=None): - req = {"part": "snippet", "maxResults": "50", "playlistId": playlist_id} + def getPlaylists(self, ch_id): + return map(self.getPlaylist, self._getPlaylists(ch_id)) + + def _getVideosId(self, id, token=None): + req = {"part": "contentDetails", "maxResults": "50", "playlistId": id} if token: req.update({"pageToken": token}) - res = self.json_response("playlistItems", req) - for item in res["items"]: - yield "http://youtube.com/watch?v=" + item["snippet"]["resourceId"]["videoId"] + playlist = self.api_response("playlistItems", req) - if "nextPageToken" in res: - for item in self.get_videos(playlist_id, res["nextPageToken"]): + for item in playlist["items"]: + yield item["contentDetails"]["videoId"] + + if "nextPageToken" in playlist: + for item in self._getVideosId(id, playlist["nextPageToken"]): yield item + def getVideosId(self, p_id): + return list(self._getVideosId(p_id)) + def decrypt(self, pyfile): - match_obj = re.match(self.__pattern__, pyfile.url) - match_type, match_result = match_obj.group(1), match_obj.group(2) - playlist_ids = [] - - #: is a channel username or just a playlist id? - if match_type == "user": - ids = self.get_playlists(match_result) - playlist_ids.extend(ids) + match = re.match(self.__pattern__, pyfile.url) + m_id = match.group("ID") + m_type = match.group("TYPE") + + if m_type == "user": + self.logDebug("Url recognized as Channel") + user = m_id + channel = self.getChannel(user) + + if channel: + playlists = self.getPlaylists(channel["id"]) + self.logDebug("%s playlist\s found on channel \"%s\"" % (len(playlists), channel["title"])) + + relatedplaylist = {p_name: self.getPlaylist(p_id) for p_name, p_id in channel["relatedPlaylists"].iteritems()} + self.logDebug("Channel's related playlists found = %s" % relatedplaylist.keys()) + + relatedplaylist["uploads"]["title"] = "Unplaylisted videos" + relatedplaylist["uploads"]["checkDups"] = True #: checkDups flag + + for p_name, p_data in relatedplaylist.iteritems(): + if self.getConfig(p_name): + p_data["title"] += " of " + user + playlists.append(p_data) + else: + playlists = [] else: - playlist_ids.append(match_result) - - self.logDebug("Playlist IDs = %s" % playlist_ids) - - if not playlist_ids: - self.fail("Wrong url") - - for id in playlist_ids: - self.logDebug("Processing playlist id: %s" % id) + self.logDebug("Url recognized as Playlist") + playlists = [self.getPlaylist(m_id)] - playlist_name, channel_title = self.get_playlist_baseinfos(id) - video_links = [x for x in self.get_videos(id)] + if not playlists: + self.fail("No playlist available") - self.logInfo("%s videos found on playlist \"%s\" (channel \"%s\")" % (len(video_links), playlist_name, channel_title)) + addedvideos = [] + urlize = lambda x: "https://www.youtube.com/watch?v=" + x + for p in playlists: + p_name = p["title"] + p_videos = self.getVideosId(p["id"]) + p_folder = save_join(self.config['general']['download_folder'], p["channelTitle"], p_name) + self.logDebug("%s video\s found on playlist \"%s\"" % (len(p_videos), p_name)) - if not video_links: + if not p_videos: continue + elif "checkDups" in p: + p_urls = [urlize(v_id) for v_id in p_videos if v_id not in addedvideos] + self.logDebug("%s video\s available on playlist \"%s\" after duplicates cleanup" % (len(p_urls), p_name)) + else: + p_urls = map(urlize, p_videos) - self.logDebug("Video links = %s" % video_links) + self.packages.append((p_name, p_urls, p_folder)) #: folder is NOT recognized by pyload 0.4.9! - folder = join(self.config['general']['download_folder'], channel_title, playlist_name) - self.packages.append((playlist_name, video_links, folder)) #Note: folder is NOT used actually! + addedvideos.extend(p_videos) From 2f3dd24356c7613c30b38303098b1986bbeb6334 Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Wed, 15 Jan 2014 11:39:10 +0100 Subject: [PATCH 0022/3774] New crypter: DailymotionBatch Meges #469 --- module/plugins/crypter/DailymotionBatch.py | 111 +++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 module/plugins/crypter/DailymotionBatch.py diff --git a/module/plugins/crypter/DailymotionBatch.py b/module/plugins/crypter/DailymotionBatch.py new file mode 100644 index 0000000000..1427bdc133 --- /dev/null +++ b/module/plugins/crypter/DailymotionBatch.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: Walter Purcaro +""" + +from urlparse import urljoin +import re + +from module.common.json_layer import json_loads +from module.plugins.Crypter import Crypter +from module.utils import save_join + + +class DailymotionBatch(Crypter): + __name__ = "DailymotionBatch" + __type__ = "crypter" + __pattern__ = r"https?://(?:www\.)?dailymotion\.com/((playlists/)?(?P<TYPE>playlist|user)/)?(?P<ID>[\w^_]+)(?(TYPE)|#)" + __version__ = "0.01" + __description__ = """Dailymotion channel & playlist decrypter""" + __author_name__ = ("Walter Purcaro") + __author_mail__ = ("vuolter@gmail.com") + + def api_response(self, ref, req=None): + url = urljoin("https://api.dailymotion.com/", ref) + page = self.load(url, get=req) + return json_loads(page) + + def getPlaylistInfo(self, id): + ref = "playlist/" + id + req = {"fields": "name,owner.screenname"} + playlist = self.api_response(ref, req) + + if "error" in playlist: + return + + name = playlist["name"] + owner = playlist["owner.screenname"] + return name, owner + + def _getPlaylists(self, user_id, page=1): + ref = "user/%s/playlists" % user_id + req = {"fields": "id", "page": page, "limit": 100} + user = self.api_response(ref, req) + + if "error" in user: + return + + for playlist in user["list"]: + yield playlist["id"] + + if user["has_more"]: + for item in self._getPlaylists(user_id, page + 1): + yield item + + def getPlaylists(self, user_id): + return [(id,) + self.getPlaylistInfo(id) for id in self._getPlaylists(user_id)] + + def _getVideos(self, id, page=1): + ref = "playlist/%s/videos" % id + req = {"fields": "url", "page": page, "limit": 100} + playlist = self.api_response(ref, req) + + if "error" in playlist: + return + + for video in playlist["list"]: + yield video["url"] + + if playlist["has_more"]: + for item in self._getVideos(id, page + 1): + yield item + + def getVideos(self, playlist_id): + return list(self._getVideos(playlist_id))[::-1] + + def decrypt(self, pyfile): + m = re.match(self.__pattern__, pyfile.url) + m_id = m.group("ID") + m_type = m.group("TYPE") + + if m_type == "playlist": + self.logDebug("Url recognized as Playlist") + p_info = self.getPlaylistInfo(m_id) + playlists = [(m_id,) + p_info] if p_info else None + else: + self.logDebug("Url recognized as Channel") + playlists = self.getPlaylists(m_id) + self.logDebug("%s playlist\s found on channel \"%s\"" % (len(playlists), m_id)) + + if not playlists: + self.fail("No playlist available") + + for p_id, p_name, p_owner in playlists: + p_videos = self.getVideos(p_id) + p_folder = save_join(self.config['general']['download_folder'], p_owner, p_name) + self.logDebug("%s video\s found on playlist \"%s\"" % (len(p_videos), p_name)) + self.packages.append((p_name, p_videos, p_folder)) #: folder is NOT recognized by pyload 0.4.9! From 089ed7073cd438f9994c990ec640502e6c043cdb Mon Sep 17 00:00:00 2001 From: peekayy <peekayy.dev@gmail.com> Date: Wed, 15 Jan 2014 11:51:37 +0100 Subject: [PATCH 0023/3774] New hoster: SoundcloudCom Merges #478 --- module/plugins/hoster/SoundcloudCom.py | 54 ++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 module/plugins/hoster/SoundcloudCom.py diff --git a/module/plugins/hoster/SoundcloudCom.py b/module/plugins/hoster/SoundcloudCom.py new file mode 100644 index 0000000000..7e6d162362 --- /dev/null +++ b/module/plugins/hoster/SoundcloudCom.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +import re +import pycurl + +from module.plugins.Hoster import Hoster + + +class SoundcloudCom(Hoster): + __name__ = "SoundcloudCom" + __type__ = "hoster" + __pattern__ = r"https?://(?:www\.)?soundcloud\.com/(?P<UID>.*?)/(?P<SID>.*)" + __version__ = "0.1" + __description__ = """SoundCloud.com audio download hoster""" + __author_name__ = ("Peekayy") + __author_mail__ = ("peekayy.dev@gmail.com") + + def process(self, pyfile): + # default UserAgent of HTTPRequest fails for this hoster so we use this one + self.req.http.c.setopt(pycurl.USERAGENT, 'Mozilla/5.0') + page = self.load(pyfile.url) + match = re.search(r'<div class="haudio.*?large.*?" data-sc-track="(?P<ID>[0-9]*)"', page) + songId = clientId = "" + if match: + songId = match.group("ID") + if len(songId) <= 0: + self.logError("Could not find song id") + self.offline() + else: + match = re.search(r'"clientID":"(?P<CID>.*?)"', page) + if match: + clientId = match.group("CID") + + if len(clientId) <= 0: + clientId = "b45b1aa10f1ac2941910a7f0d10f8e28" + + match = re.search(r'<em itemprop="name">\s(?P<TITLE>.*?)\s</em>', page) + if match: + pyfile.name = match.group("TITLE") + ".mp3" + else: + pyfile.name = re.match(self.__pattern__, pyfile.url).group("SID") + ".mp3" + + # url to retrieve the actual song url + page = self.load("https://api.sndcdn.com/i1/tracks/%s/streams" % songId, get={"client_id": clientId}) + # getting streams + # for now we choose the first stream found in all cases + # it could be improved if relevant for this hoster + streams = [ + (result.group("QUALITY"), result.group("URL")) + for result in re.finditer(r'"(?P<QUALITY>.*?)":"(?P<URL>.*?)"', page) + ] + self.logDebug("Found Streams", streams) + self.logDebug("Downloading", streams[0][0], streams[0][1]) + self.download(streams[0][1]) From cd9aebb7ed4e742fe17b09e0886341367662b2c7 Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Thu, 16 Jan 2014 13:36:16 +0100 Subject: [PATCH 0024/3774] SimpleHoster: improved PREMIUM_ONLY process Usually premium only pages doesn't show the file information so trying to get them would raise an exception. --- module/plugins/internal/SimpleHoster.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 47fded2601..46d0a95170 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -163,7 +163,7 @@ def __str__(self): class SimpleHoster(Hoster): __name__ = "SimpleHoster" - __version__ = "0.32" + __version__ = "0.33" __pattern__ = None __type__ = "hoster" __description__ = """Base hoster plugin""" @@ -202,14 +202,17 @@ def process(self, pyfile): # Due to a 0.4.9 core bug self.load would keep previous cookies even if overridden by cookies parameter. # Workaround using getURL. Can be reverted in 0.5 as the cookies bug has been fixed. self.html = getURL(pyfile.url, decode=not self.SH_BROKEN_ENCODING, cookies=self.SH_COOKIES) - self.getFileInfo() + premium_only = hasattr(self, 'PREMIUM_ONLY_PATTERN') and re.search(self.PREMIUM_ONLY_PATTERN, self.html) + if not premium_only: # Usually premium only pages doesn't show the file information + self.getFileInfo() + if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()): self.handlePremium() + elif premium_only: + self.fail("This link require a premium account") else: # This line is required due to the getURL workaround. Can be removed in 0.5 self.html = self.load(pyfile.url, decode=not self.SH_BROKEN_ENCODING, cookies=self.SH_COOKIES) - if hasattr(self, 'PREMIUM_ONLY_PATTERN') and re.search(self.PREMIUM_ONLY_PATTERN, self.html): - self.fail("This link require a premium account") self.handleFree() def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False, decode=False): From 145602cde43f99aa704b8a2e01cb0b1852938565 Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Thu, 16 Jan 2014 13:36:54 +0100 Subject: [PATCH 0025/3774] Filefactory: added PREMIUM_ONLY_PATTERN --- module/plugins/hoster/FilefactoryCom.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/plugins/hoster/FilefactoryCom.py b/module/plugins/hoster/FilefactoryCom.py index 90b844b9f8..37987059b2 100644 --- a/module/plugins/hoster/FilefactoryCom.py +++ b/module/plugins/hoster/FilefactoryCom.py @@ -24,7 +24,7 @@ class FilefactoryCom(SimpleHoster): __name__ = "FilefactoryCom" __type__ = "hoster" __pattern__ = r"https?://(?:www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+)" - __version__ = "0.46" + __version__ = "0.47" __description__ = """Filefactory.Com File Download Hoster""" __author_name__ = ("stickell") __author_mail__ = ("l.stickell@yahoo.it") @@ -32,6 +32,7 @@ class FilefactoryCom(SimpleHoster): FILE_INFO_PATTERN = r'<div id="file_name"[^>]*>\s*<h2>(?P<N>[^<]+)</h2>\s*<div id="file_info">\s*(?P<S>[\d.]+) (?P<U>\w+) uploaded' DIRECT_LINK_PATTERN = r'<a href="(https?://[^"]+)"[^>]*><i[^>]*></i> Download with FileFactory Premium</a>' FILE_OFFLINE_PATTERN = r'<h2>File Removed</h2>' + PREMIUM_ONLY_PATTERN = r'>Premium Account Required<' def handleFree(self): self.html = self.load(self.pyfile.url, decode=True) From 56d728540dcfa8b7f74622731b34675a4e99e0ee Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Thu, 16 Jan 2014 13:58:32 +0100 Subject: [PATCH 0026/3774] UploadingCom: updated patterns Fixes #462 --- module/plugins/hoster/UploadingCom.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/module/plugins/hoster/UploadingCom.py b/module/plugins/hoster/UploadingCom.py index 1da5714600..c8ca2169c5 100644 --- a/module/plugins/hoster/UploadingCom.py +++ b/module/plugins/hoster/UploadingCom.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- + """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ import re from pycurl import HTTPHEADER + from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp from module.common.json_layer import json_loads @@ -27,14 +28,14 @@ class UploadingCom(SimpleHoster): __name__ = "UploadingCom" __type__ = "hoster" __pattern__ = r"http://(?:www\.)?uploading\.com/files/(?:get/)?(?P<ID>[\w\d]+)" - __version__ = "0.33" + __version__ = "0.34" __description__ = """Uploading.Com File Download Hoster""" __author_name__ = ("jeix", "mkaay", "zoidberg") __author_mail__ = ("jeix@hasnomail.de", "mkaay@mkaay.de", "zoidberg@mujmail.cz") - FILE_NAME_PATTERN = r'<title>Download (?P<N>.*?) for free on uploading.com' - FILE_SIZE_PATTERN = r'File size: (?P.*?)' - FILE_OFFLINE_PATTERN = r'The requested file is not found' + FILE_NAME_PATTERN = r'id="file_title">(?P.+)(?P[\d.]+) (?P\w+)<' + FILE_OFFLINE_PATTERN = r'Page not found!' def process(self, pyfile): # set lang to english From 4c02adf00b8a7d6abcd2467eaff512f5780c4d7d Mon Sep 17 00:00:00 2001 From: igel-kun Date: Thu, 16 Jan 2014 18:20:56 +0100 Subject: [PATCH 0027/3774] Update FilestubeCom.py --- module/plugins/crypter/FilestubeCom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/plugins/crypter/FilestubeCom.py b/module/plugins/crypter/FilestubeCom.py index 1e5712cb59..ca6333de4c 100644 --- a/module/plugins/crypter/FilestubeCom.py +++ b/module/plugins/crypter/FilestubeCom.py @@ -21,7 +21,7 @@ class FilestubeCom(SimpleCrypter): __name__ = "FilestubeCom" __type__ = "crypter" - __pattern__ = r"http://(?:w{3}.)?filestube\.com/\w+" + __pattern__ = r"http://(?:w{3}.)?filestube\.(?:com|to)/\w+" __version__ = "0.01" __description__ = """Filestube.com Plugin""" __author_name__ = ("stickell") From 046bffc70cb2ea66e3d7e24e426e5ea99bff1654 Mon Sep 17 00:00:00 2001 From: Stefano Date: Fri, 17 Jan 2014 13:02:13 +0100 Subject: [PATCH 0028/3774] Filestube: version increase after 4c02adf00b8a7d6abcd2467eaff512f5780c4d7d --- module/plugins/crypter/FilestubeCom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/plugins/crypter/FilestubeCom.py b/module/plugins/crypter/FilestubeCom.py index ca6333de4c..24e2ca1378 100644 --- a/module/plugins/crypter/FilestubeCom.py +++ b/module/plugins/crypter/FilestubeCom.py @@ -22,7 +22,7 @@ class FilestubeCom(SimpleCrypter): __name__ = "FilestubeCom" __type__ = "crypter" __pattern__ = r"http://(?:w{3}.)?filestube\.(?:com|to)/\w+" - __version__ = "0.01" + __version__ = "0.02" __description__ = """Filestube.com Plugin""" __author_name__ = ("stickell") __author_mail__ = ("l.stickell@yahoo.it") From c297f2749efe9e37ecab0965993cc8c8c11e8e59 Mon Sep 17 00:00:00 2001 From: igel-kun Date: Sat, 18 Jan 2014 15:28:37 +0100 Subject: [PATCH 0029/3774] XFileSharingPro: * Added 2 hosters * Extended OFFLINE_PATTERN Merged pull request #485 --- module/plugins/hooks/XFileSharingPro.py | 4 ++-- module/plugins/hoster/XFileSharingPro.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/module/plugins/hooks/XFileSharingPro.py b/module/plugins/hooks/XFileSharingPro.py index fe2df840d9..7186322930 100644 --- a/module/plugins/hooks/XFileSharingPro.py +++ b/module/plugins/hooks/XFileSharingPro.py @@ -7,7 +7,7 @@ class XFileSharingPro(Hook): __name__ = "XFileSharingPro" - __version__ = "0.06" + __version__ = "0.07" __type__ = "hook" __config__ = [("activated", "bool", "Activated", "True"), ("loadDefault", "bool", "Include default (built-in) hoster list", "True"), @@ -30,7 +30,7 @@ def loadPattern(self): "aieshare.com", "asixfiles.com", "banashare.com", "cyberlocker.ch", "eyesfile.co", "eyesfile.com", "fileband.com", "filedwon.com", "filedownloads.org", "hipfile.com", "kingsupload.com", "mlfat4arab.com", "netuploaded.com", "odsiebie.pl", "q4share.com", "ravishare.com", "uptobox.com", "verzend.be", - "xvidstage.com", + "xvidstage.com", "thefile.me", "sharesix.com", #NOT TESTED: "bebasupload.com", "boosterking.com", "divxme.com", "filevelocity.com", "glumbouploads.com", "grupload.com", "heftyfile.com", "host4desi.com", "laoupload.com", "linkzhost.com", "movreel.com", diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py index 1fb0cf96c6..5b167c3c96 100644 --- a/module/plugins/hoster/XFileSharingPro.py +++ b/module/plugins/hoster/XFileSharingPro.py @@ -36,7 +36,7 @@ class XFileSharingPro(SimpleHoster): __name__ = "XFileSharingPro" __type__ = "hoster" __pattern__ = r"^unmatchable$" - __version__ = "0.24" + __version__ = "0.25" __description__ = """XFileSharingPro common hoster base""" __author_name__ = ("zoidberg", "stickell") __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -44,7 +44,7 @@ class XFileSharingPro(SimpleHoster): FILE_NAME_PATTERN = r'[^<]+ \((?P[^<]+)\)' FILE_INFO_PATTERN = r'Filename:(?P[^<]+)\s*.*?\((?P[^<]+)\)' - FILE_OFFLINE_PATTERN = r'<(b|h[1-6])>File Not Found' + FILE_OFFLINE_PATTERN = r'<(b|h[1-6])>File Not Found|This file has been removed' WAIT_PATTERN = r'.*?>(\d+)' LONG_WAIT_PATTERN = r'(?P\d+(?=\s*hour))?.*?(?P\d+(?=\s*minute))?.*?(?P\d+(?=\s*second))?' From aaa01255c938604a1df090edb570a1df1e7800e2 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 17 Feb 2014 22:08:40 +0100 Subject: [PATCH 0030/3774] Hoster: RyushareCom: Free dl fix (thx nomad71) --- module/plugins/hoster/RyushareCom.py | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/module/plugins/hoster/RyushareCom.py b/module/plugins/hoster/RyushareCom.py index 675eaddde6..77efa00810 100644 --- a/module/plugins/hoster/RyushareCom.py +++ b/module/plugins/hoster/RyushareCom.py @@ -12,11 +12,11 @@ class RyushareCom(XFileSharingPro): __name__ = "RyushareCom" __type__ = "hoster" - __pattern__ = r"http://(?:\w*\.)*?ryushare.com/\w{11,}" - __version__ = "0.13" + __pattern__ = r"http://(?:www\.)?ryushare\.com/\w+" + __version__ = "0.14" __description__ = """ryushare.com hoster plugin""" - __author_name__ = ("zoidberg", "stickell","quareevo") - __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it","quareevo@arcor.de") + __author_name__ = ("zoidberg", "stickell", "quareevo") + __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it", "quareevo@arcor.de") HOSTER_NAME = "ryushare.com" @@ -24,13 +24,6 @@ class RyushareCom(XFileSharingPro): DIRECT_LINK_PATTERN = r'(http://([^/]*?ryushare.com|\d+\.\d+\.\d+\.\d+)(:\d+/d/|/files/\w+/\w+/)[^"\'<]+)' SOLVEMEDIA_PATTERN = r'http:\/\/api\.solvemedia\.com\/papi\/challenge\.script\?k=(.*?)"' - def setup(self): - self.resumeDownload = self.multiDL = True - if not self.premium: - self.limitDL = 2 - # Up to 3 chunks allowed in free downloads. Unknown for premium - self.chunkLimit = 3 - def getDownloadLink(self): retry = False self.html = self.load(self.pyfile.url) @@ -42,15 +35,15 @@ def getDownloadLink(self): action, inputs = self.parseHtmlForm('F1') self.setWait(65) - # Wait + # Wait 1 hour if 'You have reached the download-limit!!!' in self.html: - self.setWait(3600, True) + self.setWait(1 * 60 * 60, True) retry = True - + match = re.search(self.WAIT_PATTERN, self.html) if match: m = match.groupdict(0) - waittime = int(m["hour"])*60*60 + int(m['min']) * 60 + int(m['sec']) + waittime = int(m["hour"]) * 60 * 60 + int(m['min']) * 60 + int(m['sec']) self.setWait(waittime, True) retry = True @@ -59,7 +52,6 @@ def getDownloadLink(self): self.retry() for i in xrange(5): - m = re.search(self.SOLVEMEDIA_PATTERN, self.html) if not m: self.parseError("Error parsing captcha") @@ -71,14 +63,13 @@ def getDownloadLink(self): inputs["adcopy_challenge"] = challenge inputs["adcopy_response"] = response - self.html = self.load(self.pyfile.url, post = inputs) + self.html = self.load(self.pyfile.url, post=inputs) if "WRONG CAPTCHA" in self.html: self.invalidCaptcha() self.logInfo("Invalid Captcha") else: self.correctCaptcha() break - else: self.fail("You have entered 5 invalid captcha codes") @@ -86,4 +77,5 @@ def getDownloadLink(self): m = re.search(r'Click here to download', self.html) return m.group(1) + getInfo = create_getInfo(RyushareCom) From 81fc21ea133b26a51f597bccd021b7504373a2a2 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 25 Jan 2014 18:03:45 +0100 Subject: [PATCH 0031/3774] New crypter MultiUpOrg --- module/plugins/crypter/MultiUpOrg.py | 49 ++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 module/plugins/crypter/MultiUpOrg.py diff --git a/module/plugins/crypter/MultiUpOrg.py b/module/plugins/crypter/MultiUpOrg.py new file mode 100644 index 0000000000..997d608622 --- /dev/null +++ b/module/plugins/crypter/MultiUpOrg.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# @author: Walter Purcaro +############################################################################### + +import re +from urlparse import urljoin + +from module.plugins.internal.SimpleCrypter import SimpleCrypter + + +class MultiUpOrg(SimpleCrypter): + __name__ = "MultiUpOrg" + __type__ = "crypter" + __pattern__ = r"http://(?:www\.)?multiup\.org/(en|fr)/(?Pproject|download|miror)/\w+(/\w+)?" + __version__ = "0.01" + __description__ = """MultiUp.org crypter plugin""" + __author_name__ = "Walter Purcaro" + __author_mail__ = "vuolter@gmail.com" + + TITLE_PATTERN = r'.*(Project|Projet|ownload|élécharger) (?P<title>.+?) (\(|- )' + + def getLinks(self): + m_type = re.match(self.__pattern__, self.pyfile.url).group("TYPE") + + if m_type == "project": + pattern = r'\n(http://www\.multiup\.org/(?:en|fr)/download/.*)' + else: + pattern = r'style="width:97%;text-align:left".*\n.*href="(.*)"' + if m_type == "download": + dl_pattern = r'href="(.*)">.*\n.*<h5>DOWNLOAD</h5>' + miror_page = urljoin("http://www.multiup.org", re.search(dl_pattern, self.html).group(1)) + self.html = self.load(miror_page) + + return re.findall(pattern, self.html) From 58a1b3e5144697526aad5e0f8b7cf23411d69337 Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Fri, 21 Feb 2014 02:46:17 +0100 Subject: [PATCH 0032/3774] Hoster: CyberlockerCh: Mark dead --- module/plugins/hoster/CyberlockerCh.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/module/plugins/hoster/CyberlockerCh.py b/module/plugins/hoster/CyberlockerCh.py index 19a4473b3a..a08bf85189 100644 --- a/module/plugins/hoster/CyberlockerCh.py +++ b/module/plugins/hoster/CyberlockerCh.py @@ -1,17 +1,16 @@ # -*- coding: utf-8 -*- -from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo +from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo -class CyberlockerCh(XFileSharingPro): + +class CyberlockerCh(DeadHoster): __name__ = "CyberlockerCh" __type__ = "hoster" - __pattern__ = r"http://(www\.)?cyberlocker\.ch/\w{12}" - __version__ = "0.01" + __pattern__ = r'http://(?:www\.)?cyberlocker\.ch/\w+' + __version__ = "0.02" __description__ = """Cyberlocker.ch hoster plugin""" - __author_name__ = ("stickell") - __author_mail__ = ("l.stickell@yahoo.it") - - HOSTER_NAME = "cyberlocker.ch" + __author_name__ = "stickell" + __author_mail__ = "l.stickell@yahoo.it" getInfo = create_getInfo(CyberlockerCh) From 4dcd89c60c0e7658367b259f74346f92e133bf8c Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Fri, 21 Feb 2014 17:08:23 +0100 Subject: [PATCH 0033/3774] Hoster: CloudzerNet: Mark dead --- module/plugins/hoster/CloudzerNet.py | 79 ++-------------------------- 1 file changed, 5 insertions(+), 74 deletions(-) diff --git a/module/plugins/hoster/CloudzerNet.py b/module/plugins/hoster/CloudzerNet.py index 8253c35b9b..d0a19a9450 100644 --- a/module/plugins/hoster/CloudzerNet.py +++ b/module/plugins/hoster/CloudzerNet.py @@ -1,85 +1,16 @@ # -*- coding: utf-8 -*- -import re -from module.plugins.internal.SimpleHoster import SimpleHoster -from module.common.json_layer import json_loads -from module.plugins.internal.CaptchaService import ReCaptcha -from module.network.RequestFactory import getURL -from module.utils import parseFileSize +from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo -def getInfo(urls): - for url in urls: - header = getURL(url, just_header=True) - if 'Location: http://cloudzer.net/404' in header: - file_info = (url, 0, 1, url) - else: - fid = re.search(CloudzerNet.__pattern__, url).group('ID') - api_data = getURL('http://cloudzer.net/file/%s/status' % fid) - name, size = api_data.splitlines() - size = parseFileSize(size) - file_info = (name, size, 2, url) - yield file_info - - -class CloudzerNet(SimpleHoster): +class CloudzerNet(DeadHoster): __name__ = "CloudzerNet" __type__ = "hoster" - __pattern__ = r"http://(www\.)?(cloudzer\.net/file/|clz\.to/(file/)?)(?P<ID>\w+).*" - __version__ = "0.04" + __pattern__ = r"https?://(?:www\.)?(cloudzer\.net/file/|clz\.to/(file/)?)\w+" + __version__ = "0.05" __description__ = """Cloudzer.net hoster plugin""" __author_name__ = ("gs", "z00nx", "stickell") __author_mail__ = ("I-_-I-_-I@web.de", "z00nx0@gmail.com", "l.stickell@yahoo.it") - WAIT_PATTERN = '<meta name="wait" content="(\d+)">' - CAPTCHA_KEY = '6Lcqz78SAAAAAPgsTYF3UlGf2QFQCNuPMenuyHF3' - - def handleFree(self): - found = re.search(self.WAIT_PATTERN, self.html) - seconds = int(found.group(1)) - self.logDebug("Found wait", seconds) - self.setWait(seconds + 1) - self.wait() - response = self.load('http://cloudzer.net/io/ticket/slot/%s' % self.file_info['ID'], post=' ', cookies=True) - self.logDebug("Download slot request response", response) - response = json_loads(response) - if response["succ"] is not True: - self.fail("Unable to get a download slot") - - recaptcha = ReCaptcha(self) - challenge, response = recaptcha.challenge(self.CAPTCHA_KEY) - post_data = {"recaptcha_challenge_field": challenge, "recaptcha_response_field": response} - response = json_loads(self.load('http://cloudzer.net/io/ticket/captcha/%s' % self.file_info['ID'], - post=post_data, cookies=True)) - self.logDebug("Captcha check response", response) - self.logDebug("First check") - - if "err" in response: - if response["err"] == "captcha": - self.logDebug("Wrong captcha") - self.invalidCaptcha() - self.retry() - elif "Sie haben die max" in response["err"] or "You have reached the max" in response["err"]: - self.logDebug("Download limit reached, waiting an hour") - self.setWait(3600, True) - self.wait() - if "type" in response: - if response["type"] == "download": - url = response["url"] - self.logDebug("Download link", url) - self.download(url, disposition=True) - - def getFileInfo(self): - self.logDebug("URL: %s" % self.pyfile.url) - - header = getURL(self.pyfile.url, just_header=True) - - if 'Location: http://cloudzer.net/404' in header: - self.offline() - else: - self.fid = re.search(self.__pattern__, self.pyfile.url).group('ID') - api_data = getURL('http://cloudzer.net/file/%s/status' % self.fid) - self.pyfile.name, size = api_data.splitlines() - self.pyfile.size = parseFileSize(size) - self.logDebug("FILE NAME: %s FILE SIZE: %s" % (self.pyfile.name, self.pyfile.size)) +getInfo = create_getInfo(CloudzerNet) From 171af764df8cbd54e869f0a5e375e8292fc2cfec Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Fri, 7 Mar 2014 15:31:20 +0100 Subject: [PATCH 0034/3774] PutlockerCom (Firedrive now) and SockshareCom updated. Merged #515 Fixed: #501 --- module/plugins/hoster/PutlockerCom.py | 100 +++++++---------------- module/plugins/hoster/SockshareCom.py | 110 ++++++++++++++++++++------ 2 files changed, 116 insertions(+), 94 deletions(-) diff --git a/module/plugins/hoster/PutlockerCom.py b/module/plugins/hoster/PutlockerCom.py index afe084028b..002783bfde 100644 --- a/module/plugins/hoster/PutlockerCom.py +++ b/module/plugins/hoster/PutlockerCom.py @@ -1,96 +1,54 @@ # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: jeix -""" +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# @author: Walter Purcaro +############################################################################### import re -from os import rename -from module.plugins.internal.SimpleHoster import SimpleHoster +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class PutlockerCom(SimpleHoster): __name__ = "PutlockerCom" __type__ = "hoster" - __pattern__ = r'http://(?:www\.)?putlocker\.com/(mobile/)?(file|embed)/(?P<ID>[a-zA-Z0-9]+)' - __version__ = "0.32" - __description__ = """Putlocker.Com""" - __author_name__ = ("jeix", "stickell", "Walter Purcaro") - __author_mail__ = ("", "l.stickell@yahoo.it", "vuolter@gmail.com") + __pattern__ = r'https?://(?:www\.)?(firedrive|putlocker)\.com/(mobile/)?(file|embed)/(?P<ID>\w+)' + __version__ = "0.33" + __description__ = """Firedrive.com hoster plugin""" + __author_name__ = "Walter Purcaro" + __author_mail__ = "vuolter@gmail.com" - FILE_OFFLINE_PATTERN = r"This file doesn't exist, or has been removed." - FILE_INFO_PATTERN = r'site-content">\s*<h1>(?P<N>.+)<strong>\( (?P<S>[^)]+) \)</strong></h1>' + FILE_NAME_PATTERN = r'<b>Name:</b> (?P<N>.+) <br>' + FILE_SIZE_PATTERN = r'<b>Size:</b> (?P<S>[\d.]+) (?P<U>[a-zA-Z]+) <br>' + FILE_OFFLINE_PATTERN = r"<div class=\"sad_face_image\">" - FILE_URL_REPLACEMENTS = [(__pattern__, r'http://www.putlocker.com/file/\g<ID>')] - HOSTER_NAME = "putlocker.com" + FILE_URL_REPLACEMENTS = [(__pattern__, r'http://www.firedrive.com/file/\g<ID>')] def setup(self): self.multiDL = self.resumeDownload = True self.chunkLimit = -1 def handleFree(self): - name = self.pyfile.name link = self._getLink() self.logDebug("Direct link: " + link) self.download(link, disposition=True) - self.processName(name) def _getLink(self): - hash_data = re.search(r'<input type="hidden" value="([a-z0-9]+)" name="hash">', self.html) - if not hash_data: - self.parseError('Unable to detect hash') - - post_data = {"hash": hash_data.group(1), "confirm": "Continue+as+Free+User"} - self.html = self.load(self.pyfile.url, post=post_data) - if (">You have exceeded the daily stream limit for your country\\. You can wait until tomorrow" in self.html or - "(>This content server has been temporarily disabled for upgrades|Try again soon\\. You can still download it below\\.<)" in self.html): - self.retry(wait_time=60 * 60 * 2, reason="Download limit exceeded or server disabled") # 2 hours wait - - patterns = (r'(/get_file\.php\?id=[A-Z0-9]+&key=[a-zA-Z0-9=]+&original=1)', - r'(/get_file\.php\?download=[A-Z0-9]+&key=[a-z0-9]+)', - r'(/get_file\.php\?download=[A-Z0-9]+&key=[a-z0-9]+&original=1)', - r'<a href="/gopro\.php">Tired of ads and waiting\? Go Pro!</a>[\t\n\rn ]+</div>[\t\n\rn ]+<a href="(/.*?)"') - for pattern in patterns: - link = re.search(pattern, self.html) - if link: - break - else: - link = re.search(r"playlist: '(/get_file\.php\?stream=[a-zA-Z0-9=]+)'", self.html) - if link: - self.html = self.load("http://www.%s%s" % (self.HOSTER_NAME, link.group(1))) - link = re.search(r'media:content url="(http://.*?)"', self.html) - if not link: - pattern = "\"(http://media\\-b\\d+\\.%s\\.%s/download/\\d+/.*?)\"" % self.HOSTER_NAME.rsplit(".") - link = re.search(pattern, self.html) - else: - self.parseError('Unable to detect a download link') + self.html = self.load(self.pyfile.url, post={"confirm": re.search(r'name="confirm" value="(.*)"', self.html).group(1)}) + return re.search(r'<a href="(https?://dl\.firedrive\.com/.*?)"', self.html).group(1) - link = link.group(1).replace("&", "&") - if link.startswith("http://"): - return link - else: - return "http://www.%s%s" % (self.HOSTER_NAME, link) - def processName(self, name_old): - name = self.pyfile.name - if name <= name_old: - return - name_new = re.sub(r'\.[^.]+$', "", name_old) + name[len(name_old):] - filename = self.lastDownload - self.pyfile.name = name_new - rename(filename, filename.rsplit(name)[0] + name_new) - self.logInfo("%(name)s renamed to %(newname)s" % {"name": name, "newname": name_new}) +getInfo = create_getInfo(PutlockerCom) diff --git a/module/plugins/hoster/SockshareCom.py b/module/plugins/hoster/SockshareCom.py index b2635d8bc8..fd0e5aa918 100644 --- a/module/plugins/hoster/SockshareCom.py +++ b/module/plugins/hoster/SockshareCom.py @@ -1,33 +1,97 @@ # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# @author: Walter Purcaro +############################################################################### - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. +import re +from os import rename - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo - @author: Walter Purcaro -""" -from module.plugins.hoster.PutlockerCom import PutlockerCom - - -class SockshareCom(PutlockerCom): +class SockshareCom(SimpleHoster): __name__ = "SockshareCom" __type__ = "hoster" - __pattern__ = r'http://(?:www\.)?sockshare\.com/(mobile/)?(file|embed)/(?P<ID>[A-Z0-9]+)' - __version__ = "0.01" - __description__ = """Sockshare.Com""" - __author_name__ = ("Walter Purcaro") - __author_mail__ = ("vuolter@gmail.com") + __pattern__ = r'http://(?:www\.)?sockshare\.com/(mobile/)?(file|embed)/(?P<ID>\w+)' + __version__ = "0.02" + __description__ = """Sockshare.com hoster plugin""" + __author_name__ = ("jeix", "stickell", "Walter Purcaro") + __author_mail__ = ("", "l.stickell@yahoo.it", "vuolter@gmail.com") + + FILE_INFO_PATTERN = r'site-content">\s*<h1>(?P<N>.+)<strong>\( (?P<S>[^)]+) \)</strong></h1>' + FILE_OFFLINE_PATTERN = r'>This file doesn\'t exist, or has been removed.<' FILE_URL_REPLACEMENTS = [(__pattern__, r'http://www.sockshare.com/file/\g<ID>')] - HOSTER_NAME = "sockshare.com" + + def setup(self): + self.multiDL = self.resumeDownload = True + self.chunkLimit = -1 + + def handleFree(self): + name = self.pyfile.name + link = self._getLink() + self.logDebug("Direct link: " + link) + self.download(link, disposition=True) + self.processName(name) + + def _getLink(self): + hash_data = re.search(r'<input type="hidden" value="([a-z0-9]+)" name="hash">', self.html) + if not hash_data: + self.parseError("Unable to detect hash") + + post_data = {"hash": hash_data.group(1), "confirm": "Continue+as+Free+User"} + self.html = self.load(self.pyfile.url, post=post_data) + if (">You have exceeded the daily stream limit for your country\\. You can wait until tomorrow" in self.html or + "(>This content server has been temporarily disabled for upgrades|Try again soon\\. You can still download it below\\.<)" in self.html): + self.retry(wait_time=60 * 60 * 2, reason="Download limit exceeded or server disabled") # 2 hours wait + + patterns = (r'(/get_file\.php\?id=[A-Z0-9]+&key=[a-zA-Z0-9=]+&original=1)', + r'(/get_file\.php\?download=[A-Z0-9]+&key=[a-z0-9]+)', + r'(/get_file\.php\?download=[A-Z0-9]+&key=[a-z0-9]+&original=1)', + r'<a href="/gopro\.php">Tired of ads and waiting\? Go Pro!</a>[\t\n\rn ]+</div>[\t\n\rn ]+<a href="(/.*?)"') + for pattern in patterns: + link = re.search(pattern, self.html) + if link: + break + else: + link = re.search(r"playlist: '(/get_file\.php\?stream=[a-zA-Z0-9=]+)'", self.html) + if link: + self.html = self.load("http://www.sockshare.com" + link.group(1)) + link = re.search(r'media:content url="(http://.*?)"', self.html) + if not link: + link = re.search(r'\"(http://media\\-b\\d+\\.sockshare\\.com/download/\\d+/.*?)\"', self.html) + else: + self.parseError('Unable to detect a download link') + + link = link.group(1).replace("&", "&") + if link.startswith("http://"): + return link + else: + return "http://www.sockshare.com" + link + + def processName(self, name_old): + name = self.pyfile.name + if name <= name_old: + return + name_new = re.sub(r'\.[^.]+$', "", name_old) + name[len(name_old):] + filename = self.lastDownload + self.pyfile.name = name_new + rename(filename, filename.rsplit(name)[0] + name_new) + self.logInfo("%(name)s renamed to %(newname)s" % {"name": name, "newname": name_new}) + + +getInfo = create_getInfo(SockshareCom) From 46d41e6674954362cbb681b5ec541c8885b1b2c7 Mon Sep 17 00:00:00 2001 From: igel-kun <mathiaswe@gmx.de> Date: Fri, 7 Mar 2014 15:40:59 +0100 Subject: [PATCH 0035/3774] New hoster NosuploadCom New crypter NosvideoCom Merged #496 --- module/plugins/crypter/NosvideoCom.py | 13 +++++++++ module/plugins/hoster/NosuploadCom.py | 38 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 module/plugins/crypter/NosvideoCom.py create mode 100644 module/plugins/hoster/NosuploadCom.py diff --git a/module/plugins/crypter/NosvideoCom.py b/module/plugins/crypter/NosvideoCom.py new file mode 100644 index 0000000000..49b932fc0c --- /dev/null +++ b/module/plugins/crypter/NosvideoCom.py @@ -0,0 +1,13 @@ +from module.plugins.internal.SimpleCrypter import SimpleCrypter + + +class NosvideoCom(SimpleCrypter): + __name__ = "NosvideoCom" + __type__ = "crypter" + __pattern__ = r"http://(?:www\.)?nosvideo\.com/\?v=\w+" + __version__ = "0.01" + __description__ = """Nosvideo.com Plugin""" + __author_name__ = "igel" + + LINK_PATTERN = r'href="(http://(?:w{3}\.)?nosupload.com/\?d=\w+)"' + TITLE_PATTERN = r"<[tT]itle>Watch (?P<title>.+)</[tT]itle>" diff --git a/module/plugins/hoster/NosuploadCom.py b/module/plugins/hoster/NosuploadCom.py new file mode 100644 index 0000000000..5735390bbd --- /dev/null +++ b/module/plugins/hoster/NosuploadCom.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class NosuploadCom(XFileSharingPro): + __name__ = "NosuploadCom" + __type__ = "hoster" + __version__ = "0.1" + __pattern__ = r"http://(?:www\.)?nosupload\.com/\?d=\w{12}" + __description__ = """nosupload.com hoster plugin""" + __author_name__ = "igel" + + HOSTER_NAME = "nosupload.com" + + FILE_SIZE_PATTERN = r'<p><strong>Size:</strong> (?P<S>[0-9\.]+) (?P<U>[kKMG]?B)</p>' + DIRECT_LINK_PATTERN = r'<a class="select" href="(http://.+?)">Download</a>' + WAIT_PATTERN = r'Please wait.*?>(\d+)</span>' + + def getDownloadLink(self): + # stage1: press the "Free Download" button + data = self.getPostParameters() + self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True) + + # stage2: wait some time and press the "Download File" button + data = self.getPostParameters() + wait_time = re.search(self.WAIT_PATTERN, self.html, re.MULTILINE | re.DOTALL).group(1) + self.logDebug("hoster told us to wait %s seconds" % wait_time) + self.wait(wait_time) + self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True) + + # stage3: get the download link + return re.search(self.DIRECT_LINK_PATTERN, self.html, re.S).group(1) + + +getInfo = create_getInfo(NosuploadCom) From c067065bd110d9a8e0d27d806767a3f48ad55d19 Mon Sep 17 00:00:00 2001 From: igel-kun <mathiaswe@gmx.de> Date: Fri, 7 Mar 2014 15:56:41 +0100 Subject: [PATCH 0036/3774] K2S: added two wait patterns. Merged #495 --- module/plugins/hoster/Keep2shareCC.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/module/plugins/hoster/Keep2shareCC.py b/module/plugins/hoster/Keep2shareCC.py index 323ee09caf..59308690cb 100644 --- a/module/plugins/hoster/Keep2shareCC.py +++ b/module/plugins/hoster/Keep2shareCC.py @@ -16,7 +16,7 @@ ############################################################################ # Test links (random.bin): -# http://k2s.cc/file/527111edfb9ba/random.bin +# http://k2s.cc/file/55fb73e1c00c5/random.bin import re from urlparse import urlparse, urljoin @@ -29,7 +29,7 @@ class Keep2shareCC(SimpleHoster): __name__ = "Keep2shareCC" __type__ = "hoster" __pattern__ = r"https?://(?:www\.)?(keep2share|k2s|keep2s)\.cc/file/(?P<ID>\w+)" - __version__ = "0.08" + __version__ = "0.10" __description__ = """Keep2share.cc hoster plugin""" __author_name__ = ("stickell") __author_mail__ = ("l.stickell@yahoo.it") @@ -40,6 +40,7 @@ class Keep2shareCC(SimpleHoster): DIRECT_LINK_PATTERN = r'To download this file with slow speed, use <a href="([^"]+)">this link</a>' WAIT_PATTERN = r'Please wait ([\d:]+) to download this file' + ALREADY_DOWNLOADING_PATTERN = r'Free account does not allow to download more than one file at the same time' RECAPTCHA_KEY = '6LcYcN0SAAAAABtMlxKj7X0hRxOY8_2U86kI1vbb' @@ -60,6 +61,22 @@ def handleFree(self): 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, reconnect=True) + self.retry() + + m = re.search(self.ALREADY_DOWNLOADING_PATTERN, 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(1800, reconnect=True) + self.retry() + m = re.search(self.DIRECT_LINK_PATTERN, self.html) if not m: self.parseError("Unable to detect direct link") From b09b41e252de8eefaa9c2a3efb91b7663c4c244c Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Fri, 7 Mar 2014 16:16:43 +0100 Subject: [PATCH 0037/3774] New crypter: DlProtectCom Merged #492 Resolves: #273 --- module/plugins/crypter/DlProtectCom.py | 75 ++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 module/plugins/crypter/DlProtectCom.py diff --git a/module/plugins/crypter/DlProtectCom.py b/module/plugins/crypter/DlProtectCom.py new file mode 100644 index 0000000000..d93455a55f --- /dev/null +++ b/module/plugins/crypter/DlProtectCom.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- + +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# @author: Walter Purcaro +############################################################################### + +import re +from base64 import urlsafe_b64encode +from time import time + +from module.plugins.internal.SimpleCrypter import SimpleCrypter + + +class DlProtectCom(SimpleCrypter): + __name__ = "DlProtectCom" + __type__ = "crypter" + __pattern__ = r"http://(?:www\.)?dl-protect\.com/((en|fr)/)?(?P<ID>\w+)" + __version__ = "0.01" + __description__ = """dl-protect.com decrypter plugin""" + __author_name__ = "Walter Purcaro" + __author_mail__ = "vuolter@gmail.com" + + OFFLINE_PATTERN = ">Unfortunately, the link you are looking for is not found" + + def getLinks(self): + # Direct link with redirect + if not re.match(r"http://(?:www\.)?dl-protect\.com", self.req.http.lastEffectiveURL): + return [self.req.http.lastEffectiveURL] + + #id = re.match(self.__pattern__, self.pyfile.url).group("ID") + key = re.search(r'name="id_key" value="(.+?)"', self.html).group(1) + + post_req = {"id_key": key, "submitform": ""} + + if self.OFFLINE_PATTERN in self.html: + self.offline() + elif ">Please click on continue to see the content" in self.html: + post_req.update({"submitform": "Continue"}) + else: + mstime = int(round(time() * 1000)) + b64time = "_" + urlsafe_b64encode(str(mstime)).replace("=", "%3D") + + post_req.update({"i": b64time, "submitform": "Decrypt+link"}) + + if ">Password :" in self.html: + post_req["pwd"] = self.getPassword() + + if ">Security Code" in self.html: + captcha_id = re.search(r'/captcha\.php\?uid=(.+?)"', self.html).group(1) + captcha_url = "http://www.dl-protect.com/captcha.php?uid=" + captcha_id + captcha_code = self.decryptCaptcha(captcha_url, imgtype="gif") + + post_req["secure"] = captcha_code + + self.html = self.load(self.pyfile.url, post=post_req) + + for errmsg in (">The password is incorrect", ">The security code is incorrect"): + if errmsg in self.html: + self.fail(errmsg[1:]) + + pattern = r'<a href="([^/].+?)" target="_blank">' + return re.findall(pattern, self.html) From b22047eebc3e4b54e7d5f4254718d71cd20349ee Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Sat, 8 Mar 2014 14:22:38 +0100 Subject: [PATCH 0038/3774] Zippyshare: fixed #537 + new test link + cleanup --- module/plugins/hoster/ZippyshareCom.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index e4f2befa01..790dab6c4e 100644 --- a/module/plugins/hoster/ZippyshareCom.py +++ b/module/plugins/hoster/ZippyshareCom.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- # Test links (random.bin): -# http://www29.zippyshare.com/v/55578602/file.html +# http://www8.zippyshare.com/v/3120421/file.html import re import subprocess @@ -18,7 +17,7 @@ class ZippyshareCom(SimpleHoster): __name__ = "ZippyshareCom" __type__ = "hoster" __pattern__ = r"(?P<HOST>http://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(?P<KEY>\d+)" - __version__ = "0.42" + __version__ = "0.43" __description__ = """Zippyshare.com Download Hoster""" __author_name__ = ("spoob", "zoidberg", "stickell") __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -31,7 +30,7 @@ class ZippyshareCom(SimpleHoster): SH_COOKIES = [('zippyshare.com', 'ziplocale', 'en')] - DOWNLOAD_URL_PATTERN = r"<script type=\"text/javascript\">([^<]*?)(document\.getElementById\('dlbutton'\).href = [^;]+;)" + DOWNLOAD_URL_PATTERN = r"<script type=\"text/javascript\">([^<]*?)(document\.getElementById\('dlbutton'\).href\s*=\s*[^;]+;)" SEED_PATTERN = r'swfobject.embedSWF\("([^"]+)".*?seed: (\d+)' CAPTCHA_KEY_PATTERN = r'Recaptcha.create\("([^"]+)"' CAPTCHA_SHORTENCODE_PATTERN = r"shortencode: '([^']+)'" @@ -66,8 +65,6 @@ def handleFree(self): def get_file_url(self): """ returns the absolute downloadable filepath """ - url = None - found = re.search(self.DOWNLOAD_URL_PATTERN, self.html, re.S) #Method #1: JS eval if found and re.search(r'span id="omg" class="(\d*)"', self.html): @@ -84,7 +81,8 @@ def get_file_url(self): omg = re.search(regex + r" = ([^;]+);", js).group(1) js = re.sub(regex + r" = ([^;]+);", '', js) js = re.sub(regex, omg, js) - js = re.sub(r"document.getElementById\(\\*'dlbutton\\*'\).href = ", '', js) + js = re.sub(r"document.getElementById\(\\*'dlbutton\\*'\).href\s*= ", '', js) + js = re.sub(r"function someFunction\(\) {", '', js) url = self.js.eval(js) elif found and re.search(r"document.getElementById\(\\*'dlbutton\\*'\).href = \"", self.html): js = "\n".join(found.groups()) @@ -210,7 +208,7 @@ def do_recaptcha(self): 'response': code, 'shortencode': shortencode})) self.logDebug("reCaptcha response : %s" % response) - if response == True: + if response: self.correctCaptcha() break else: From 948fa0dfe8bb04766287b626e67826323c92a76a Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Sat, 8 Mar 2014 22:13:44 +0100 Subject: [PATCH 0039/3774] Hoster: UptoboxCom: Fixed --- module/plugins/hoster/UptoboxCom.py | 36 ++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/module/plugins/hoster/UptoboxCom.py b/module/plugins/hoster/UptoboxCom.py index 420610ee40..4568526cb6 100644 --- a/module/plugins/hoster/UptoboxCom.py +++ b/module/plugins/hoster/UptoboxCom.py @@ -1,19 +1,43 @@ # -*- coding: utf-8 -*- + +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# @author: Walter Purcaro +############################################################################### + from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo class UptoboxCom(XFileSharingPro): __name__ = "UptoboxCom" __type__ = "hoster" - __pattern__ = r"http://(?:\w*\.)*?uptobox.com/\w{12}" - __version__ = "0.07" + __pattern__ = r'https?://(?:www\.)?uptobox\.com/\w+' + __version__ = "0.08" __description__ = """Uptobox.com hoster plugin""" - __author_name__ = ("zoidberg") - __author_mail__ = ("zoidberg@mujmail.cz") + __author_name__ = "Walter Purcaro" + __author_mail__ = "vuolter@gmail.com" - FILE_INFO_PATTERN = r'<div class="para_title">(?P<N>.+) \((?P<S>[^)]+)\)</div>' - FILE_OFFLINE_PATTERN = r'<center>File Not Found</center>' HOSTER_NAME = "uptobox.com" + FILE_INFO_PATTERN = r'"para_title">(?P<N>.+) \((?P<S>[\d\.]+) (?P<U>\w+)\)' + FILE_OFFLINE_PATTERN = r'>(File not found|Access Denied|404 Not Found)' + TEMP_OFFLINE_PATTERN = r'>This server is in maintenance mode' + + WAIT_PATTERN = r'>(\d+)</span> seconds<' + + DIRECT_LINK_PATTERN = r'"(https?://\w+\.uptobox\.com/d/.*?)"' + getInfo = create_getInfo(UptoboxCom) From dcb1e6799f9eb0f372abf93a253e37678e6658ae Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Wed, 12 Mar 2014 17:06:45 +0100 Subject: [PATCH 0040/3774] LoadTo: fixed #523 --- module/plugins/hoster/LoadTo.py | 99 +++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/module/plugins/hoster/LoadTo.py b/module/plugins/hoster/LoadTo.py index 0f99c272a2..d1c1eb0f88 100644 --- a/module/plugins/hoster/LoadTo.py +++ b/module/plugins/hoster/LoadTo.py @@ -1,61 +1,90 @@ # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: halfman -""" +############################################################################ +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU Affero General Public License as # +# published by the Free Software Foundation, either version 3 of the # +# License, or (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU Affero General Public License for more details. # +# # +# You should have received a copy of the GNU Affero General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +############################################################################ # Test links (random.bin): -# http://www.load.to/dNsmgXRk4/random.bin -# http://www.load.to/edbNTxcUb/random100.bin +# http://www.load.to/JWydcofUY6/random.bin +# http://www.load.to/oeSmrfkXE/random100.bin import re + from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha class LoadTo(SimpleHoster): __name__ = "LoadTo" __type__ = "hoster" __pattern__ = r"http://(?:www\.)?load\.to/\w+" - __version__ = "0.12" + __version__ = "0.13" __description__ = """Load.to hoster plugin""" __author_name__ = ("halfman", "stickell") __author_mail__ = ("Pulpan3@gmail.com", "l.stickell@yahoo.it") - FILE_INFO_PATTERN = r'<a [^>]+>(?P<N>.+)</a></h3>\s*Size: (?P<S>\d+) Bytes' + FILE_INFO_PATTERN = r'<a [^>]+>(?P<N>.+)</a></h3>\s*Size: (?P<S>\d+) (?P<U>[kKmMgG]?i?[bB])' URL_PATTERN = r'<form method="post" action="(.+?)"' - FILE_OFFLINE_PATTERN = r'Can\'t find file. Please check URL.<br />' + FILE_OFFLINE_PATTERN = r'Can\'t find file. Please check URL.' WAIT_PATTERN = r'type="submit" value="Download \((\d+)\)"' + RECAPTCHA_PATTERN = r'http://www.google.com/recaptcha/api/challenge' + RECAPTCHA_KEY = "6Lc34eISAAAAAKNbPVyxBgNriTjPRmF-FA1oxApG" def setup(self): - self.multiDL = False + self.multiDL = True + self.chunkLimit = 1 def process(self, pyfile): - self.html = self.load(pyfile.url, decode=True) - - found = re.search(self.URL_PATTERN, self.html) - if not found: - self.parseError('URL') - download_url = found.group(1) - - timmy = re.search(self.WAIT_PATTERN, self.html) - if timmy: - self.setWait(timmy.group(1)) - self.wait() - - self.download(download_url, disposition=True) + self.getFileInfo() + + # Check if File is online + if re.search(self.FILE_OFFLINE_PATTERN, self.html): + self.offline() + + # Search for Download URL + m = re.search(self.URL_PATTERN, self.html) + if not m: + self.parseError('Unable to detect download URL') + download_url = m.group(1) + + # Set Timer - may be obsolete + m = re.search(self.WAIT_PATTERN, self.html) + if m: + self.wait(m.group(1)) + + # Check if reCaptcha is present + m = re.search(self.RECAPTCHA_PATTERN, self.html) + if not m: # No captcha found + self.download(download_url) + else: + recaptcha = ReCaptcha(self) + for _ in xrange(5): + challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) + if not response == '0': + break + else: + self.fail("No valid captcha solution received") + + self.download(download_url, + post={'recaptcha_challenge_field': challenge, 'recaptcha_response_field': response}) + + # Verifiy reCaptcha by checking content of file for html 404-error + check = self.checkDownload({"404": re.compile("\A<h1>404 Not Found</h1>")}) + if check == "404": + self.logWarning("The captcha you entered was incorrect. Please try again.") + self.invalidCaptcha() + self.retry() getInfo = create_getInfo(LoadTo) From 815a940789f3d689fbc00f5a82fe7712ecd33b02 Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Wed, 12 Mar 2014 17:15:53 +0100 Subject: [PATCH 0041/3774] XFileSharingPro: ability to use FILE_URL_REPLACEMENTS + improved FILE_OFFLINE_PATTERN + trivial fixes --- module/plugins/hoster/XFileSharingPro.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py index 5b167c3c96..6dec8e02a7 100644 --- a/module/plugins/hoster/XFileSharingPro.py +++ b/module/plugins/hoster/XFileSharingPro.py @@ -21,7 +21,7 @@ from urllib import unquote from urlparse import urlparse from pycurl import FOLLOWLOCATION, LOW_SPEED_TIME -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError, replace_patterns from module.plugins.internal.CaptchaService import ReCaptcha, SolveMedia from module.utils import html_unescape from module.network.RequestFactory import getURL @@ -36,7 +36,7 @@ class XFileSharingPro(SimpleHoster): __name__ = "XFileSharingPro" __type__ = "hoster" __pattern__ = r"^unmatchable$" - __version__ = "0.25" + __version__ = "0.26" __description__ = """XFileSharingPro common hoster base""" __author_name__ = ("zoidberg", "stickell") __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -44,10 +44,10 @@ class XFileSharingPro(SimpleHoster): FILE_NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>[^"]+)"' FILE_SIZE_PATTERN = r'You have requested <font color="red">[^<]+</font> \((?P<S>[^<]+)\)</font>' FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>' - FILE_OFFLINE_PATTERN = r'<(b|h[1-6])>File Not Found</(b|h[1-6])>|This file has been removed' + FILE_OFFLINE_PATTERN = r'>\w+ (Not Found|file (was|has been) removed)' WAIT_PATTERN = r'<span id="countdown_str">.*?>(\d+)</span>' - LONG_WAIT_PATTERN = r'(?P<H>\d+(?=\s*hour))?.*?(?P<M>\d+(?=\s*minute))?.*?(?P<S>\d+(?=\s*second))?' + #LONG_WAIT_PATTERN = r'(?P<H>\d+(?=\s*hour))?.*?(?P<M>\d+(?=\s*minute))?.*?(?P<S>\d+(?=\s*second))?' OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)' OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)' CAPTCHA_URL_PATTERN = r'(http://[^"\']+?/captchas?/[^"\']+)' @@ -68,7 +68,9 @@ def setup(self): def process(self, pyfile): self.prepare() - if not re.match(self.__pattern__, self.pyfile.url): + pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS) + + if not re.match(self.__pattern__, pyfile.url): if self.premium: self.handleOverriden() else: @@ -128,7 +130,7 @@ def handleFree(self): self.startDownload(url) def getDownloadLink(self): - for i in range(5): + for i in xrange(5): self.logDebug("Getting download link: #%d" % i) data = self.getPostParameters() @@ -238,7 +240,7 @@ def checkErrors(self): return self.errmsg def getPostParameters(self): - for _ in range(3): + for _ in xrange(3): if not self.errmsg: self.checkErrors() From 0cfb0bd904b83f79c69883ccec280230f6e955e0 Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Wed, 12 Mar 2014 17:20:46 +0100 Subject: [PATCH 0042/3774] New hoster: FileomCom Merged #539 Fixes #532 --- module/plugins/hoster/FileomCom.py | 53 ++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 module/plugins/hoster/FileomCom.py diff --git a/module/plugins/hoster/FileomCom.py b/module/plugins/hoster/FileomCom.py new file mode 100644 index 0000000000..3cf9bb4c1b --- /dev/null +++ b/module/plugins/hoster/FileomCom.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- + +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# @author: Walter Purcaro +############################################################################### + +# Test links (random.bin): +# http://fileom.com/gycaytyzdw3g/random.bin.html + +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class FileomCom(XFileSharingPro): + __name__ = "FileomCom" + __type__ = "hoster" + __pattern__ = r'https?://(?:www\.)?fileom\.com/\w+' + __version__ = "0.01" + __description__ = """Fileom.com hoster plugin""" + __author_name__ = "Walter Purcaro" + __author_mail__ = "vuolter@gmail.com" + + HOSTER_NAME = "fileom.com" + + FILE_URL_REPLACEMENTS = [(r'/$', "")] + SH_COOKIES = [(".fileom.com", "lang", "english")] + + FILE_NAME_PATTERN = r'Filename: <span>(?P<N>.+?)<' + FILE_SIZE_PATTERN = r'File Size: <span class="size">(?P<S>[\d\.]+) (?P<U>\w+)' + + ERROR_PATTERN = r'class=["\']err["\'][^>]*>(.*?)(?:\'|</)' + + DIRECT_LINK_PATTERN = r"var url2 = '(.+?)';" + + def setup(self): + self.resumeDownload = self.premium + self.multiDL = True + self.chunkLimit = 1 + + +getInfo = create_getInfo(FileomCom) From 853e79074ea21cf31f46c23e4cef45609b19483f Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Wed, 12 Mar 2014 17:29:24 +0100 Subject: [PATCH 0043/3774] FastshareCz: Fixed #521 Merged #529 --- module/plugins/hoster/FastshareCz.py | 95 ++++++++++++++++------------ 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/module/plugins/hoster/FastshareCz.py b/module/plugins/hoster/FastshareCz.py index fba7041232..93fbad6be9 100644 --- a/module/plugins/hoster/FastshareCz.py +++ b/module/plugins/hoster/FastshareCz.py @@ -1,55 +1,63 @@ # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: zoidberg -""" +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# @author: zoidberg +############################################################################### # Test links (random.bin): # http://www.fastshare.cz/2141189/random.bin import re +from urlparse import urljoin + from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FastshareCz(SimpleHoster): __name__ = "FastshareCz" __type__ = "hoster" - __pattern__ = r"http://(?:\w*\.)?fastshare.cz/\d+/.+" - __version__ = "0.21" - __description__ = """FastShare.cz""" - __author_name__ = ("zoidberg", "stickell") + __pattern__ = r'http://(?:www\.)?fastshare\.cz/\d+/.+' + __version__ = "0.22" + __description__ = """FastShare.cz hoster plugin""" + __author_name__ = ("zoidberg", "stickell", "Walter Purcaro") + __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it", "vuolter@gmail.com") + + FILE_INFO_PATTERN = r'<h1 class="dwp">(?P<N>[^<]+)</h1>\s*<div class="fileinfo">\s*Size\s*: (?P<S>\d+) (?P<U>\w+),' + FILE_OFFLINE_PATTERN = '>(The file has been deleted|Requested page not found)' - FILE_INFO_PATTERN = r'<h1 class="dwp">(?P<N>[^<]+)</h1>\s*<div class="fileinfo">\s*(?:Velikost|Size)\s*: (?P<S>[^,]+),' - FILE_OFFLINE_PATTERN = '(?:The file ?has been deleted|Requested page not found)' - FILE_URL_REPLACEMENTS = [('#.*', '')] - SH_COOKIES = [('fastshare.cz', 'lang', 'en')] + FILE_URL_REPLACEMENTS = [("#.*", "")] + SH_COOKIES = [(".fastshare.cz", "lang", "en")] FREE_URL_PATTERN = r'action=(/free/.*?)>\s*<img src="([^"]*)"><br' - PREMIUM_URL_PATTERN = r'(http://data\d+\.fastshare\.cz/download\.php\?id=\d+\&[^\s\"\'<>]+)' - NOT_ENOUGH_CREDIC_PATTERN = "Nem.te dostate.n. kredit pro sta.en. tohoto souboru" + PREMIUM_URL_PATTERN = r'(http://data\d+\.fastshare\.cz/download\.php\?id=\d+&)' + CREDIT_PATTERN = " credit for " def handleFree(self): - if '100% of FREE slots are full' in self.html: + if "> 100% of FREE slots are full" in self.html: self.retry(120, 60, "No free slots") found = re.search(self.FREE_URL_PATTERN, self.html) - if not found: + if found: + action, captcha_src = found.groups() + else: self.parseError("Free URL") - action, captcha_src = found.groups() - captcha = self.decryptCaptcha("http://www.fastshare.cz" + captcha_src) - self.download("http://www.fastshare.cz" + action, post={"code": captcha, "btn.x": 77, "btn.y": 18}) + + baseurl = "http://www.fastshare.cz" + captcha = self.decryptCaptcha(urljoin(baseurl, captcha_src)) + self.download(urljoin(baseurl, action), post={"code": captcha, "btn.x": 77, "btn.y": 18}) check = self.checkDownload({ "paralell_dl": @@ -64,24 +72,27 @@ def handleFree(self): def handlePremium(self): header = self.load(self.pyfile.url, just_header=True) - if 'location' in header: - url = header['location'] + if "location" in header: + url = header["location"] else: self.html = self.load(self.pyfile.url) - self.getFileInfo() - if self.NOT_ENOUGH_CREDIC_PATTERN in self.html: - self.logWarning('Not enough traffic left') - self.resetAccount() - found = re.search(self.PREMIUM_URL_PATTERN, self.html) - if not found: - self.parseError("Premium URL") - url = found.group(1) + self.getFileInfo() # - self.logDebug("PREMIUM URL: %s" % url) + if self.CREDIT_PATTERN in self.html: + self.logWarning("Not enough traffic left") + self.resetAccount() + else: + found = re.search(self.PREMIUM_URL_PATTERN, self.html) + if found: + url = found.group(1) + else: + self.parseError("Premium URL") + + self.logDebug("PREMIUM URL: " + url) self.download(url, disposition=True) - check = self.checkDownload({"credit": re.compile(self.NOT_ENOUGH_CREDIC_PATTERN)}) + check = self.checkDownload({"credit": re.compile(self.CREDIT_PATTERN)}) if check == "credit": self.resetAccount() From c694583c40dc95799d79035ba19a7bac15702f7a Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Wed, 12 Mar 2014 18:13:42 +0100 Subject: [PATCH 0044/3774] New crypter: TusfilesNetFolder Merges #520 --- module/plugins/crypter/TusfilesNetFolder.py | 54 +++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 module/plugins/crypter/TusfilesNetFolder.py diff --git a/module/plugins/crypter/TusfilesNetFolder.py b/module/plugins/crypter/TusfilesNetFolder.py new file mode 100644 index 0000000000..f364aabe73 --- /dev/null +++ b/module/plugins/crypter/TusfilesNetFolder.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# @author: Walter Purcaro +############################################################################### + +import math +import re +from urlparse import urljoin + +from module.plugins.internal.SimpleCrypter import SimpleCrypter + + +class TusfilesNetFolder(SimpleCrypter): + __name__ = "TusfilesNetFolder" + __type__ = "crypter" + __pattern__ = r'https?://(?:www\.)?tusfiles\.net/go/(?P<ID>\w+)/?' + __version__ = "0.01" + __description__ = """Tusfiles.net folder decrypter plugin""" + __author_name__ = ("Walter Purcaro", "stickell") + __author_mail__ = ("vuolter@gmail.com", "l.stickell@yahoo.it") + + LINK_PATTERN = r'<TD align=left><a href="(.*?)">' + TITLE_PATTERN = r'<Title>.*?\: (?P<title>.+) folder' + PAGES_PATTERN = r'>\((?P\d+) \w+\)<' + + FILE_URL_REPLACEMENTS = [(__pattern__, r'https://www.tusfiles.net/go/\g/')] + + def loadPage(self, page_n): + return self.load(urljoin(self.pyfile.url, str(page_n)), decode=True) + + def handleMultiPages(self): + pages = re.search(self.PAGES_PATTERN, self.html) + if pages: + pages = int(math.ceil(int(pages.group('pages')) / 25.0)) + else: + return + + for p in xrange(2, pages + 1): + self.html = self.loadPage(p) + self.package_links += self.getLinks() From 472c2e44ecfabafb77609bab5613f6757baa52cb Mon Sep 17 00:00:00 2001 From: Stefano Date: Fri, 14 Mar 2014 11:21:41 +0100 Subject: [PATCH 0045/3774] Zippyshare: fixed #542 Thanks @gaberad --- module/plugins/hoster/ZippyshareCom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index 790dab6c4e..2df59c58f7 100644 --- a/module/plugins/hoster/ZippyshareCom.py +++ b/module/plugins/hoster/ZippyshareCom.py @@ -17,7 +17,7 @@ class ZippyshareCom(SimpleHoster): __name__ = "ZippyshareCom" __type__ = "hoster" __pattern__ = r"(?Phttp://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(?P\d+)" - __version__ = "0.43" + __version__ = "0.44" __description__ = """Zippyshare.com Download Hoster""" __author_name__ = ("spoob", "zoidberg", "stickell") __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -82,7 +82,7 @@ def get_file_url(self): js = re.sub(regex + r" = ([^;]+);", '', js) js = re.sub(regex, omg, js) js = re.sub(r"document.getElementById\(\\*'dlbutton\\*'\).href\s*= ", '', js) - js = re.sub(r"function someFunction\(\) {", '', js) + js = re.sub(r"function som(e|d)Function\(\) {", '', js) url = self.js.eval(js) elif found and re.search(r"document.getElementById\(\\*'dlbutton\\*'\).href = \"", self.html): js = "\n".join(found.groups()) From 94d3ffda1f90327f41b8f77bb15d099e95410b6a Mon Sep 17 00:00:00 2001 From: CrazYoshi Date: Tue, 18 Mar 2014 13:49:55 +0100 Subject: [PATCH 0046/3774] Easybytez registered user seen as premium account Now registered users are not seen as premium anymore. validuntil date and trafficleft criteria changed. --- module/plugins/accounts/EasybytezCom.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/module/plugins/accounts/EasybytezCom.py b/module/plugins/accounts/EasybytezCom.py index 72f37b6992..93a221615b 100644 --- a/module/plugins/accounts/EasybytezCom.py +++ b/module/plugins/accounts/EasybytezCom.py @@ -18,7 +18,7 @@ """ import re -from time import mktime, strptime +from time import mktime, strptime, gmtime from module.plugins.Account import Account from module.plugins.internal.SimpleHoster import parseHtmlForm @@ -27,7 +27,7 @@ class EasybytezCom(Account): __name__ = "EasybytezCom" - __version__ = "0.03" + __version__ = "0.04" __type__ = "account" __description__ = """EasyBytez.com account plugin""" __author_name__ = ("zoidberg") @@ -44,19 +44,19 @@ def loadAccountInfo(self, user, req): found = re.search(self.VALID_UNTIL_PATTERN, html) if found: - premium = True - trafficleft = -1 try: self.logDebug("Expire date: " + found.group(1)) validuntil = mktime(strptime(found.group(1), "%d %B %Y")) except Exception, e: self.logError(e) + if validuntil>mktime(gmtime()): + premium = True + trafficleft = -1 else: found = re.search(self.TRAFFIC_LEFT_PATTERN, html) if found: trafficleft = found.group(1) if "Unlimited" in trafficleft: - premium = True trafficleft = -1 else: trafficleft = parseFileSize(trafficleft) / 1024 From 229046d95d5ee4021a4b470347d43669a5efc70f Mon Sep 17 00:00:00 2001 From: CrazYoshi Date: Wed, 19 Mar 2014 11:49:42 +0100 Subject: [PATCH 0047/3774] Add space between args on operator > Add space between args on operator > --- module/plugins/accounts/EasybytezCom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/plugins/accounts/EasybytezCom.py b/module/plugins/accounts/EasybytezCom.py index 93a221615b..ffd132ba36 100644 --- a/module/plugins/accounts/EasybytezCom.py +++ b/module/plugins/accounts/EasybytezCom.py @@ -49,7 +49,7 @@ def loadAccountInfo(self, user, req): validuntil = mktime(strptime(found.group(1), "%d %B %Y")) except Exception, e: self.logError(e) - if validuntil>mktime(gmtime()): + if validuntil > mktime(gmtime()): premium = True trafficleft = -1 else: From 900994bdb2062f547baa7be7c5dc5f93e1927111 Mon Sep 17 00:00:00 2001 From: Stefano Date: Wed, 19 Mar 2014 14:45:22 +0100 Subject: [PATCH 0048/3774] Zippyshare: Fixed #545 Thanks @gaberad --- module/plugins/hoster/ZippyshareCom.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index 2df59c58f7..221db71048 100644 --- a/module/plugins/hoster/ZippyshareCom.py +++ b/module/plugins/hoster/ZippyshareCom.py @@ -17,7 +17,7 @@ class ZippyshareCom(SimpleHoster): __name__ = "ZippyshareCom" __type__ = "hoster" __pattern__ = r"(?Phttp://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(?P\d+)" - __version__ = "0.44" + __version__ = "0.45" __description__ = """Zippyshare.com Download Hoster""" __author_name__ = ("spoob", "zoidberg", "stickell") __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -82,7 +82,8 @@ def get_file_url(self): js = re.sub(regex + r" = ([^;]+);", '', js) js = re.sub(regex, omg, js) js = re.sub(r"document.getElementById\(\\*'dlbutton\\*'\).href\s*= ", '', js) - js = re.sub(r"function som(e|d)Function\(\) {", '', js) + js = re.sub(r"(function som(e|d)Function\(\) {)|(var som(e|d)function = function\(\) {)", + '', js, flags=re.I) url = self.js.eval(js) elif found and re.search(r"document.getElementById\(\\*'dlbutton\\*'\).href = \"", self.html): js = "\n".join(found.groups()) From 2450d9c687193d64bbe028640b77af9ae011d64e Mon Sep 17 00:00:00 2001 From: Thierry Merle Date: Wed, 19 Mar 2014 14:57:02 +0100 Subject: [PATCH 0049/3774] OneFichier: Fixed #536 Merges #541 --- module/plugins/hoster/OneFichierCom.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py index 54bf1d1fa6..9fa0a4b906 100644 --- a/module/plugins/hoster/OneFichierCom.py +++ b/module/plugins/hoster/OneFichierCom.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +# Test links (random.bin): +# http://5pnm24ltcw.1fichier.com/ + import re from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo @@ -8,17 +11,17 @@ class OneFichierCom(SimpleHoster): __name__ = "OneFichierCom" __type__ = "hoster" __pattern__ = r"(http://(\w+)\.((1fichier|d(es)?fichiers|pjointe)\.(com|fr|net|org)|(cjoint|mesfichiers|piecejointe|oi)\.(org|net)|tenvoi\.(com|org|net)|dl4free\.com|alterupload\.com|megadl.fr))" - __version__ = "0.48" + __version__ = "0.49" __description__ = """1fichier.com download hoster""" __author_name__ = ("fragonib", "the-razer", "zoidberg", "imclem") __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "daniel_ AT gmx DOT net", "zoidberg@mujmail.cz", "imclem on github") - FILE_NAME_PATTERN = r'">File name :\s*(?P[^<]+)' - FILE_SIZE_PATTERN = r'File size :\s*(?P[^<]+)' + FILE_NAME_PATTERN = r'">Filename :\s*(?P[^<]+)' + FILE_SIZE_PATTERN = r'Size :\s*(?P[^<]+)' FILE_OFFLINE_PATTERN = r'The (requested)? file (could not be found|has been deleted)' FILE_URL_REPLACEMENTS = [(r'(http://[^/]*).*', r'\1/en/')] - DOWNLOAD_LINK_PATTERN = r'
 
 
 \s+http://.*?)'""" PASSWORD_PROTECTED_TOKEN = "protected by password" WAITING_PATTERN = "Warning ! Without premium status, you can download only one file at a time and you must wait up to (\d+) minutes between each downloads." @@ -26,7 +29,7 @@ def process(self, pyfile): found = re.search(self.__pattern__, pyfile.url) file_id = found.group(2) url = "http://%s.%s/en/" % (found.group(2), found.group(3)) - self.html = self.load(url, decode=True) + self.html = self.load(url, post="submit", decode=True) found = re.search(self.WAITING_PATTERN, self.html) if found: @@ -42,7 +45,13 @@ def process(self, pyfile): if "pass" in inputs: inputs['pass'] = self.getPassword() - self.download(url, post=inputs) + self.html = self.load(url, post=inputs) + m = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) + if not m: + self.parseError("Unable to detect download link") + download_url = m.group(1) + + self.download(download_url) # Check download self.checkDownloadedFile() From b893d603e3fbefa6f27825b4758b49a1475906e1 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 19 Mar 2014 15:00:38 +0100 Subject: [PATCH 0050/3774] Rapidgator: Pattern updated Fixed #513 Merges #514 --- module/plugins/hoster/RapidgatorNet.py | 154 +++++++++++++------------ 1 file changed, 80 insertions(+), 74 deletions(-) diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py index 611d2ba5dd..4229b2aa12 100644 --- a/module/plugins/hoster/RapidgatorNet.py +++ b/module/plugins/hoster/RapidgatorNet.py @@ -1,52 +1,58 @@ # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . - - @author: zoidberg -""" +############################################################################### +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# @author: zoidberg +############################################################################### import re from pycurl import HTTPHEADER -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from module.plugins.internal.CaptchaService import ReCaptcha, SolveMedia, AdsCaptcha from module.common.json_layer import json_loads from module.network.HTTPRequest import BadHeader +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha, SolveMedia, AdsCaptcha class RapidgatorNet(SimpleHoster): __name__ = "RapidgatorNet" __type__ = "hoster" - __pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\w+)" - __version__ = "0.19" - __description__ = """rapidgator.net""" - __author_name__ = ("zoidberg", "chrox", "stickell") + __pattern__ = r"http://(?:www\.)?rapidgator\.net/file/\w+" + __version__ = "0.20" + __description__ = """Rapidgator.net hoster plugin""" + __author_name__ = ("zoidberg", "chrox", "stickell", "Walter Purcaro") + __author_mail__ = ("zoidberg@mujmail.cz", "", "l.stickell@yahoo.it", "vuolter@gmail.com") API_URL = 'http://rapidgator.net/api/file' - FILE_NAME_PATTERN = r'Downloading:(?:\s*<[^>]*>)*\s*(?P.*?)(?:\s*<[^>]*>)' - FILE_SIZE_PATTERN = r'File size:\s*(?P.*?)' - FILE_OFFLINE_PATTERN = r'File not found' + FILE_NAME_PATTERN = r'Download file (?P<N>.*)' + FILE_SIZE_PATTERN = r'File size:\s*(?P[\d\.]+) (?P\w+)' + FILE_OFFLINE_PATTERN = r'>(File not found|Error 404)' JSVARS_PATTERN = r"\s+var\s*(startTimerUrl|getDownloadUrl|captchaUrl|fid|secs)\s*=\s*'?(.*?)'?;" - DOWNLOAD_LINK_PATTERN = r"return '(http[^']+)';\s*}\s*}\s*}?\);" - RECAPTCHA_KEY_PATTERN = r'"http://api.recaptcha.net/challenge?k=(.*?)"' - ADSCAPTCHA_SRC_PATTERN = r'(http://api.adscaptcha.com/Get.aspx[^"\']*)' - SOLVEMEDIA_PATTERN = r'http:\/\/api\.solvemedia\.com\/papi\/challenge\.script\?k=(.*?)"' + PREMIUM_ONLY_ERROR_PATTERN = r'You can download files up to|This file can be downloaded by premium only<' + DOWNLOAD_LIMIT_ERROR_PATTERN = r'You have reached your (daily|hourly) downloads limit' + WAIT_PATTERN = r'(?:Delay between downloads must be not less than|Try again in)\s*(\d+)\s*(hour|min)' + DOWNLOAD_LINK_PATTERN = r"return '(http://\w+.rapidgator.net/.*)';" + + RECAPTCHA_KEY_PATTERN = r'"http://api\.recaptcha\.net/challenge\?k=(.*?)"' + ADSCAPTCHA_SRC_PATTERN = r'(http://api\.adscaptcha\.com/Get\.aspx[^"\']*)' + SOLVEMEDIA_PATTERN = r'http://api\.solvemedia\.com/papi/challenge\.script\?k=(.*?)"' def setup(self): - self.resumeDownload = self.multiDL = False + self.resumeDownload = self.multiDL = self.premium self.sid = None self.chunkLimit = 1 self.req.setOption("timeout", 120) @@ -60,7 +66,7 @@ def process(self, pyfile): else: self.handleFree() - def getAPIResponse(self, cmd): + def api_response(self, cmd): try: json = self.load('%s/%s' % (self.API_URL, cmd), get={'sid': self.sid, @@ -85,23 +91,17 @@ def getAPIResponse(self, cmd): def handlePremium(self): #self.logDebug("ACCOUNT_DATA", self.account.getAccountData(self.user)) - self.api_data = self.getAPIResponse('info') + self.api_data = self.api_response('info') self.api_data['md5'] = self.api_data['hash'] self.pyfile.name = self.api_data['filename'] self.pyfile.size = self.api_data['size'] - url = self.getAPIResponse('download')['url'] - self.multiDL = True + url = self.api_response('download')['url'] self.download(url) def handleFree(self): self.html = self.load(self.pyfile.url, decode=True) - self.getFileInfo() - if ("You can download files up to 500 MB in free mode" in self.html or - "This file can be downloaded by premium only" in self.html): - self.fail("Premium account needed for download") - - self.checkWait() + self.checkFree() jsvars = dict(re.findall(self.JSVARS_PATTERN, self.html)) self.logDebug(jsvars) @@ -113,8 +113,7 @@ def handleFree(self): jsvars.get('startTimerUrl', '/download/AjaxStartTimer'), jsvars["fid"]) jsvars.update(self.getJsonResponse(url)) - self.setWait(int(jsvars.get('secs', 30)) + 1, False) - self.wait() + self.wait(int(jsvars.get('secs', 45)) + 1, False) url = "http://rapidgator.net%s?sid=%s" % ( jsvars.get('getDownloadUrl', '/download/AjaxGetDownload'), jsvars["sid"]) @@ -125,6 +124,32 @@ def handleFree(self): url = "http://rapidgator.net%s" % jsvars.get('captchaUrl', '/download/captcha') self.html = self.load(url) + + for _ in xrange(5): + found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) + if found: + link = found.group(1) + self.logDebug(link) + self.download(link, disposition=True) + break + else: + captcha, captcha_key = self.getCaptcha() + captcha_challenge, captcha_response = captcha.challenge(captcha_key) + + self.html = self.load(url, post={ + "DownloadCaptchaForm[captcha]": "", + "adcopy_challenge": captcha_challenge, + "adcopy_response": captcha_response + }) + + if "The verification code is incorrect" in self.html: + self.invalidCaptcha() + else: + self.correctCaptcha() + else: + self.parseError("Download link") + + def getCaptcha(self): found = re.search(self.ADSCAPTCHA_SRC_PATTERN, self.html) if found: captcha_key = found.group(1) @@ -134,7 +159,6 @@ def handleFree(self): if found: captcha_key = found.group(1) captcha = ReCaptcha(self) - else: found = re.search(self.SOLVEMEDIA_PATTERN, self.html) if found: @@ -143,47 +167,29 @@ def handleFree(self): else: self.parseError("Captcha") - for i in range(5): - self.checkWait() - captcha_challenge, captcha_response = captcha.challenge(captcha_key) - - self.html = self.load(url, post={ - "DownloadCaptchaForm[captcha]": "", - "adcopy_challenge": captcha_challenge, - "adcopy_response": captcha_response - }) + return captcha, captcha_key - if 'The verification code is incorrect' in self.html: - self.invalidCaptcha() - else: - self.correctCaptcha() - break + def checkFree(self): + found = re.search(self.PREMIUM_ONLY_ERROR_PATTERN, self.html) + if found: + self.fail("Premium account needed for download") else: - self.fail("No valid captcha solution received") - - found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) - if not found: - self.parseError("download link") - download_url = found.group(1) - self.logDebug(download_url) - self.download(download_url) - - def checkWait(self): - found = re.search(r"(?:Delay between downloads must be not less than|Try again in)\s*(\d+)\s*(hour|min)", - self.html) + found = re.search(self.WAIT_PATTERN, self.html) + if found: wait_time = int(found.group(1)) * {"hour": 60, "min": 1}[found.group(2)] else: - found = re.search(r"You have reached your (daily|hourly) downloads limit", self.html) - if found: + found = re.search(self.DOWNLOAD_LIMIT_ERROR_PATTERN, self.html) + if not found: + return + elif found.group(1) == "daily": wait_time = 60 else: - return + wait_time = 24 * 60 self.logDebug("Waiting %d minutes" % wait_time) - self.setWait(wait_time * 60, True) - self.wait() - self.retry(max_tries=24) + self.wait(wait_time * 60, True) + self.retry() def getJsonResponse(self, url): response = self.load(url, decode=True) From d1a4bc65f6d560b1a851c3359f6511a1e96025e3 Mon Sep 17 00:00:00 2001 From: m42e Date: Wed, 19 Mar 2014 15:04:39 +0100 Subject: [PATCH 0051/3774] ZDF: ignore series id, use progressive only, not hbbtv Merges #544 --- module/plugins/hoster/ZDF.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/module/plugins/hoster/ZDF.py b/module/plugins/hoster/ZDF.py index 9940fd078e..e45717186e 100644 --- a/module/plugins/hoster/ZDF.py +++ b/module/plugins/hoster/ZDF.py @@ -10,7 +10,7 @@ class ZDF(Hoster): # Based on zdfm by Roland Beermann # http://github.com/enkore/zdfm/ __name__ = "ZDF Mediathek" - __version__ = "0.7" + __version__ = "0.8" __pattern__ = r"http://www\.zdf\.de/ZDFmediathek/[^0-9]*([0-9]+)[^0-9]*" __config__ = [] @@ -23,11 +23,12 @@ def video_key(video): @staticmethod def video_valid(video): - return video.findtext("url").startswith("http") and video.findtext("url").endswith(".mp4") + return video.findtext("url").startswith("http") and video.findtext("url").endswith(".mp4") and \ + video.findtext("facets/facet").startswith("progressive") @staticmethod def get_id(url): - return int(re.search(r"[^0-9]*([0-9]+)[^0-9]*", url).group(1)) + return int(re.search(r"[^0-9]*([0-9]{4,})[^0-9]*", url).group(1)) def process(self, pyfile): xml = fromstring(self.load(XML_API % self.get_id(pyfile.url))) From 7c272fffe59683ed232be7f93648b5904cc58139 Mon Sep 17 00:00:00 2001 From: Stefano Date: Wed, 19 Mar 2014 15:30:43 +0100 Subject: [PATCH 0052/3774] Filestube: patterns updated Resolves #543 and #497 --- module/plugins/crypter/FilestubeCom.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/plugins/crypter/FilestubeCom.py b/module/plugins/crypter/FilestubeCom.py index 24e2ca1378..bb90e63b8a 100644 --- a/module/plugins/crypter/FilestubeCom.py +++ b/module/plugins/crypter/FilestubeCom.py @@ -22,10 +22,10 @@ class FilestubeCom(SimpleCrypter): __name__ = "FilestubeCom" __type__ = "crypter" __pattern__ = r"http://(?:w{3}.)?filestube\.(?:com|to)/\w+" - __version__ = "0.02" + __version__ = "0.03" __description__ = """Filestube.com Plugin""" __author_name__ = ("stickell") __author_mail__ = ("l.stickell@yahoo.it") - LINK_PATTERN = r"link_download'\]\); renderGo\('(http://[^)]+)'\);" - TITLE_PATTERN = r"(?P<title>.+) download" + LINK_PATTERN = r"<a class=\"file-link-main(?: noref)?\" [^>]* href=\"(http://[^\"]+)" + TITLE_PATTERN = r"<h1\s*> (?P<title>.+) download\s*</h1>" From e4da4c592779642a2ce1e2c361dd6d0fb7b62c1c Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Wed, 19 Mar 2014 15:40:24 +0100 Subject: [PATCH 0053/3774] Zippyshare: using (?i) instead of re.I to make it work even on Python < 2.7 --- module/plugins/hoster/ZippyshareCom.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index 221db71048..5983627d5d 100644 --- a/module/plugins/hoster/ZippyshareCom.py +++ b/module/plugins/hoster/ZippyshareCom.py @@ -17,7 +17,7 @@ class ZippyshareCom(SimpleHoster): __name__ = "ZippyshareCom" __type__ = "hoster" __pattern__ = r"(?P<HOST>http://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(?P<KEY>\d+)" - __version__ = "0.45" + __version__ = "0.46" __description__ = """Zippyshare.com Download Hoster""" __author_name__ = ("spoob", "zoidberg", "stickell") __author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -82,8 +82,7 @@ def get_file_url(self): js = re.sub(regex + r" = ([^;]+);", '', js) js = re.sub(regex, omg, js) js = re.sub(r"document.getElementById\(\\*'dlbutton\\*'\).href\s*= ", '', js) - js = re.sub(r"(function som(e|d)Function\(\) {)|(var som(e|d)function = function\(\) {)", - '', js, flags=re.I) + js = re.sub(r"(?i)(function som(e|d)Function\(\) {)|(var som(e|d)function = function\(\) {)", '', js) url = self.js.eval(js) elif found and re.search(r"document.getElementById\(\\*'dlbutton\\*'\).href = \"", self.html): js = "\n".join(found.groups()) From cece2a8ad7d1d10491e07c5494c897427e319017 Mon Sep 17 00:00:00 2001 From: flubshi <flubshi@web.de> Date: Thu, 20 Mar 2014 13:30:47 +0100 Subject: [PATCH 0054/3774] Add multihost plugin for free-way.me --- module/plugins/accounts/FreeWayMe.py | 67 ++++++++++++++++++++++++++++ module/plugins/hooks/FreeWayMe.py | 41 +++++++++++++++++ module/plugins/hoster/FreeWayMe.py | 48 ++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 module/plugins/accounts/FreeWayMe.py create mode 100644 module/plugins/hooks/FreeWayMe.py create mode 100644 module/plugins/hoster/FreeWayMe.py diff --git a/module/plugins/accounts/FreeWayMe.py b/module/plugins/accounts/FreeWayMe.py new file mode 100644 index 0000000000..ca895c4566 --- /dev/null +++ b/module/plugins/accounts/FreeWayMe.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: Nicolas Giese +""" + +from module.plugins.Account import Account +from module.common.json_layer import json_loads + + +class FreeWayMe(Account): + __name__ = "FreeWayMe" + __version__ = "0.11" + __type__ = "account" + __description__ = """FreeWayMe account plugin""" + __author_name__ = ("Nicolas Giese") + __author_mail__ = ("james@free-way.me") + + def loadAccountInfo(self, user, req): + status = self.getAccountStatus(user, req) + if status is False: + return False + self.logDebug(status) + + account_info = {"validuntil": -1, "premium": False} + if status["premium"] == "Free": + account_info["trafficleft"] = int(status["guthaben"])*1024 + elif status["premium"] == "Spender": + account_info["trafficleft"] = -1 + elif status["premium"] == "Flatrate": + account_info = {"validuntil": int(status["Flatrate"]), + "trafficleft": -1, + "premium": True} + + return account_info + + def getpw(self, user): + return self.accounts[user]["password"] + + def login(self, user, data, req): + status = self.getAccountStatus(user, req) + + # Check if user and password are valid + if status is False: + self.wrongPassword() + + def getAccountStatus(self, user, req): + answer = req.load("https://www.free-way.me/ajax/jd.php", + get={"id": 4, "user": user, "pass": self.accounts[user]["password"]}) + self.logDebug("login: %s" % answer) + if answer == "Invalid login": + self.wrongPassword() + return False + return json_loads(answer) diff --git a/module/plugins/hooks/FreeWayMe.py b/module/plugins/hooks/FreeWayMe.py new file mode 100644 index 0000000000..57de50d330 --- /dev/null +++ b/module/plugins/hooks/FreeWayMe.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: Nicolas Giese +""" + +from module.network.RequestFactory import getURL, getRequest +from module.plugins.internal.MultiHoster import MultiHoster + +class FreeWayMe(MultiHoster): + __name__ = "FreeWayMe" + __version__ = "0.11" + __type__ = "hook" + __description__ = """FreeWayMe hook plugin""" + __config__ = [("activated", "bool", "Activated", "False"), + ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported):", "all"), + ("hosterList", "str", "Hoster list (comma separated)", ""), + ("unloadFailing", "bool", "Revert to stanard download if download fails", "False"), + ("interval", "int", "Reload interval in hours (0 to disable)", "24")] + __author_name__ = ("Nicolas Giese") + __author_mail__ = ("james@free-way.me") + + def getHoster(self): + req = getRequest() + hostis = req.load("https://www.free-way.me/ajax/jd.php", get={"id": 3}).replace("\"", "").strip() + req.close() + self.logDebug("hosters: %s" % hostis) + return [x.strip() for x in hostis.split(",") if x.strip()] diff --git a/module/plugins/hoster/FreeWayMe.py b/module/plugins/hoster/FreeWayMe.py new file mode 100644 index 0000000000..5439c10c13 --- /dev/null +++ b/module/plugins/hoster/FreeWayMe.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: Nicolas Giese +""" + +from module.plugins.Hoster import Hoster + +class FreeWayMe(Hoster): + __name__ = "FreeWayMe" + __version__ = "0.11" + __type__ = "hoster" + __pattern__ = r"https://free-way.me/.*" + __description__ = """FreeWayMe hoster plugin""" + __author_name__ = ("Nicolas Giese") + __author_mail__ = ("james@free-way.me") + + def setup(self): + self.resumeDownload = False + self.chunkLimit = 1 + self.multiDL = self.premium + + def process(self, pyfile): + if not self.account: + self.logError(_("Please enter your %s account or deactivate this plugin") % "FreeWayMe") + self.fail("No FreeWay account provided") + + self.logDebug("Old URL: %s" % pyfile.url) + + (user, data) = self.account.selectAccount() + + self.download( + "https://www.free-way.me/load.php", + get={"multiget": 7, "url": pyfile.url, "user": user, "pw": self.account.getpw(user), "json": ""}, + disposition=True) From 3a8d1ab28eb9d9cd1cd8fadf7e88289e323e66dc Mon Sep 17 00:00:00 2001 From: flubshi <flubshi@web.de> Date: Thu, 20 Mar 2014 14:30:46 +0100 Subject: [PATCH 0055/3774] Improve free-way plugin (thanks stickell for your comments!) --- module/plugins/accounts/FreeWayMe.py | 4 ++-- module/plugins/hooks/FreeWayMe.py | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/module/plugins/accounts/FreeWayMe.py b/module/plugins/accounts/FreeWayMe.py index ca895c4566..087b380d9e 100644 --- a/module/plugins/accounts/FreeWayMe.py +++ b/module/plugins/accounts/FreeWayMe.py @@ -31,7 +31,7 @@ class FreeWayMe(Account): def loadAccountInfo(self, user, req): status = self.getAccountStatus(user, req) - if status is False: + if not status: return False self.logDebug(status) @@ -54,7 +54,7 @@ def login(self, user, data, req): status = self.getAccountStatus(user, req) # Check if user and password are valid - if status is False: + if not status: self.wrongPassword() def getAccountStatus(self, user, req): diff --git a/module/plugins/hooks/FreeWayMe.py b/module/plugins/hooks/FreeWayMe.py index 57de50d330..30d76cb8ed 100644 --- a/module/plugins/hooks/FreeWayMe.py +++ b/module/plugins/hooks/FreeWayMe.py @@ -17,7 +17,7 @@ @author: Nicolas Giese """ -from module.network.RequestFactory import getURL, getRequest +from module.network.RequestFactory import getURL from module.plugins.internal.MultiHoster import MultiHoster class FreeWayMe(MultiHoster): @@ -34,8 +34,6 @@ class FreeWayMe(MultiHoster): __author_mail__ = ("james@free-way.me") def getHoster(self): - req = getRequest() - hostis = req.load("https://www.free-way.me/ajax/jd.php", get={"id": 3}).replace("\"", "").strip() - req.close() + hostis = getURL("https://www.free-way.me/ajax/jd.php", get={"id": 3}).replace("\"", "").strip() self.logDebug("hosters: %s" % hostis) return [x.strip() for x in hostis.split(",") if x.strip()] From c7b8e5b668dafe6fa1eb474b35cf313361482eac Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Thu, 20 Mar 2014 17:14:07 +0100 Subject: [PATCH 0056/3774] Removed ARD from the repository --- module/plugins/hoster/ARD.py | 83 ------------------------------------ 1 file changed, 83 deletions(-) delete mode 100644 module/plugins/hoster/ARD.py diff --git a/module/plugins/hoster/ARD.py b/module/plugins/hoster/ARD.py deleted file mode 100644 index 12cb6c95a8..0000000000 --- a/module/plugins/hoster/ARD.py +++ /dev/null @@ -1,83 +0,0 @@ -import subprocess -import re -import os.path -import os - -from module.utils import save_join, save_path -from module.plugins.Hoster import Hoster - -# Requires rtmpdump -# by Roland Beermann - - -class RTMP: - # TODO: Port to some RTMP-library like rtmpy or similar - # TODO?: Integrate properly into the API of pyLoad - - command = "rtmpdump" - - @classmethod - def download_rtmp_stream(cls, url, output_file, playpath=None): - opts = [ - "-r", url, - "-o", output_file, - ] - if playpath: - opts.append("--playpath") - opts.append(playpath) - - cls._invoke_rtmpdump(opts) - - @classmethod - def _invoke_rtmpdump(cls, opts): - args = [ - cls.command - ] - args.extend(opts) - - return subprocess.check_call(args) - - -class ARD(Hoster): - __name__ = "ARD Mediathek" - __version__ = "0.12" - __pattern__ = r"http://www\.ardmediathek\.de/.*" - __config__ = [] - - def process(self, pyfile): - site = self.load(pyfile.url) - - avail_videos = re.findall( - r'mediaCollection.addMediaStream\(0, ([0-9]*), "([^\"]*)", "([^\"]*)", "[^\"]*"\);', site) - avail_videos.sort(key=lambda videodesc: int(videodesc[0]), - reverse=True) # The higher the number, the better the quality - - quality, url, playpath = avail_videos[0] - - pyfile.name = re.search(r"<h1>([^<]*)</h1>", site).group(1) - - if url.startswith("http"): - # Best quality is available over HTTP. Very rare. - self.download(url) - else: - pyfile.setStatus("downloading") - - download_folder = self.config['general']['download_folder'] - - location = save_join(download_folder, pyfile.package().folder) - - if not os.path.exists(location): - os.makedirs(location, int(self.config["permission"]["folder"], 8)) - - if self.config["permission"]["change_dl"] and os.name != "nt": - try: - uid = getpwnam(self.config["permission"]["user"])[2] - gid = getgrnam(self.config["permission"]["group"])[2] - - chown(location, uid, gid) - except Exception, e: - self.logWarning(_("Setting User and Group failed: %s") % str(e)) - - output_file = save_join(location, save_path(pyfile.name)) + os.path.splitext(playpath)[1] - - RTMP.download_rtmp_stream(url, playpath=playpath, output_file=output_file) From 6050e7443891c8433e906298838ffeb55d922fd6 Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Fri, 21 Mar 2014 15:14:06 +0100 Subject: [PATCH 0057/3774] FreeWayMe: cosmetics --- module/plugins/accounts/FreeWayMe.py | 134 +++++++++++++-------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/module/plugins/accounts/FreeWayMe.py b/module/plugins/accounts/FreeWayMe.py index 087b380d9e..0222ad65ff 100644 --- a/module/plugins/accounts/FreeWayMe.py +++ b/module/plugins/accounts/FreeWayMe.py @@ -1,67 +1,67 @@ -# -*- coding: utf-8 -*- - -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: Nicolas Giese -""" - -from module.plugins.Account import Account -from module.common.json_layer import json_loads - - -class FreeWayMe(Account): - __name__ = "FreeWayMe" - __version__ = "0.11" - __type__ = "account" - __description__ = """FreeWayMe account plugin""" - __author_name__ = ("Nicolas Giese") - __author_mail__ = ("james@free-way.me") - - def loadAccountInfo(self, user, req): - status = self.getAccountStatus(user, req) - if not status: - return False - self.logDebug(status) - - account_info = {"validuntil": -1, "premium": False} - if status["premium"] == "Free": - account_info["trafficleft"] = int(status["guthaben"])*1024 - elif status["premium"] == "Spender": - account_info["trafficleft"] = -1 - elif status["premium"] == "Flatrate": - account_info = {"validuntil": int(status["Flatrate"]), - "trafficleft": -1, - "premium": True} - - return account_info - - def getpw(self, user): - return self.accounts[user]["password"] - - def login(self, user, data, req): - status = self.getAccountStatus(user, req) - - # Check if user and password are valid - if not status: - self.wrongPassword() - - def getAccountStatus(self, user, req): - answer = req.load("https://www.free-way.me/ajax/jd.php", - get={"id": 4, "user": user, "pass": self.accounts[user]["password"]}) - self.logDebug("login: %s" % answer) - if answer == "Invalid login": - self.wrongPassword() - return False - return json_loads(answer) +# -*- coding: utf-8 -*- + +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <http://www.gnu.org/licenses/>. + + @author: Nicolas Giese +""" + +from module.plugins.Account import Account +from module.common.json_layer import json_loads + + +class FreeWayMe(Account): + __name__ = "FreeWayMe" + __version__ = "0.11" + __type__ = "account" + __description__ = """FreeWayMe account plugin""" + __author_name__ = ("Nicolas Giese") + __author_mail__ = ("james@free-way.me") + + def loadAccountInfo(self, user, req): + status = self.getAccountStatus(user, req) + if not status: + return False + self.logDebug(status) + + account_info = {"validuntil": -1, "premium": False} + if status["premium"] == "Free": + account_info["trafficleft"] = int(status["guthaben"]) * 1024 + elif status["premium"] == "Spender": + account_info["trafficleft"] = -1 + elif status["premium"] == "Flatrate": + account_info = {"validuntil": int(status["Flatrate"]), + "trafficleft": -1, + "premium": True} + + return account_info + + def getpw(self, user): + return self.accounts[user]["password"] + + def login(self, user, data, req): + status = self.getAccountStatus(user, req) + + # Check if user and password are valid + if not status: + self.wrongPassword() + + def getAccountStatus(self, user, req): + answer = req.load("https://www.free-way.me/ajax/jd.php", + get={"id": 4, "user": user, "pass": self.accounts[user]["password"]}) + self.logDebug("login: %s" % answer) + if answer == "Invalid login": + self.wrongPassword() + return False + return json_loads(answer) From 287fcd6cb8db1c2fd7875d8eb1c8a54c315e8a80 Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Fri, 21 Mar 2014 15:35:03 +0100 Subject: [PATCH 0058/3774] Added .gitignore --- .hgignore => .gitignore | 40 +++++++++++++++++++++++++++++++++++++--- pavement.py | 2 +- 2 files changed, 38 insertions(+), 4 deletions(-) rename .hgignore => .gitignore (57%) diff --git a/.hgignore b/.gitignore similarity index 57% rename from .hgignore rename to .gitignore index 1215b241de..f6ad32bca5 100644 --- a/.hgignore +++ b/.gitignore @@ -1,6 +1,41 @@ +*.py[cod] + +# C extensions +*.so + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg +lib/* +lib64 +__pycache__ + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# PyCharm +.idea + # ignoreing unneeded files, using glob syntax -syntax: glob -*.pyc *~ *.pidaproject .svn @@ -25,7 +60,6 @@ cert.pem module/web/pyload.db *.svg *.prefs -*.po *.orig *.rej pyload/* diff --git a/pavement.py b/pavement.py index ac9a6fa1a8..e46374ca88 100644 --- a/pavement.py +++ b/pavement.py @@ -136,7 +136,7 @@ def get_source(options): file.chmod(0755) (pyload / ".hgtags").remove() - (pyload / ".hgignore").remove() + (pyload / ".gitignore").remove() #(pyload / "docs").rmtree() f = open(pyload / "__init__.py", "wb") From e546187e6b9c653091cc5847db902ac4f784a333 Mon Sep 17 00:00:00 2001 From: Stefano <l.stickell@yahoo.it> Date: Fri, 21 Mar 2014 15:43:10 +0100 Subject: [PATCH 0059/3774] Revert "Added .gitignore" This reverts commit 287fcd6cb8db1c2fd7875d8eb1c8a54c315e8a80. --- .gitignore => .hgignore | 40 +++------------------------------------- pavement.py | 2 +- 2 files changed, 4 insertions(+), 38 deletions(-) rename .gitignore => .hgignore (57%) diff --git a/.gitignore b/.hgignore similarity index 57% rename from .gitignore rename to .hgignore index f6ad32bca5..1215b241de 100644 --- a/.gitignore +++ b/.hgignore @@ -1,41 +1,6 @@ -*.py[cod] - -# C extensions -*.so - -# Packages -*.egg -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib/* -lib64 -__pycache__ - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox -nosetests.xml - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# PyCharm -.idea - # ignoreing unneeded files, using glob syntax +syntax: glob +*.pyc *~ *.pidaproject .svn @@ -60,6 +25,7 @@ cert.pem module/web/pyload.db *.svg *.prefs +*.po *.orig *.rej pyload/* diff --git a/pavement.py b/pavement.py index e46374ca88..ac9a6fa1a8 100644 --- a/pavement.py +++ b/pavement.py @@ -136,7 +136,7 @@ def get_source(options): file.chmod(0755) (pyload / ".hgtags").remove() - (pyload / ".gitignore").remove() + (pyload / ".hgignore").remove() #(pyload / "docs").rmtree() f = open(pyload / "__init__.py", "wb") From 3f101407b75e35c2460f725fc68777ac75451302 Mon Sep 17 00:00:00 2001 From: Thierry Merle <thierry.merle@free.fr> Date: Sun, 23 Mar 2014 17:57:08 +0100 Subject: [PATCH 0060/3774] 1fichier: fixed #553 Merges #556 --- module/plugins/hoster/OneFichierCom.py | 35 +++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py index 9fa0a4b906..4142eaece6 100644 --- a/module/plugins/hoster/OneFichierCom.py +++ b/module/plugins/hoster/OneFichierCom.py @@ -11,7 +11,7 @@ class OneFichierCom(SimpleHoster): __name__ = "OneFichierCom" __type__ = "hoster" __pattern__ = r"(http://(\w+)\.((1fichier|d(es)?fichiers|pjointe)\.(com|fr|net|org)|(cjoint|mesfichiers|piecejointe|oi)\.(org|net)|tenvoi\.(com|org|net)|dl4free\.com|alterupload\.com|megadl.fr))" - __version__ = "0.49" + __version__ = "0.50" __description__ = """1fichier.com download hoster""" __author_name__ = ("fragonib", "the-razer", "zoidberg", "imclem") __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "daniel_ AT gmx DOT net", "zoidberg@mujmail.cz", "imclem on github") @@ -23,35 +23,42 @@ class OneFichierCom(SimpleHoster): DOWNLOAD_LINK_PATTERN = r"""location\s*.\s*'(?P<N>http://.*?)'""" PASSWORD_PROTECTED_TOKEN = "protected by password" - WAITING_PATTERN = "Warning ! Without premium status, you can download only one file at a time and you must wait up to (\d+) minutes between each downloads." + WAITING_PATTERN = "Warning ! Without premium status, you must wait up to (\d+) minutes between each downloads" + LAST_DOWNLOAD_DELAY = "Your last download finished (\d+) minutes ago" + NOT_PARALLEL = r"Warning ! Without premium status, you can download only one file at a time" + RETRY_TIME = 15*60 #Default retry time in seconds (if detected parallel download) def process(self, pyfile): found = re.search(self.__pattern__, pyfile.url) file_id = found.group(2) url = "http://%s.%s/en/" % (found.group(2), found.group(3)) - self.html = self.load(url, post="submit", decode=True) + self.html = self.load(url, decode=True) + + self.getFileInfo() found = re.search(self.WAITING_PATTERN, self.html) if found: - self.waitAndRetry(int(found.group(1)) * 60) - - self.getFileInfo() + last_delay=0 + # retrieve the delay from the last download to substract from required delay + found_delay = re.search(self.LAST_DOWNLOAD_DELAY, self.html) + if found_delay: + last_delay=int(found_delay.group(1)) + self.waitAndRetry((int(found.group(1)) - last_delay) * 60) + else: #detect parallel download + found = re.search(self.NOT_PARALLEL, self.html) + if found: + self.waitAndRetry(self.RETRY_TIME) url, inputs = self.parseHtmlForm('action="http://%s' % file_id) - if not url or not inputs: + if not url: self.parseError("Download link not found") # Check for protection if "pass" in inputs: inputs['pass'] = self.getPassword() + inputs['submit'] = "Download" - self.html = self.load(url, post=inputs) - m = re.search(self.DOWNLOAD_LINK_PATTERN, self.html) - if not m: - self.parseError("Unable to detect download link") - download_url = m.group(1) - - self.download(download_url) + self.download(url, post=inputs) # Check download self.checkDownloadedFile() From d97e8b26cc111527cec0acda4f67b0c0eff7d946 Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Mon, 24 Mar 2014 22:31:48 +0100 Subject: [PATCH 0061/3774] Hoster: RapidgatorNet: __pattern__ updated (thx Gromit) --- module/plugins/hoster/RapidgatorNet.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py index 4229b2aa12..7cb4cd2293 100644 --- a/module/plugins/hoster/RapidgatorNet.py +++ b/module/plugins/hoster/RapidgatorNet.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - ############################################################################### # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -29,8 +28,8 @@ class RapidgatorNet(SimpleHoster): __name__ = "RapidgatorNet" __type__ = "hoster" - __pattern__ = r"http://(?:www\.)?rapidgator\.net/file/\w+" - __version__ = "0.20" + __pattern__ = r"http://(?:www\.)?(rapidgator\.net|rg\.to)/file/\w+" + __version__ = "0.21" __description__ = """Rapidgator.net hoster plugin""" __author_name__ = ("zoidberg", "chrox", "stickell", "Walter Purcaro") __author_mail__ = ("zoidberg@mujmail.cz", "", "l.stickell@yahoo.it", "vuolter@gmail.com") From 73dafe48e3d347a160509154bc6b8a9ae2c33d13 Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Mon, 24 Mar 2014 22:49:04 +0100 Subject: [PATCH 0062/3774] Hoster: XFileSharingPro: Fixed expired session detection --- module/plugins/hoster/UptoboxCom.py | 1 - module/plugins/hoster/XFileSharingPro.py | 38 ++++++++++++------------ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/module/plugins/hoster/UptoboxCom.py b/module/plugins/hoster/UptoboxCom.py index 4568526cb6..b4b35ab208 100644 --- a/module/plugins/hoster/UptoboxCom.py +++ b/module/plugins/hoster/UptoboxCom.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- - ############################################################################### # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py index 6dec8e02a7..c4c05f6045 100644 --- a/module/plugins/hoster/XFileSharingPro.py +++ b/module/plugins/hoster/XFileSharingPro.py @@ -1,20 +1,20 @@ # -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: zoidberg -""" +############################################################################### +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# @author: zoidberg +############################################################################### import re from random import random @@ -36,7 +36,7 @@ class XFileSharingPro(SimpleHoster): __name__ = "XFileSharingPro" __type__ = "hoster" __pattern__ = r"^unmatchable$" - __version__ = "0.26" + __version__ = "0.27" __description__ = """XFileSharingPro common hoster base""" __author_name__ = ("zoidberg", "stickell") __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -225,8 +225,8 @@ def checkErrors(self): self.setWait(3600, True) self.wait() self.retry(25) - elif 'countdown' in self.errmsg or 'Expired session' in self.errmsg: - self.retry(3) + elif 'countdown' in self.errmsg or 'Expired' in self.errmsg: + self.retry() elif 'maintenance' in self.errmsg: self.tempOffline() elif 'download files up to' in self.errmsg: From 24973fe7c4c6269597907fdf77b51827521cb376 Mon Sep 17 00:00:00 2001 From: Walter Purcaro <vuolter@gmail.com> Date: Tue, 25 Mar 2014 11:58:53 +0100 Subject: [PATCH 0063/3774] Hoster: ShareFilesCo: Mark dead --- module/plugins/accounts/ShareFilesCo.py | 13 ------------- module/plugins/hoster/ShareFilesCo.py | 24 ++++++------------------ 2 files changed, 6 insertions(+), 31 deletions(-) delete mode 100644 module/plugins/accounts/ShareFilesCo.py diff --git a/module/plugins/accounts/ShareFilesCo.py b/module/plugins/accounts/ShareFilesCo.py deleted file mode 100644 index cff52d570c..0000000000 --- a/module/plugins/accounts/ShareFilesCo.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -from module.plugins.internal.XFSPAccount import XFSPAccount - - -class ShareFilesCo(XFSPAccount): - __name__ = "ShareFilesCo" - __version__ = "0.01" - __type__ = "account" - __description__ = """ShareFilesCo account plugin""" - __author_name__ = ("stickell") - __author_mail__ = ("l.stickell@yahoo.it") - - MAIN_PAGE = "http://sharefiles.co/" diff --git a/module/plugins/hoster/ShareFilesCo.py b/module/plugins/hoster/ShareFilesCo.py index 245e20ea6a..35f21916c4 100644 --- a/module/plugins/hoster/ShareFilesCo.py +++ b/module/plugins/hoster/ShareFilesCo.py @@ -1,28 +1,16 @@ # -*- coding: utf-8 -*- -import re -from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo +from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo -class ShareFilesCo(XFileSharingPro): +class ShareFilesCo(DeadHoster): __name__ = "ShareFilesCo" __type__ = "hoster" - __pattern__ = r"http://(www\.)?sharefiles\.co/\w{12}" - __version__ = "0.01" + __pattern__ = r'http://(?:www\.)?sharefiles\.co/\w{12}' + __version__ = "0.02" __description__ = """Sharefiles.co hoster plugin""" - __author_name__ = ("stickell") - __author_mail__ = ("l.stickell@yahoo.it") - - HOSTER_NAME = "sharefiles.co" - - def startDownload(self, link): - link = link.strip() - if link.startswith('http://adf.ly'): - link = re.sub('http://adf.ly/\d+/', '', link) - if self.captcha: - self.correctCaptcha() - self.logDebug('DIRECT LINK: %s' % link) - self.download(link) + __author_name__ = "stickell" + __author_mail__ = "l.stickell@yahoo.it" getInfo = create_getInfo(ShareFilesCo) From ff3e4562923d8b23491fdee6aa231d3b97ff7226 Mon Sep 17 00:00:00 2001 From: marley2013 <marley@over-load.me> Date: Tue, 25 Mar 2014 12:12:34 +0100 Subject: [PATCH 0064/3774] New multihoster: OverLoadMe Merges #549, #550 and #551 --- module/plugins/accounts/OverLoadMe.py | 31 +++++++++++ module/plugins/hooks/OverLoadMe.py | 28 ++++++++++ module/plugins/hoster/OverLoadMe.py | 78 +++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 module/plugins/accounts/OverLoadMe.py create mode 100644 module/plugins/hooks/OverLoadMe.py create mode 100644 module/plugins/hoster/OverLoadMe.py diff --git a/module/plugins/accounts/OverLoadMe.py b/module/plugins/accounts/OverLoadMe.py new file mode 100644 index 0000000000..e288181ebf --- /dev/null +++ b/module/plugins/accounts/OverLoadMe.py @@ -0,0 +1,31 @@ +from module.plugins.Account import Account +from module.common.json_layer import json_loads + + +class OverLoadMe(Account): + __name__ = "OverLoadMe" + __version__ = "0.01" + __type__ = "account" + __description__ = """Over-Load.me account plugin""" + __author_name__ = ("marley") + __author_mail__ = ("marley@over-load.me") + + def loadAccountInfo(self, user, req): + data = self.getAccountData(user) + page = req.load("https://api.over-load.me/account.php", get={"user": user, "auth": data["password"]}).strip() + data = json_loads(page) + + # Check for premium + if data["membership"] == "Free": + return {"premium": False} + + account_info = {"validuntil": data["expirationunix"], "trafficleft": -1} + return account_info + + def login(self, user, data, req): + jsondata = req.load("https://api.over-load.me/account.php", + get={"user": user, "auth": data["password"]}).strip() + data = json_loads(jsondata) + + if data["err"] == 1: + self.wrongPassword() diff --git a/module/plugins/hooks/OverLoadMe.py b/module/plugins/hooks/OverLoadMe.py new file mode 100644 index 0000000000..bc8f9f5cb2 --- /dev/null +++ b/module/plugins/hooks/OverLoadMe.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster + + +class OverLoadMe(MultiHoster): + __name__ = "OverLoadMe" + __version__ = "0.01" + __type__ = "hook" + __config__ = [("activated", "bool", "Activated", "False"), + ("https", "bool", "Enable HTTPS", "True"), + ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported):", "all"), + ("hosterList", "str", "Hoster list (comma separated)", ""), + ("unloadFailing", "bool", "Revert to standard download if download fails", "False"), + ("interval", "int", "Reload interval in hours (0 to disable)", "12")] + __description__ = """Over-Load.me hook plugin""" + __author_name__ = ("marley") + __author_email__ = ("marley@over-load.me") + + def getHoster(self): + https = "https" if self.getConfig("https") else "http" + page = getURL(https + "://api.over-load.me/hoster.php", + get={"auth": "0001-cb1f24dadb3aa487bda5afd3b76298935329be7700cd7-5329be77-00cf-1ca0135f"} + ).replace("\"", "").strip() + self.logDebug("Hosterlist: %s" % page) + + return [x.strip() for x in page.split(",") if x.strip()] diff --git a/module/plugins/hoster/OverLoadMe.py b/module/plugins/hoster/OverLoadMe.py new file mode 100644 index 0000000000..658b3940fe --- /dev/null +++ b/module/plugins/hoster/OverLoadMe.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- + +import re +from urllib import unquote +from random import randrange + +from module.plugins.Hoster import Hoster +from module.common.json_layer import json_loads +from module.utils import parseFileSize + + +class OverLoadMe(Hoster): + __name__ = "OverLoadMe" + __version__ = "0.01" + __type__ = "hoster" + __pattern__ = r"https?://.*overload\.me.*" + __description__ = """Over-Load.me hoster plugin""" + __author_name__ = ("marley") + __author_mail__ = ("marley@over-load.me") + + def getFilename(self, url): + try: + name = unquote(url.rsplit("/", 1)[1]) + except IndexError: + name = "Unknown_Filename..." + if name.endswith("..."): # incomplete filename, append random stuff + name += "%s.tmp" % randrange(100, 999) + return name + + def setup(self): + self.chunkLimit = 5 + self.resumeDownload = True + + def process(self, pyfile): + if re.match(self.__pattern__, pyfile.url): + new_url = pyfile.url + elif not self.account: + self.logError(_("Please enter your %s account or deactivate this plugin") % "Over-Load") + self.fail("No Over-Load account provided") + else: + self.logDebug("Old URL: %s" % pyfile.url) + data = self.account.getAccountData(self.user) + + page = self.load("https://api.over-load.me/getdownload.php", + get={"auth": data["password"], "link": pyfile.url}) + data = json_loads(page) + + self.logDebug("Returned Data: %s" % data) + + if data["err"] == 1: + self.logWarning(data["msg"]) + self.tempOffline() + else: + if self.pyfile.name is not None and self.pyfile.name.endswith('.tmp') and data["filename"]: + self.pyfile.name = data["filename"] + self.pyfile.size = parseFileSize(data["filesize"]) + new_url = data["downloadlink"] + + if self.getConfig("https"): + new_url = new_url.replace("http://", "https://") + else: + new_url = new_url.replace("https://", "http://") + + if new_url != pyfile.url: + self.logDebug("New URL: %s" % new_url) + + if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown") or pyfile.name.endswith('..'): + # only use when name wasn't already set + pyfile.name = self.getFilename(new_url) + + self.download(new_url, disposition=True) + + check = self.checkDownload( + {"error": "<title>An error occured while processing your request"}) + + if check == "error": + # usual this download can safely be retried + self.retry(reason="An error occured while generating link.", wait_time=60) From a80bf6d4edc8ba13d1383d9502e994be10a9d375 Mon Sep 17 00:00:00 2001 From: radek-senfeld Date: Sat, 29 Mar 2014 22:37:01 +0100 Subject: [PATCH 0065/3774] Fixed UlozTo hoster and account Merged #554 --- module/plugins/accounts/UlozTo.py | 8 ++++---- module/plugins/hoster/UlozTo.py | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/module/plugins/accounts/UlozTo.py b/module/plugins/accounts/UlozTo.py index 8a281389e5..429a32db31 100644 --- a/module/plugins/accounts/UlozTo.py +++ b/module/plugins/accounts/UlozTo.py @@ -7,13 +7,13 @@ class UlozTo(Account): __name__ = "UlozTo" - __version__ = "0.05" + __version__ = "0.06" __type__ = "account" __description__ = """uloz.to account plugin""" __author_name__ = ("zoidberg", "pulpe") __author_mail__ = ("zoidberg@mujmail.cz") - TRAFFIC_LEFT_PATTERN = r'