diff options
Diffstat (limited to 'module/plugins')
29 files changed, 973 insertions, 503 deletions
diff --git a/module/plugins/accounts/EasybytezCom.py b/module/plugins/accounts/EasybytezCom.py index 72f37b699..ffd132ba3 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 @@ from module.utils import parseFileSize 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 @@ class EasybytezCom(Account): 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 diff --git a/module/plugins/accounts/FreeWayMe.py b/module/plugins/accounts/FreeWayMe.py new file mode 100644 index 000000000..0222ad65f --- /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 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) diff --git a/module/plugins/accounts/OverLoadMe.py b/module/plugins/accounts/OverLoadMe.py new file mode 100644 index 000000000..e288181eb --- /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/accounts/ShareFilesCo.py b/module/plugins/accounts/ShareFilesCo.py deleted file mode 100644 index cff52d570..000000000 --- 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/crypter/DlProtectCom.py b/module/plugins/crypter/DlProtectCom.py new file mode 100644 index 000000000..d93455a55 --- /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) diff --git a/module/plugins/crypter/FilestubeCom.py b/module/plugins/crypter/FilestubeCom.py index 24e2ca137..bb90e63b8 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"<title>(?P<title>.+) download" + LINK_PATTERN = r"<a class=\"file-link-main(?: noref)?\" [^>]* href=\"(http://[^\"]+)" + TITLE_PATTERN = r"<h1\s*> (?P<title>.+) download\s*</h1>" diff --git a/module/plugins/crypter/NosvideoCom.py b/module/plugins/crypter/NosvideoCom.py new file mode 100644 index 000000000..49b932fc0 --- /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/crypter/TusfilesNetFolder.py b/module/plugins/crypter/TusfilesNetFolder.py new file mode 100644 index 000000000..f364aabe7 --- /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</Title>' + PAGES_PATTERN = r'>\((?P<pages>\d+) \w+\)<' + + FILE_URL_REPLACEMENTS = [(__pattern__, r'https://www.tusfiles.net/go/\g<ID>/')] + + 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() diff --git a/module/plugins/hooks/FreeWayMe.py b/module/plugins/hooks/FreeWayMe.py new file mode 100644 index 000000000..30d76cb8e --- /dev/null +++ b/module/plugins/hooks/FreeWayMe.py @@ -0,0 +1,39 @@ +# -*- 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 +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): + 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()] diff --git a/module/plugins/hooks/OverLoadMe.py b/module/plugins/hooks/OverLoadMe.py new file mode 100644 index 000000000..bc8f9f5cb --- /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/ARD.py b/module/plugins/hoster/ARD.py deleted file mode 100644 index 12cb6c95a..000000000 --- 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) diff --git a/module/plugins/hoster/CloudzerNet.py b/module/plugins/hoster/CloudzerNet.py index 8253c35b9..d0a19a945 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) diff --git a/module/plugins/hoster/CyberlockerCh.py b/module/plugins/hoster/CyberlockerCh.py index 19a4473b3..a08bf8518 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) diff --git a/module/plugins/hoster/FastshareCz.py b/module/plugins/hoster/FastshareCz.py index fba704123..93fbad6be 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 @@ class FastshareCz(SimpleHoster): 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() diff --git a/module/plugins/hoster/FileomCom.py b/module/plugins/hoster/FileomCom.py new file mode 100644 index 000000000..3cf9bb4c1 --- /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) diff --git a/module/plugins/hoster/FreeWayMe.py b/module/plugins/hoster/FreeWayMe.py new file mode 100644 index 000000000..5439c10c1 --- /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) diff --git a/module/plugins/hoster/Keep2shareCC.py b/module/plugins/hoster/Keep2shareCC.py index 323ee09ca..59308690c 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 @@ class Keep2shareCC(SimpleHoster): 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") diff --git a/module/plugins/hoster/LoadTo.py b/module/plugins/hoster/LoadTo.py index 0f99c272a..d1c1eb0f8 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) diff --git a/module/plugins/hoster/NosuploadCom.py b/module/plugins/hoster/NosuploadCom.py new file mode 100644 index 000000000..5735390bb --- /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) diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py index 54bf1d1fa..4142eaece 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,19 +11,22 @@ 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.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") - FILE_NAME_PATTERN = r'">File name :</th>\s*<td>(?P<N>[^<]+)</td>' - FILE_SIZE_PATTERN = r'<th>File size :</th>\s*<td>(?P<S>[^<]+)</td>' + FILE_NAME_PATTERN = r'">Filename :</th>\s*<td>(?P<N>[^<]+)</td>' + FILE_SIZE_PATTERN = r'<th>Size :</th>\s*<td>(?P<S>[^<]+)</td>' 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'<br/> <br/> <br/> \s+<a href="(?P<url>http://.*?)"' + 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) @@ -28,19 +34,29 @@ class OneFichierCom(SimpleHoster): url = "http://%s.%s/en/" % (found.group(2), found.group(3)) 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.download(url, post=inputs) diff --git a/module/plugins/hoster/OverLoadMe.py b/module/plugins/hoster/OverLoadMe.py new file mode 100644 index 000000000..658b3940f --- /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</title>"}) + + if check == "error": + # usual this download can safely be retried + self.retry(reason="An error occured while generating link.", wait_time=60) diff --git a/module/plugins/hoster/PutlockerCom.py b/module/plugins/hoster/PutlockerCom.py index afe084028..002783bfd 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/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py index 611d2ba5d..7cb4cd229 100644 --- a/module/plugins/hoster/RapidgatorNet.py +++ b/module/plugins/hoster/RapidgatorNet.py @@ -1,52 +1,57 @@ # -*- 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 +############################################################################### 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|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") API_URL = 'http://rapidgator.net/api/file' - FILE_NAME_PATTERN = r'Downloading:(?:\s*<[^>]*>)*\s*(?P<N>.*?)(?:\s*<[^>]*>)' - FILE_SIZE_PATTERN = r'File size:\s*<strong>(?P<S>.*?)</strong>' - FILE_OFFLINE_PATTERN = r'<title>File not found</title>' + FILE_NAME_PATTERN = r'<title>Download file (?P<N>.*)</title>' + FILE_SIZE_PATTERN = r'File size:\s*<strong>(?P<S>[\d\.]+) (?P<U>\w+)</strong>' + 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 +65,7 @@ class RapidgatorNet(SimpleHoster): 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 +90,17 @@ class RapidgatorNet(SimpleHoster): 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 +112,7 @@ class RapidgatorNet(SimpleHoster): 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 +123,32 @@ class RapidgatorNet(SimpleHoster): 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 +158,6 @@ class RapidgatorNet(SimpleHoster): if found: captcha_key = found.group(1) captcha = ReCaptcha(self) - else: found = re.search(self.SOLVEMEDIA_PATTERN, self.html) if found: @@ -143,47 +166,29 @@ class RapidgatorNet(SimpleHoster): 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) diff --git a/module/plugins/hoster/ShareFilesCo.py b/module/plugins/hoster/ShareFilesCo.py index 245e20ea6..35f21916c 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) diff --git a/module/plugins/hoster/SockshareCom.py b/module/plugins/hoster/SockshareCom.py index b2635d8bc..fd0e5aa91 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) diff --git a/module/plugins/hoster/UptoboxCom.py b/module/plugins/hoster/UptoboxCom.py index 420610ee4..b4b35ab20 100644 --- a/module/plugins/hoster/UptoboxCom.py +++ b/module/plugins/hoster/UptoboxCom.py @@ -1,19 +1,42 @@ # -*- 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) diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py index 5b167c3c9..c4c05f604 100644 --- a/module/plugins/hoster/XFileSharingPro.py +++ b/module/plugins/hoster/XFileSharingPro.py @@ -1,27 +1,27 @@ # -*- 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 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.27" __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 @@ class XFileSharingPro(SimpleHoster): 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 @@ class XFileSharingPro(SimpleHoster): 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() @@ -223,8 +225,8 @@ class XFileSharingPro(SimpleHoster): 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: @@ -238,7 +240,7 @@ class XFileSharingPro(SimpleHoster): return self.errmsg def getPostParameters(self): - for _ in range(3): + for _ in xrange(3): if not self.errmsg: self.checkErrors() diff --git a/module/plugins/hoster/ZDF.py b/module/plugins/hoster/ZDF.py index 9940fd078..e45717186 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 @@ class ZDF(Hoster): @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))) diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index e4f2befa0..5983627d5 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.46" __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 @@ class ZippyshareCom(SimpleHoster): 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 @@ class ZippyshareCom(SimpleHoster): 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"(?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()) @@ -210,7 +208,7 @@ class ZippyshareCom(SimpleHoster): 'response': code, 'shortencode': shortencode})) self.logDebug("reCaptcha response : %s" % response) - if response == True: + if response: self.correctCaptcha() break else: |