diff options
Diffstat (limited to 'pyload/plugins')
26 files changed, 1437 insertions, 0 deletions
| diff --git a/pyload/plugins/accounts/FreeWayMe.py b/pyload/plugins/accounts/FreeWayMe.py new file mode 100644 index 000000000..955cc3c7f --- /dev/null +++ b/pyload/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/pyload/plugins/accounts/OverLoadMe.py b/pyload/plugins/accounts/OverLoadMe.py new file mode 100644 index 000000000..eab20480f --- /dev/null +++ b/pyload/plugins/accounts/OverLoadMe.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- + +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/pyload/plugins/accounts/SimplyPremiumCom.py b/pyload/plugins/accounts/SimplyPremiumCom.py new file mode 100644 index 000000000..1e6d66806 --- /dev/null +++ b/pyload/plugins/accounts/SimplyPremiumCom.py @@ -0,0 +1,58 @@ +# -*- 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/>.    # +############################################################################ + +from module.plugins.Account import Account +from module.common.json_layer import json_loads + + +class SimplyPremiumCom(Account): +    __name__ = "SimplyPremiumCom" +    __version__ = "0.01" +    __type__ = "account" +    __description__ = """Simply-Premium.Com account plugin""" +    __author_name__ = ("EvolutionClip") +    __author_mail__ = ("evolutionclip@live.de") + +    def loadAccountInfo(self, user, req): +        json_data = req.load('http://www.simply-premium.com/api/user.php?format=json') +        self.logDebug("JSON data: " + json_data) +        json_data = json_loads(json_data) + +        if 'vip' in json_data['result'] and json_data['result']['vip'] == 0: +            return {"premium": False} + +        #Time package +        validuntil = float(json_data['result']['timeend']) +        #Traffic package +        # {"trafficleft": int(traffic) / 1024, "validuntil": -1} +        #trafficleft = int(json_data['result']['traffic'] / 1024) + +        #return {"premium": True, "validuntil": validuntil, "trafficleft": trafficleft} +        return {"premium": True, "validuntil": validuntil} + +    def login(self, user, data, req): +        req.cj.setCookie("simply-premium.com", "lang", "EN") + +        if data['password'] == '' or data['password'] == '0': +            post_data = {"key": user} +        else: +            post_data = {"login_name": user, "login_pass": data["password"]} + +        self.html = req.load("http://www.simply-premium.com/login.php", post=post_data) + +        if 'logout' not in self.html: +            self.wrongPassword() diff --git a/pyload/plugins/accounts/Vipleech4uCom.py b/pyload/plugins/accounts/Vipleech4uCom.py new file mode 100644 index 000000000..1e8463456 --- /dev/null +++ b/pyload/plugins/accounts/Vipleech4uCom.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +import re +from time import mktime, strptime + +from module.plugins.Account import Account + + +class Vipleech4uCom(Account): +    __name__ = "Vipleech4uCom" +    __version__ = "0.1" +    __type__ = "account" +    __description__ = """Vipleech4u.com account plugin""" +    __author_name__ = ("Kagenoshin") +    __author_mail__ = ("kagenoshin@gmx.ch") + +    STATUS_PATTERN = re.compile(r'status.*?<\s*?strong\s*?>[^<]*?vip[^<]*?<', re.I) +    VALIDUNTIL_PATTERN = re.compile(r'valid\s*?until.*?<\s*?strong\s*?>([^<]*?)<', re.I) + +    def loadAccountInfo(self, user, req): +        response = req.load("http://vipleech4u.com", decode=True) +        status = self.STATUS_PATTERN.search(response) + +        validuntil = self.VALIDUNTIL_PATTERN.search(response) +        if validuntil: +            validuntil = validuntil.group(1) + +        if status and validuntil: +            print status +            print validuntil +            return {"trafficleft": -1, "validuntil": mktime(strptime("%s 23:59" % validuntil, "%d-%m-%Y %H:%M"))} +        else: +            return {"premium": False} + +    def login(self, user, data, req): +        self.loginname = user +        self.password = data["password"] +        post_data = {'action': 'login', 'user': self.loginname, 'pass': self.password} +        req.load("http://vipleech4u.com/login.php") +        response = req.load("http://vipleech4u.com/login.php", post=post_data, decode=True) +        if 'Username or Password are incorrect' in response: +            self.wrongPassword() diff --git a/pyload/plugins/addons/FreeWayMe.py b/pyload/plugins/addons/FreeWayMe.py new file mode 100644 index 000000000..7d4bcc852 --- /dev/null +++ b/pyload/plugins/addons/FreeWayMe.py @@ -0,0 +1,40 @@ +# -*- 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__ = """FreeWay.me 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/pyload/plugins/addons/OverLoadMe.py b/pyload/plugins/addons/OverLoadMe.py new file mode 100644 index 000000000..e15d0b05f --- /dev/null +++ b/pyload/plugins/addons/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_mail__ = "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/pyload/plugins/addons/SimplyPremiumCom.py b/pyload/plugins/addons/SimplyPremiumCom.py new file mode 100644 index 000000000..ca1122e45 --- /dev/null +++ b/pyload/plugins/addons/SimplyPremiumCom.py @@ -0,0 +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/>.    # +############################################################################ + +from module.plugins.internal.MultiHoster import MultiHoster +from module.network.RequestFactory import getURL +from module.common.json_layer import json_loads + + +class SimplyPremiumCom(MultiHoster): +    __name__ = "SimplyPremiumCom" +    __version__ = "0.01" +    __type__ = "hook" +    __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 standard download if download fails", "False"), +                  ("interval", "int", "Reload interval in hours (0 to disable)", "24")] +    __description__ = """Simply-Premium.Com hook plugin""" +    __author_name__ = ("EvolutionClip") +    __author_mail__ = ("evolutionclip@live.de") + +    def getHoster(self): +        json_data = getURL('http://www.simply-premium.com/api/hosts.php?format=json&online=1') +        json_data = json_loads(json_data) + +        host_list = [element['host'] for element in json_data['result']] + +        return host_list diff --git a/pyload/plugins/addons/Vipleech4uCom.py b/pyload/plugins/addons/Vipleech4uCom.py new file mode 100644 index 000000000..b2156b017 --- /dev/null +++ b/pyload/plugins/addons/Vipleech4uCom.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +import re + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster + + +class Vipleech4uCom(MultiHoster): +    __name__ = "Vipleech4uCom" +    __version__ = "0.01" +    __type__ = "hook" +    __config__ = [("activated", "bool", "Activated", "False"), +                  ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"), +                  ("hosterList", "str", "Hoster list (comma separated)", "")] +    __description__ = """Vipleech4u.com hook plugin""" +    __author_name__ = ("Kagenoshin") +    __author_mail__ = ("kagenoshin@gmx.ch") + +    HOSTER_PATTERN = re.compile(r'align\s*?=\s*?["\']*?left.*?<\s*?strong\s*?>([^<]*?)<', re.I) + +    def getHoster(self): +        hosters = { +            'depositfiles': ['depositfiles.com', 'dfiles.eu'], +            'uploaded': ['uploaded.to', 'uploaded.net', 'ul.to'], +            'rapidggator': ['rapidgator.net'],  # they have a typo it's called rapidgator +            'freakshare': ['freakshare.net', 'freakshare.com'], +            'filefactory': ['filefactory.com'], +            'bitshare': ['bitshare.com'], +            'share-online': ['share-online.biz', 'egoshare.com'], +            'youtube': ['youtube.com'], +            'turbobit': ['turbobit.net', 'unextfiles.com'], +            'firedrive': ['firedrive.com', 'putlocker.com'], +            'filepost': ['filepost.com', 'fp.io'], +            'netload': ['netload.in'], +            'uploadhero': ['uploadhero.com'], +            'ryushare': ['ryushare.com'], +        } + +        #check if the list is still valid +        self.check_for_new_or_removed_hosters(hosters) + +        #build list +        hoster_list = [] + +        for item in hosters.itervalues(): +            hoster_list.extend(item) + +        return hoster_list + +    def check_for_new_or_removed_hosters(self, hosters): +        #get the old hosters +        old_hosters = hosters.keys() + +        #load the current hosters from vipleech4u.com +        page = getURL('http://vipleech4u.com/hosts.php') +        current_hosters = self.HOSTER_PATTERN.findall(page) +        current_hosters = [x.lower() for x in current_hosters] + +        #let's look for new hosters +        new_hosters = [] + +        for hoster in current_hosters: +            if not hoster in old_hosters: +                new_hosters.append(hoster) + +        #let's look for removed hosters +        removed_hosters = [] + +        for hoster in old_hosters: +            if not hoster in current_hosters: +                removed_hosters.append(hoster) + +        if new_hosters: +            self.logDebug('The following new hosters were found on vipleech4u.com: %s' % str(new_hosters)) + +        if removed_hosters: +            self.logDebug('The following hosters were removed from vipleech4u.com: %s' % str(removed_hosters)) + +        if not (new_hosters and removed_hosters): +            self.logDebug('The hoster list is still valid.') diff --git a/pyload/plugins/crypter/DailymotionBatch.py b/pyload/plugins/crypter/DailymotionBatch.py new file mode 100644 index 000000000..5c0dd9cec --- /dev/null +++ b/pyload/plugins/crypter/DailymotionBatch.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- + +""" +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 3 of the License, +    or (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +    See the GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. + +    @author: Walter Purcaro +""" + +from urlparse import urljoin +import re + +from module.common.json_layer import json_loads +from module.plugins.Crypter import Crypter +from module.utils import save_join + + +class DailymotionBatch(Crypter): +    __name__ = "DailymotionBatch" +    __type__ = "crypter" +    __pattern__ = r'https?://(?:www\.)?dailymotion\.com/((playlists/)?(?P<TYPE>playlist|user)/)?(?P<ID>[\w^_]+)(?(TYPE)|#)' +    __version__ = "0.01" +    __description__ = """Dailymotion.com channel & playlist decrypter""" +    __author_name__ = "Walter Purcaro" +    __author_mail__ = "vuolter@gmail.com" + +    def api_response(self, ref, req=None): +        url = urljoin("https://api.dailymotion.com/", ref) +        page = self.load(url, get=req) +        return json_loads(page) + +    def getPlaylistInfo(self, id): +        ref = "playlist/" + id +        req = {"fields": "name,owner.screenname"} +        playlist = self.api_response(ref, req) + +        if "error" in playlist: +            return + +        name = playlist["name"] +        owner = playlist["owner.screenname"] +        return name, owner + +    def _getPlaylists(self, user_id, page=1): +        ref = "user/%s/playlists" % user_id +        req = {"fields": "id", "page": page, "limit": 100} +        user = self.api_response(ref, req) + +        if "error" in user: +            return + +        for playlist in user["list"]: +            yield playlist["id"] + +        if user["has_more"]: +            for item in self._getPlaylists(user_id, page + 1): +                yield item + +    def getPlaylists(self, user_id): +        return [(id,) + self.getPlaylistInfo(id) for id in self._getPlaylists(user_id)] + +    def _getVideos(self, id, page=1): +        ref = "playlist/%s/videos" % id +        req = {"fields": "url", "page": page, "limit": 100} +        playlist = self.api_response(ref, req) + +        if "error" in playlist: +            return + +        for video in playlist["list"]: +            yield video["url"] + +        if playlist["has_more"]: +            for item in self._getVideos(id, page + 1): +                yield item + +    def getVideos(self, playlist_id): +        return list(self._getVideos(playlist_id))[::-1] + +    def decrypt(self, pyfile): +        m = re.match(self.__pattern__, pyfile.url) +        m_id = m.group("ID") +        m_type = m.group("TYPE") + +        if m_type == "playlist": +            self.logDebug("Url recognized as Playlist") +            p_info = self.getPlaylistInfo(m_id) +            playlists = [(m_id,) + p_info] if p_info else None +        else: +            self.logDebug("Url recognized as Channel") +            playlists = self.getPlaylists(m_id) +            self.logDebug("%s playlist\s found on channel \"%s\"" % (len(playlists), m_id)) + +        if not playlists: +            self.fail("No playlist available") + +        for p_id, p_name, p_owner in playlists: +            p_videos = self.getVideos(p_id) +            p_folder = save_join(self.config['general']['download_folder'], p_owner, p_name) +            self.logDebug("%s video\s found on playlist \"%s\"" % (len(p_videos), p_name)) +            self.packages.append((p_name, p_videos, p_folder))  #: folder is NOT recognized by pyload 0.4.9! diff --git a/pyload/plugins/crypter/DlProtectCom.py b/pyload/plugins/crypter/DlProtectCom.py new file mode 100644 index 000000000..dbe5bf705 --- /dev/null +++ b/pyload/plugins/crypter/DlProtectCom.py @@ -0,0 +1,74 @@ +# -*- 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/pyload/plugins/crypter/MultiUpOrg.py b/pyload/plugins/crypter/MultiUpOrg.py new file mode 100644 index 000000000..997d60862 --- /dev/null +++ b/pyload/plugins/crypter/MultiUpOrg.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +############################################################################### +#  This program is free software: you can redistribute it and/or modify +#  it under the terms of the GNU Affero General Public License as +#  published by the Free Software Foundation, either version 3 of the +#  License, or (at your option) any later version. +# +#  This program is distributed in the hope that it will be useful, +#  but WITHOUT ANY WARRANTY; without even the implied warranty of +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +#  GNU Affero General Public License for more details. +# +#  You should have received a copy of the GNU Affero General Public License +#  along with this program.  If not, see <http://www.gnu.org/licenses/>. +# +#  @author: Walter Purcaro +############################################################################### + +import re +from urlparse import urljoin + +from module.plugins.internal.SimpleCrypter import SimpleCrypter + + +class MultiUpOrg(SimpleCrypter): +    __name__ = "MultiUpOrg" +    __type__ = "crypter" +    __pattern__ = r"http://(?:www\.)?multiup\.org/(en|fr)/(?P<TYPE>project|download|miror)/\w+(/\w+)?" +    __version__ = "0.01" +    __description__ = """MultiUp.org crypter plugin""" +    __author_name__ = "Walter Purcaro" +    __author_mail__ = "vuolter@gmail.com" + +    TITLE_PATTERN = r'<title>.*(Project|Projet|ownload|élécharger) (?P<title>.+?) (\(|- )' + +    def getLinks(self): +        m_type = re.match(self.__pattern__, self.pyfile.url).group("TYPE") + +        if m_type == "project": +            pattern = r'\n(http://www\.multiup\.org/(?:en|fr)/download/.*)' +        else: +            pattern = r'style="width:97%;text-align:left".*\n.*href="(.*)"' +            if m_type == "download": +                dl_pattern = r'href="(.*)">.*\n.*<h5>DOWNLOAD</h5>' +                miror_page = urljoin("http://www.multiup.org", re.search(dl_pattern, self.html).group(1)) +                self.html = self.load(miror_page) + +        return re.findall(pattern, self.html) diff --git a/pyload/plugins/crypter/NosvideoCom.py b/pyload/plugins/crypter/NosvideoCom.py new file mode 100644 index 000000000..63e199a7a --- /dev/null +++ b/pyload/plugins/crypter/NosvideoCom.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +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 decrypter plugin""" +    __author_name__ = "igel" +    __author_mail__ = "igelkun@myopera.com" + +    LINK_PATTERN = r'href="(http://(?:w{3}\.)?nosupload.com/\?d=\w+)"' +    TITLE_PATTERN = r"<[tT]itle>Watch (?P<title>.+)</[tT]itle>" diff --git a/pyload/plugins/crypter/TnyCz.py b/pyload/plugins/crypter/TnyCz.py new file mode 100644 index 000000000..6c56f7639 --- /dev/null +++ b/pyload/plugins/crypter/TnyCz.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +""" +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 3 of the License, +    or (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +    See the GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. + +    @author: Walter Purcaro +""" + +from module.plugins.internal.SimpleCrypter import SimpleCrypter + +import re + + +class TnyCz(SimpleCrypter): +    __name__ = "TnyCz" +    __type__ = "crypter" +    __pattern__ = r'http://(?:www\.)?tny\.cz/\w+' +    __version__ = "0.01" +    __description__ = """Tny.cz decrypter plugin""" +    __author_name__ = "Walter Purcaro" +    __author_mail__ = "vuolter@gmail.com" + +    TITLE_PATTERN = r'<title>(?P<title>.+) - .+</title>' + +    def getLinks(self): +        m = re.search(r'<a id=\'save_paste\' href="(.+save\.php\?hash=.+)">', self.html) +        return re.findall(".+", self.load(m.group(1), decode=True)) if m else None diff --git a/pyload/plugins/crypter/TusfilesNetFolder.py b/pyload/plugins/crypter/TusfilesNetFolder.py new file mode 100644 index 000000000..0bc770f99 --- /dev/null +++ b/pyload/plugins/crypter/TusfilesNetFolder.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 +############################################################################### + +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/pyload/plugins/hoster/FileStoreTo.py b/pyload/plugins/hoster/FileStoreTo.py new file mode 100644 index 000000000..5a73fb9ef --- /dev/null +++ b/pyload/plugins/hoster/FileStoreTo.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +""" +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 3 of the License, +    or (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +    See the GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. + +    @author: Walter Purcaro +""" + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class FileStoreTo(SimpleHoster): +    __name__ = "FileStoreTo" +    __type__ = "hoster" +    __pattern__ = r'http://(?:www\.)?filestore\.to/\?d=(?P<ID>\w+)' +    __version__ = "0.01" +    __description__ = """FileStore.to hoster plugin""" +    __author_name__ = ("Walter Purcaro", "stickell") +    __author_mail__ = ("vuolter@gmail.com", "l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'File: <span[^>]*>(?P<N>.+)</span><br />Size: (?P<S>[\d,.]+) (?P<U>\w+)' +    FILE_OFFLINE_PATTERN = r'>Download-Datei wurde nicht gefunden<' + +    def setup(self): +        self.resumeDownload = self.multiDL = True + +    def handleFree(self): +        self.wait(10) +        ldc = re.search(r'wert="(\w+)"', self.html).group(1) +        link = self.load("http://filestore.to/ajax/download.php", get={"LDC": ldc}) +        self.logDebug("Download link = " + link) +        self.download(link) + + +getInfo = create_getInfo(FileStoreTo) diff --git a/pyload/plugins/hoster/FileomCom.py b/pyload/plugins/hoster/FileomCom.py new file mode 100644 index 000000000..9fda2353c --- /dev/null +++ b/pyload/plugins/hoster/FileomCom.py @@ -0,0 +1,52 @@ +# -*- 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/pyload/plugins/hoster/FreeWayMe.py b/pyload/plugins/hoster/FreeWayMe.py new file mode 100644 index 000000000..d72b12a12 --- /dev/null +++ b/pyload/plugins/hoster/FreeWayMe.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +""" +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU 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://(?:www\.)?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/pyload/plugins/hoster/NosuploadCom.py b/pyload/plugins/hoster/NosuploadCom.py new file mode 100644 index 000000000..1de734222 --- /dev/null +++ b/pyload/plugins/hoster/NosuploadCom.py @@ -0,0 +1,39 @@ +# -*- 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" +    __author_mail__ = "igelkun@myopera.com" + +    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/pyload/plugins/hoster/OverLoadMe.py b/pyload/plugins/hoster/OverLoadMe.py new file mode 100644 index 000000000..aaa1442e4 --- /dev/null +++ b/pyload/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 pyfile.name is not None and pyfile.name.endswith('.tmp') and data["filename"]: +                    pyfile.name = data["filename"] +                    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/pyload/plugins/hoster/PotloadCom.py b/pyload/plugins/hoster/PotloadCom.py new file mode 100644 index 000000000..ffcfad1a5 --- /dev/null +++ b/pyload/plugins/hoster/PotloadCom.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo + + +class PotloadCom(XFileSharingPro): +    __name__ = "PotloadCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www\.)?potload\.com/\w{12}" +    __version__ = "0.01" +    __description__ = """billionuploads.com hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'<h[1-6]>(?P<N>.+) \((?P<S>\d+) (?P<U>\w+)\)</h' +    HOSTER_NAME = "potload.com" + + +getInfo = create_getInfo(PotloadCom) diff --git a/pyload/plugins/hoster/PromptfileCom.py b/pyload/plugins/hoster/PromptfileCom.py new file mode 100644 index 000000000..3580a9509 --- /dev/null +++ b/pyload/plugins/hoster/PromptfileCom.py @@ -0,0 +1,56 @@ +# -*- 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/>.    # +############################################################################ + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class PromptfileCom(SimpleHoster): +    __name__ = "PromptfileCom" +    __type__ = "hoster" +    __pattern__ = r"https?://(?:www\.)?promptfile\.com/" +    __version__ = "0.1" +    __description__ = """Promptfile.Com File Download Hoster""" +    __author_name__ = ("igel") + +    FILE_INFO_PATTERN = r'<span style="[^"]*" title="[^"]*">(?P<N>.*?) \((?P<S>[\d.]+) (?P<U>\w+)\)</span>' +    FILE_OFFLINE_PATTERN = r'<span style="[^"]*" title="File Not Found">File Not Found</span>' + +    CHASH_PATTERN = r'<input type="hidden" name="chash" value="([^"]*)" />' +    DIRECT_LINK_PATTERN = r"clip: {\s*url: '(https?://(?:www\.)promptfile[^']*)'," + +    def handleFree(self): +        # STAGE 1: get link to continue +        m = re.search(self.CHASH_PATTERN, self.html) +        if not m: +            self.parseError("Unable to detect chash") +        chash = m.group(1) +        self.logDebug("read chash %s" % chash) +        # continue to stage2 +        self.html = self.load(self.pyfile.url, decode=True, post={'chash': chash}) + +        # STAGE 2: get the direct link +        m = re.search(self.DIRECT_LINK_PATTERN, self.html, re.MULTILINE | re.DOTALL) +        if not m: +            self.parseError("Unable to detect direct link") +        direct = m.group(1) +        self.logDebug('found direct link: ' + direct) +        self.download(direct, disposition=True) + + +getInfo = create_getInfo(PromptfileCom) diff --git a/pyload/plugins/hoster/SimplyPremiumCom.py b/pyload/plugins/hoster/SimplyPremiumCom.py new file mode 100644 index 000000000..c9fbf2ff1 --- /dev/null +++ b/pyload/plugins/hoster/SimplyPremiumCom.py @@ -0,0 +1,103 @@ +# -*- 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/>.    # +############################################################################ + +import re +from datetime import datetime, timedelta + +from module.plugins.Hoster import Hoster + + +def secondsToMidnight(): +    # Seconds until 00:10 GMT+2 +    now = datetime.utcnow() + timedelta(hours=2) +    if now.hour is 0 and now.minute < 10: +        midnight = now +    else: +        midnight = now + timedelta(days=1) +    midnight = midnight.replace(hour=0, minute=10, second=0, microsecond=0) +    return int((midnight - now).total_seconds()) + + +class SimplyPremiumCom(Hoster): +    __name__ = "SimplyPremiumCom" +    __version__ = "0.01" +    __type__ = "hoster" +    __pattern__ = r"https?://.*(simply-premium)\.com" +    __description__ = """Simply-Premium.Com hoster plugin""" +    __author_name__ = ("EvolutionClip") +    __author_mail__ = ("evolutionclip@live.de") + +    def setup(self): +        self.chunkLimit = 16 +        self.resumeDownload = False + +    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") % "Simply-Premium.com") +            self.fail("No Simply-Premium.com account provided") +        else: +            self.logDebug("Old URL: %s" % pyfile.url) +            for i in xrange(5): +                page = self.load('http://www.simply-premium.com/premium.php?info&link=' + pyfile.url) +                self.logDebug("JSON data: " + page) +                if page != '': +                    break +            else: +                self.logInfo("Unable to get API data, waiting 1 minute and retry") +                self.retry(5, 60, "Unable to get API data") + +            if '<valid>0</valid>' in page or ( +                    "You are not allowed to download from this host" in page and self.premium): +                self.account.relogin(self.user) +                self.retry() +            elif "NOTFOUND" in page: +                self.offline() +            elif "downloadlimit" in page: +                self.logInfo("Reached maximum connctions") +                self.retry(5, 60, "Reached maximum connctions") +            elif "trafficlimit" in page: +                self.logInfo("Reached daily limit for this host. Waiting until 00:10 GMT+2") +                self.retry(5, secondsToMidnight(), "Daily limit for this host reached") +            elif "hostererror" in page: +                self.logInfo("Hoster temporarily unavailable, waiting 1 minute and retry") +                self.retry(5, 60, "Hoster is temporarily unavailable") +            #page = json_loads(page) +            #new_url = page.keys()[0] +            #self.api_data = page[new_url] + +            try: +                start = page.index('<name>') + len('<name>') +                end = page.index('</name>', start) +                self.pyfile.name = page[start:end] +            except ValueError: +                self.pyfile.name = "" + +            try: +                start = page.index('<size>') + len('<size>') +                end = page.index('</size>', start) +                self.pyfile.size = int(float(page[start:end])) +            except ValueError: +                self.pyfile.size = 0 + +            new_url = 'http://www.simply-premium.com/premium.php?link=' + pyfile.url + +        if new_url != pyfile.url: +            self.logDebug("New URL: " + new_url) + +        self.download(new_url, disposition=True) diff --git a/pyload/plugins/hoster/SoundcloudCom.py b/pyload/plugins/hoster/SoundcloudCom.py new file mode 100644 index 000000000..a1ec1378a --- /dev/null +++ b/pyload/plugins/hoster/SoundcloudCom.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +import re +import pycurl + +from module.plugins.Hoster import Hoster + + +class SoundcloudCom(Hoster): +    __name__ = "SoundcloudCom" +    __type__ = "hoster" +    __pattern__ = r'https?://(?:www\.)?soundcloud\.com/(?P<UID>.*?)/(?P<SID>.*)' +    __version__ = "0.1" +    __description__ = """SoundCloud.com hoster plugin""" +    __author_name__ = "Peekayy" +    __author_mail__ = "peekayy.dev@gmail.com" + +    def process(self, pyfile): +        # default UserAgent of HTTPRequest fails for this hoster so we use this one +        self.req.http.c.setopt(pycurl.USERAGENT, 'Mozilla/5.0') +        page = self.load(pyfile.url) +        match = re.search(r'<div class="haudio.*?large.*?" data-sc-track="(?P<ID>[0-9]*)"', page) +        songId = clientId = "" +        if match: +            songId = match.group("ID") +        if len(songId) <= 0: +            self.logError("Could not find song id") +            self.offline() +        else: +            match = re.search(r'"clientID":"(?P<CID>.*?)"', page) +            if match: +                clientId = match.group("CID") + +            if len(clientId) <= 0: +                clientId = "b45b1aa10f1ac2941910a7f0d10f8e28" + +            match = re.search(r'<em itemprop="name">\s(?P<TITLE>.*?)\s</em>', page) +            if match: +                pyfile.name = match.group("TITLE") + ".mp3" +            else: +                pyfile.name = re.match(self.__pattern__, pyfile.url).group("SID") + ".mp3" + +            # url to retrieve the actual song url +            page = self.load("https://api.sndcdn.com/i1/tracks/%s/streams" % songId, get={"client_id": clientId}) +            # getting streams +            # for now we choose the first stream found in all cases +            # it could be improved if relevant for this hoster +            streams = [ +                (result.group("QUALITY"), result.group("URL")) +                for result in re.finditer(r'"(?P<QUALITY>.*?)":"(?P<URL>.*?)"', page) +            ] +            self.logDebug("Found Streams", streams) +            self.logDebug("Downloading", streams[0][0], streams[0][1]) +            self.download(streams[0][1]) diff --git a/pyload/plugins/hoster/UpstoreNet.py b/pyload/plugins/hoster/UpstoreNet.py new file mode 100644 index 000000000..9d1c4b3dd --- /dev/null +++ b/pyload/plugins/hoster/UpstoreNet.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha + + +class UpstoreNet(SimpleHoster): +    __name__ = "UpstoreNet" +    __type__ = "hoster" +    __pattern__ = r"https?://(?:www\.)?upstore\.net/" +    __version__ = "0.02" +    __description__ = """Upstore.Net File Download Hoster""" +    __author_name__ = ("igel") + +    FILE_INFO_PATTERN = r'<div class="comment">.*?</div>\s*\n<h2 style="margin:0">(?P<N>.*?)</h2>\s*\n<div class="comment">\s*\n\s*(?P<S>[\d.]+) (?P<U>\w+)' +    FILE_OFFLINE_PATTERN = r'<span class="error">File not found</span>' + +    WAIT_PATTERN = r"var sec = (\d+)" +    CHASH_PATTERN = r'<input type="hidden" name="hash" value="([^"]*)">' +    DIRECT_LINK_PATTERN = r'<a href="(https?://.*?)" target="_blank"><b>' + +    def handleFree(self): +        # STAGE 1: get link to continue +        m = re.search(self.CHASH_PATTERN, self.html) +        if not m: +            self.parseError("could not detect hash") +        chash = m.group(1) +        self.logDebug("read hash " + chash) +        # continue to stage2 +        post_data = {'hash': chash, 'free': 'Slow download'} +        self.html = self.load(self.pyfile.url, post=post_data, decode=True) + +        # STAGE 2: solv captcha and wait +        # first get the infos we need: recaptcha key and wait time +        recaptcha = ReCaptcha(self) +        if not recaptcha.detect_key(self.html): +            self.parseError("could not find recaptcha pattern") +        self.logDebug("using captcha key " + recaptcha.recaptcha_key) +        # try the captcha 5 times +        for i in xrange(5): +            m = re.search(self.WAIT_PATTERN, self.html) +            if not m: +                self.parseError("could not find wait pattern") +            wait_time = m.group(1) + +            # then, do the waiting +            self.wait(wait_time) + +            # then, handle the captcha +            challenge, code = recaptcha.challenge() +            post_data['recaptcha_challenge_field'] = challenge +            post_data['recaptcha_response_field'] = code + +            self.html = self.load(self.pyfile.url, post=post_data, decode=True) + +            # STAGE 3: get direct link +            m = re.search(self.DIRECT_LINK_PATTERN, self.html, re.DOTALL) +            if m: +                break + +        if not m: +            self.parseError("could not detect direct link") + +        direct = m.group(1) +        self.logDebug('found direct link: ' + direct) +        self.download(direct, disposition=True) + + +getInfo = create_getInfo(UpstoreNet) diff --git a/pyload/plugins/hoster/VeohCom.py b/pyload/plugins/hoster/VeohCom.py new file mode 100644 index 000000000..c1ebffb81 --- /dev/null +++ b/pyload/plugins/hoster/VeohCom.py @@ -0,0 +1,56 @@ +# -*- 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/>. +############################################################################ + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class VeohCom(SimpleHoster): +    __name__ = "VeohCom" +    __type__ = "hoster" +    __pattern__ = r'http://(?:www\.)?veoh\.com/(tv/)?(watch|videos)/(?P<ID>v\w+)' +    __version__ = "0.1" +    __config__ = [("quality", "Low;High", "Quality", "High")] +    __description__ = """Veoh.com hoster plugin""" +    __author_name__ = "Walter Purcaro" +    __author_mail__ = "vuolter@gmail.com" + +    FILE_NAME_PATTERN = r'<meta name="title" content="(?P<N>.*?)"' +    FILE_OFFLINE_PATTERN = r'>Sorry, we couldn\'t find the video you were looking for' + +    FILE_URL_REPLACEMENTS = [(__pattern__, r'http://www.veoh.com/watch/\g<ID>')] + +    SH_COOKIES = [(".veoh.com", "lassieLocale", "en")] + +    def setup(self): +        self.resumeDownload = self.multiDL = True +        self.chunkLimit = -1 + +    def handleFree(self): +        q = self.getConfig("quality") +        pattern = r'"fullPreviewHash%sPath":"(.+?)"' % q +        found = re.search(pattern, self.html) +        if found: +            self.pyfile.name += ".mp4" +            link = found.group(1).replace("\\", "") +            self.logDebug("Download link: " + link) +            self.download(link) +        else: +            self.fail("No %s quality video found" % q.lower()) + + +getInfo = create_getInfo(VeohCom) diff --git a/pyload/plugins/hoster/Vipleech4uCom.py b/pyload/plugins/hoster/Vipleech4uCom.py new file mode 100644 index 000000000..53768a430 --- /dev/null +++ b/pyload/plugins/hoster/Vipleech4uCom.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.Hoster import Hoster + + +class Vipleech4uCom(Hoster): +    __name__ = "Vipleech4uCom" +    __version__ = "0.1" +    __type__ = "hoster" +    __pattern__ = r"http://vipleech4u.com/manager.php" +    __description__ = """Vipleech4u.com hoster plugin""" +    __author_name__ = ("Kagenoshin") +    __author_mail__ = ("kagenoshin@gmx.ch") + +    FILENAME_PATTERN = re.compile(r'name\s*?=\s*?["\']filename["\'][^>]*?value\s*?=\s*?["\'](.*?)["\']', re.I) +    HOST_PATTERN = re.compile(r'name\s*?=\s*?["\']host["\'][^>]*?value\s*?=\s*?["\'](.*?)["\']', re.I) +    PATH_PATTERN = re.compile(r'name\s*?=\s*?["\']path["\'][^>]*?value\s*?=\s*?["\'](.*?)["\']', re.I) +    REFERER_PATTERN = re.compile(r'name\s*?=\s*?["\']referer["\'][^>]*?value\s*?=\s*?["\'](.*?)["\']', re.I) +    LINK_PATTERN = re.compile(r'name\s*?=\s*?["\']link["\'][^>]*?value\s*?=\s*?["\'](.*?)["\']', re.I) +    COOKIE_PATTERN = re.compile(r'name\s*?=\s*?["\']cookie["\'][^>]*?value\s*?=\s*?["\'](.*?)["\']', re.I) + +    def setup(self): +        self.resumeDownload = self.multiDL = True +        self.chunkLimit = 1 + +    def process(self, pyfile): +        if not self.account: +            self.logError(_("Please enter your %s account or deactivate this plugin") % "vipleech4u.com") +            self.fail("No vipleech4u.com account provided") + +        self.logDebug("Old URL: %s" % pyfile.url) + +        new_url = pyfile.url + +        if re.match(self.__pattern__, new_url): +            self.fail("Can't handle vipleech4u links.") + +        #upload the link which has to be loaded +        page = self.load('http://vipleech4u.com/generator.php', post={'links': new_url, 'ddl': 'no'}) + +        #switch to the manager and see what's happening +        page = self.load('http://vipleech4u.com/unrestrict.php', get={'link': new_url, 'premium_acc': 'on'}) + +        if re.search(r'You have generated maximum links available to you today', page, re.I): +            self.fail('Daily limit reached.') + +        filename = self.FILENAME_PATTERN.search(page) +        host = self.HOST_PATTERN.search(page) +        path = self.PATH_PATTERN.search(page) +        referer = self.REFERER_PATTERN.search(page) +        link = self.LINK_PATTERN.search(page) +        cookie = self.COOKIE_PATTERN.search(page) + +        #build the post-dictionary +        post_dict = {} + +        if filename: +            post_dict.update({'filename': filename.group(1)}) +        if host: +            post_dict.update({'host': host.group(1)}) +        if path: +            post_dict.update({'path': path.group(1)}) +        if referer: +            post_dict.update({'referer': referer.group(1)}) +        if link: +            post_dict.update({'link': link.group(1)}) +        if cookie: +            post_dict.update({'cookie': cookie.group(1)}) + +        if not post_dict: +            self.logDebug('Get an empty post_dict. Strange.') + +        self.setWait(5) +        self.wait() +        self.logDebug("Unrestricted URL: " + str(post_dict)) + +        self.download('http://vipleech4u.com/unrestrict.php', post=post_dict, disposition=True) + +        check = self.checkDownload({"bad": "<html"}) + +        if check == "bad": +            self.retry(24, 150, 'Bad file downloaded') | 
