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: | 
