diff options
Diffstat (limited to 'module/plugins/crypter')
87 files changed, 2026 insertions, 1729 deletions
diff --git a/module/plugins/crypter/BitshareComFolder.py b/module/plugins/crypter/BitshareComFolder.py index 2afe990df..c70a849b6 100644 --- a/module/plugins/crypter/BitshareComFolder.py +++ b/module/plugins/crypter/BitshareComFolder.py @@ -1,32 +1,24 @@ # -*- 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.SimpleCrypter import SimpleCrypter + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class BitshareComFolder(SimpleCrypter): - __name__ = "BitshareComFolder" - __version__ = "0.01" - __type__ = "crypter" + __name__ = "BitshareComFolder" + __type__ = "crypter" + __version__ = "0.03" __pattern__ = r'http://(?:www\.)?bitshare\.com/\?d=\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Bitshare.com folder decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] + + + LINK_PATTERN = r'<a href="(http://bitshare\.com/files/.+)">.+</a></td>' + NAME_PATTERN = r'View public folder "(?P<N>.+)"</h1>' + - LINK_PATTERN = r'<a href="(http://bitshare.com/files/.+)">.+</a></td>' - TITLE_PATTERN = r'View public folder "(?P<title>.+)"</h1>' +getInfo = create_getInfo(BitshareComFolder) diff --git a/module/plugins/crypter/C1neonCom.py b/module/plugins/crypter/C1neonCom.py index fc1188a11..bc58fbf1c 100644 --- a/module/plugins/crypter/C1neonCom.py +++ b/module/plugins/crypter/C1neonCom.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class C1neonCom(DeadCrypter): - __name__ = "C1neonCom" + __name__ = "C1neonCom" + __type__ = "crypter" __version__ = "0.05" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?c1neon.com/.*?' + __pattern__ = r'http://(?:www\.)?c1neon\.com/.+' + __config__ = [] __description__ = """C1neon.com decrypter plugin""" - __author_name__ = "godofdream" - __author_mail__ = "soilfiction@gmail.com" + __license__ = "GPLv3" + __authors__ = [("godofdream", "soilfiction@gmail.com")] + + +getInfo = create_getInfo(C1neonCom) diff --git a/module/plugins/crypter/ChipDe.py b/module/plugins/crypter/ChipDe.py index f59903170..133e5a005 100644 --- a/module/plugins/crypter/ChipDe.py +++ b/module/plugins/crypter/ChipDe.py @@ -5,23 +5,25 @@ from module.plugins.Crypter import Crypter class ChipDe(Crypter): - __name__ = "ChipDe" - __version__ = "0.1" - __type__ = "crypter" + __name__ = "ChipDe" + __type__ = "crypter" + __version__ = "0.10" - __pattern__ = r'http://(?:www\.)?chip.de/video/.*\.html' + __pattern__ = r'http://(?:www\.)?chip\.de/video/.+\.html' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Chip.de decrypter plugin""" - __author_name__ = "4Christopher" - __author_mail__ = "4Christopher@gmx.de" + __license__ = "GPLv3" + __authors__ = [("4Christopher", "4Christopher@gmx.de")] def decrypt(self, pyfile): self.html = self.load(pyfile.url) try: - f = re.search(r'"(http://video.chip.de/\d+?/.*)"', self.html) + f = re.search(r'"(http://video\.chip\.de/.+)"', self.html) except: - self.fail('Failed to find the URL') + self.fail(_("Failed to find the URL")) else: self.urls = [f.group(1)] - self.logDebug('The file URL is %s' % self.urls[0]) + self.logDebug("The file URL is %s" % self.urls[0]) diff --git a/module/plugins/crypter/CloudzillaToFolder.py b/module/plugins/crypter/CloudzillaToFolder.py new file mode 100644 index 000000000..c156d4de4 --- /dev/null +++ b/module/plugins/crypter/CloudzillaToFolder.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +import re + +from urlparse import urljoin + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class CloudzillaToFolder(SimpleHoster): + __name__ = "CloudzillaToFolder" + __type__ = "crypter" + __version__ = "0.01" + + __pattern__ = r'http://(?:www\.)?cloudzilla\.to/share/folder/(?P<ID>[\w^_]+)' + + __description__ = """Cloudzilla.to folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + INFO_PATTERN = r'<span class="name" title="(?P<N>.+?)"' + OFFLINE_PATTERN = r'>File not found...<' + + LINK_PATTERN = r'<a href="(.+?)" class="item_href">' + + PASSWORD_PATTERN = r'<div id="pwd_protected">' + + + def checkErrors(self): + m = re.search(self.PASSWORD_PATTERN, self.html) + if m: + self.html = self.load(self.pyfile.url, get={'key': self.getPassword()}) + + if re.search(self.PASSWORD_PATTERN, self.html): + self.retry(reason="Wrong password") + + + def getLinks(self): + return [urljoin("http://www.cloudzilla.to", link) for link in super(CloudzillaToFolder, self).getLinks()] + + +getInfo = create_getInfo(CloudzillaToFolder) diff --git a/module/plugins/crypter/CrockoComFolder.py b/module/plugins/crypter/CrockoComFolder.py index 8215e23c4..57bb339ff 100644 --- a/module/plugins/crypter/CrockoComFolder.py +++ b/module/plugins/crypter/CrockoComFolder.py @@ -1,17 +1,23 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class CrockoComFolder(SimpleCrypter): - __name__ = "CrockoComFolder" + __name__ = "CrockoComFolder" + __type__ = "crypter" __version__ = "0.01" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?crocko.com/f/.*' + __pattern__ = r'http://(?:www\.)?crocko\.com/f/.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Crocko.com folder decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + LINK_PATTERN = r'<td class="last"><a href="([^"]+)">download</a>' + + +getInfo = create_getInfo(CrockoComFolder) diff --git a/module/plugins/crypter/CryptItCom.py b/module/plugins/crypter/CryptItCom.py index 331ddd5c8..2cf4e9f62 100644 --- a/module/plugins/crypter/CryptItCom.py +++ b/module/plugins/crypter/CryptItCom.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class CryptItCom(DeadCrypter): - __name__ = "CryptItCom" + __name__ = "CryptItCom" + __type__ = "crypter" __version__ = "0.11" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?crypt-it\.com/(s|e|d|c)/[\w]+' + __pattern__ = r'http://(?:www\.)?crypt-it\.com/(s|e|d|c)/\w+' + __config__ = [] __description__ = """Crypt-it.com decrypter plugin""" - __author_name__ = "jeix" - __author_mail__ = "jeix@hasnomail.de" + __license__ = "GPLv3" + __authors__ = [("jeix", "jeix@hasnomail.de")] + + +getInfo = create_getInfo(CryptItCom) diff --git a/module/plugins/crypter/CzshareComFolder.py b/module/plugins/crypter/CzshareComFolder.py index b305575a2..5623a4093 100644 --- a/module/plugins/crypter/CzshareComFolder.py +++ b/module/plugins/crypter/CzshareComFolder.py @@ -5,15 +5,18 @@ from module.plugins.Crypter import Crypter class CzshareComFolder(Crypter): - __name__ = "CzshareComFolder" - __version__ = "0.2" - __type__ = "crypter" + __name__ = "CzshareComFolder" + __type__ = "crypter" + __version__ = "0.20" - __pattern__ = r'http://(?:www\.)?(czshare|sdilej)\.(com|cz)/folders/.*' + __pattern__ = r'http://(?:www\.)?(czshare|sdilej)\.(com|cz)/folders/.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Czshare.com folder decrypter plugin, now Sdilej.cz""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + FOLDER_PATTERN = r'<tr class="subdirectory">\s*<td>\s*<table>(.*?)</table>' LINK_PATTERN = r'<td class="col2"><a href="([^"]+)">info</a></td>' @@ -22,10 +25,8 @@ class CzshareComFolder(Crypter): def decrypt(self, pyfile): html = self.load(pyfile.url) - m = re.search(self.FOLDER_PATTERN, html, re.DOTALL) + m = re.search(self.FOLDER_PATTERN, html, re.S) if m is None: - self.fail("Parse error (FOLDER)") + self.error(_("FOLDER_PATTERN not found")) self.urls.extend(re.findall(self.LINK_PATTERN, m.group(1))) - if not self.urls: - self.fail('Could not extract any links') diff --git a/module/plugins/crypter/DDLMusicOrg.py b/module/plugins/crypter/DDLMusicOrg.py index c80ec471e..55181e9ad 100644 --- a/module/plugins/crypter/DDLMusicOrg.py +++ b/module/plugins/crypter/DDLMusicOrg.py @@ -8,27 +8,30 @@ from module.plugins.Crypter import Crypter class DDLMusicOrg(Crypter): - __name__ = "DDLMusicOrg" - __version__ = "0.3" - __type__ = "crypter" + __name__ = "DDLMusicOrg" + __type__ = "crypter" + __version__ = "0.30" __pattern__ = r'http://(?:www\.)?ddl-music\.org/captcha/ddlm_cr\d\.php\?\d+\?\d+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Ddl-music.org decrypter plugin""" - __author_name__ = "mkaay" - __author_mail__ = "mkaay@mkaay.de" + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] def setup(self): self.multiDL = False + def decrypt(self, pyfile): - html = self.req.load(pyfile.url, cookies=True) + html = self.load(pyfile.url, cookies=True) if re.search(r"Wer dies nicht rechnen kann", html) is not None: self.offline() - math = re.search(r"(\d+) ([\+-]) (\d+) =\s+<inp", self.html) + math = re.search(r"(\d+) ([+-]) (\d+) =\s+<inp", self.html) id = re.search(r"name=\"id\" value=\"(\d+)\"", self.html).group(1) linknr = re.search(r"name=\"linknr\" value=\"(\d+)\"", self.html).group(1) @@ -38,7 +41,7 @@ class DDLMusicOrg(Crypter): else: solve = int(math.group(1)) - int(math.group(3)) sleep(3) - htmlwithlink = self.req.load(pyfile.url, cookies=True, + htmlwithlink = self.load(pyfile.url, cookies=True, post={"calc%s" % linknr: solve, "send%s" % linknr: "Send", "id": id, "linknr": linknr}) m = re.search(r"<form id=\"ff\" action=\"(.*?)\" method=\"post\">", htmlwithlink) diff --git a/module/plugins/crypter/DailymotionBatch.py b/module/plugins/crypter/DailymotionBatch.py index c86c966d8..8d4cb64df 100644 --- a/module/plugins/crypter/DailymotionBatch.py +++ b/module/plugins/crypter/DailymotionBatch.py @@ -1,22 +1,8 @@ # -*- 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/>. -""" +import re from urlparse import urljoin -import re from module.common.json_layer import json_loads from module.plugins.Crypter import Crypter @@ -24,15 +10,17 @@ from module.utils import save_join class DailymotionBatch(Crypter): - __name__ = "DailymotionBatch" + __name__ = "DailymotionBatch" + __type__ = "crypter" __version__ = "0.01" - __type__ = "crypter" __pattern__ = r'https?://(?:www\.)?dailymotion\.com/((playlists/)?(?P<TYPE>playlist|user)/)?(?P<ID>[\w^_]+)(?(TYPE)|#)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Dailymotion.com channel & playlist decrypter""" - __author_name__ = "Walter Purcaro" - __author_mail__ = "vuolter@gmail.com" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] def api_response(self, ref, req=None): @@ -40,6 +28,7 @@ class DailymotionBatch(Crypter): page = self.load(url, get=req) return json_loads(page) + def getPlaylistInfo(self, id): ref = "playlist/" + id req = {"fields": "name,owner.screenname"} @@ -52,6 +41,7 @@ class DailymotionBatch(Crypter): 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} @@ -67,9 +57,11 @@ class DailymotionBatch(Crypter): 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} @@ -85,13 +77,15 @@ class DailymotionBatch(Crypter): 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") + m_id = m.group('ID') + m_type = m.group('TYPE') if m_type == "playlist": self.logDebug("Url recognized as Playlist") @@ -103,7 +97,7 @@ class DailymotionBatch(Crypter): self.logDebug("%s playlist\s found on channel \"%s\"" % (len(playlists), m_id)) if not playlists: - self.fail("No playlist available") + self.fail(_("No playlist available")) for p_id, p_name, p_owner in playlists: p_videos = self.getVideos(p_id) diff --git a/module/plugins/crypter/DataHuFolder.py b/module/plugins/crypter/DataHuFolder.py index 553936b1a..a5602d6c6 100644 --- a/module/plugins/crypter/DataHuFolder.py +++ b/module/plugins/crypter/DataHuFolder.py @@ -1,57 +1,43 @@ # -*- coding: utf-8 -*- -############################################################################ -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the GNU Affero General Public License as # -# published by the Free Software Foundation, either version 3 of the # -# License, or (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU Affero General Public License for more details. # -# # -# You should have received a copy of the GNU Affero General Public License # -# along with this program. If not, see <http://www.gnu.org/licenses/>. # -############################################################################ import re -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class DataHuFolder(SimpleCrypter): - __name__ = "DataHuFolder" - __version__ = "0.03" - __type__ = "crypter" + __name__ = "DataHuFolder" + __type__ = "crypter" + __version__ = "0.06" - __pattern__ = r'http://(?:www\.)?data.hu/dir/\w+' + __pattern__ = r'http://(?:www\.)?data\.hu/dir/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Data.hu folder decrypter plugin""" - __author_name__ = ("crash", "stickell") - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("crash", None), + ("stickell", "l.stickell@yahoo.it")] - LINK_PATTERN = r"<a href='(http://data\.hu/get/.+)' target='_blank'>\1</a>" - TITLE_PATTERN = ur'<title>(?P<title>.+) Let\xf6lt\xe9se</title>' + LINK_PATTERN = r'<a href=\'(http://data\.hu/get/.+)\' target=\'_blank\'>\1</a>' + NAME_PATTERN = ur'<title>(?P<N>.+) Let\xf6lt\xe9se</title>' - def decrypt(self, pyfile): - self.html = self.load(pyfile.url, decode=True) + + def prepare(self): + super(DataHuFolder, self).prepare() if u'K\xe9rlek add meg a jelsz\xf3t' in self.html: # Password protected password = self.getPassword() - if password is '': - self.fail("No password specified, please set right password on Add package form and retry") - self.logDebug('The folder is password protected', 'Using password: ' + password) - self.html = self.load(pyfile.url, post={'mappa_pass': password}, decode=True) - if u'Hib\xe1s jelsz\xf3' in self.html: # Wrong password - self.fail("Incorrect password, please set right password on Add package form and retry") + if not password: + self.fail(_("Password required")) + + self.logDebug("The folder is password protected', 'Using password: " + password) - package_name, folder_name = self.getPackageNameAndFolder() + self.html = self.load(self.pyfile.url, post={'mappa_pass': password}, decode=True) + + if u'Hib\xe1s jelsz\xf3' in self.html: # Wrong password + self.fail(_("Wrong password")) - package_links = re.findall(self.LINK_PATTERN, self.html) - self.logDebug('Package has %d links' % len(package_links)) - if package_links: - self.packages = [(package_name, package_links, folder_name)] - else: - self.fail('Could not extract any links') +getInfo = create_getInfo(DataHuFolder) diff --git a/module/plugins/crypter/DdlstorageComFolder.py b/module/plugins/crypter/DdlstorageComFolder.py index 4c79407e4..e02e77fda 100644 --- a/module/plugins/crypter/DdlstorageComFolder.py +++ b/module/plugins/crypter/DdlstorageComFolder.py @@ -1,31 +1,20 @@ # -*- 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.SimpleCrypter import SimpleCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo -class DdlstorageComFolder(SimpleCrypter): - __name__ = "DdlstorageComFolder" - __version__ = "0.02" - __type__ = "crypter" +class DdlstorageComFolder(DeadCrypter): + __name__ = "DdlstorageComFolder" + __type__ = "crypter" + __version__ = "0.03" - __pattern__ = r'http://(?:www\.)?ddlstorage.com/folder/\w{10}' + __pattern__ = r'https?://(?:www\.)?ddlstorage\.com/folder/\w+' + __config__ = [] __description__ = """DDLStorage.com folder decrypter plugin""" - __author_name__ = ("godofdream", "stickell") - __author_mail__ = ("soilfiction@gmail.com", "l.stickell@yahoo.it") + __license__ = "GPLv3" + __authors__ = [("godofdream", "soilfiction@gmail.com"), + ("stickell", "l.stickell@yahoo.it")] - LINK_PATTERN = r'<a class="sub_title" style="text-decoration:none;" href="(http://www.ddlstorage.com/.*)">' + +getInfo = create_getInfo(DdlstorageComFolder) diff --git a/module/plugins/crypter/DepositfilesComFolder.py b/module/plugins/crypter/DepositfilesComFolder.py index bb08b627b..147f093c3 100644 --- a/module/plugins/crypter/DepositfilesComFolder.py +++ b/module/plugins/crypter/DepositfilesComFolder.py @@ -1,17 +1,23 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class DepositfilesComFolder(SimpleCrypter): - __name__ = "DepositfilesComFolder" + __name__ = "DepositfilesComFolder" + __type__ = "crypter" __version__ = "0.01" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?depositfiles.com/folders/\w+' + __pattern__ = r'http://(?:www\.)?depositfiles\.com/folders/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Depositfiles.com folder decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + LINK_PATTERN = r'<div class="progressName"[^>]*>\s*<a href="([^"]+)" title="[^"]*" target="_blank">' + + +getInfo = create_getInfo(DepositfilesComFolder) diff --git a/module/plugins/crypter/Dereferer.py b/module/plugins/crypter/Dereferer.py index 405893560..0729c8cb6 100644 --- a/module/plugins/crypter/Dereferer.py +++ b/module/plugins/crypter/Dereferer.py @@ -1,38 +1,17 @@ # -*- 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. +from module.plugins.internal.SimpleDereferer import SimpleDereferer - 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/>. -""" +class Dereferer(SimpleDereferer): + __name__ = "Dereferer" + __type__ = "crypter" + __version__ = "0.11" -import re -import urllib - -from module.plugins.Crypter import Crypter - - -class Dereferer(Crypter): - __name__ = "Dereferer" - __version__ = "0.1" - __type__ = "crypter" - - __pattern__ = r'https?://([^/]+)/.*?(?P<url>(ht|f)tps?(://|%3A%2F%2F).*)' + __pattern__ = r'https?://([^/]+)/.*?(?P<LINK>(ht|f)tps?(://|%3A%2F%2F).+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Crypter for dereferers""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" - - - def decrypt(self, pyfile): - link = re.match(self.__pattern__, pyfile.url).group('url') - self.urls = [urllib.unquote(link).rstrip('+')] + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] diff --git a/module/plugins/crypter/DevhostStFolder.py b/module/plugins/crypter/DevhostStFolder.py new file mode 100644 index 000000000..5ac9d4faf --- /dev/null +++ b/module/plugins/crypter/DevhostStFolder.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# +# Test links: +# http://d-h.st/users/shine/?fld_id=37263#files + +import re + +from urlparse import urljoin + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class DevhostStFolder(SimpleCrypter): + __name__ = "DevhostStFolder" + __type__ = "crypter" + __version__ = "0.03" + + __pattern__ = r'http://(?:www\.)?d-h\.st/users/(?P<USER>\w+)(/\?fld_id=(?P<ID>\d+))?' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """d-h.st folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"), + ("Walter Purcaro", "vuolter@gmail.com")] + + + LINK_PATTERN = r'(?:/> |;">)<a href="(.+?)"(?!>Back to \w+<)' + OFFLINE_PATTERN = r'"/cHP">test\.png<' + + + def getFileInfo(self): + if re.search(self.OFFLINE_PATTERN, self.html): + self.offline() + + try: + id = re.match(self.__pattern__, self.pyfile.url).group('ID') + if id == "0": + raise + + p = r'href="(.+?)">Back to \w+<' + m = re.search(p, self.html) + html = self.load(urljoin("http://d-h.st", m.group(1)), + cookies=False) + + p = '\?fld_id=%s.*?">(.+?)<' % id + m = re.search(p, html) + name = folder = m.group(1) + + except Exception, e: + self.logDebug(e) + name = folder = re.match(self.__pattern__, self.pyfile.url).group('USER') + + return {'name': name, 'folder': folder} + + + def getLinks(self): + return [urljoin("http://d-h.st", link) for link in re.findall(self.LINK_PATTERN, self.html)] + + +getInfo = create_getInfo(DevhostStFolder) diff --git a/module/plugins/crypter/DlProtectCom.py b/module/plugins/crypter/DlProtectCom.py index 6bd6bc5b5..a99ed0be9 100644 --- a/module/plugins/crypter/DlProtectCom.py +++ b/module/plugins/crypter/DlProtectCom.py @@ -1,37 +1,26 @@ # -*- 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 base64 import urlsafe_b64encode from time import time -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class DlProtectCom(SimpleCrypter): - __name__ = "DlProtectCom" + __name__ = "DlProtectCom" + __type__ = "crypter" __version__ = "0.01" - __type__ = "crypter" __pattern__ = r'http://(?:www\.)?dl-protect\.com/((en|fr)/)?(?P<ID>\w+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Dl-protect.com decrypter plugin""" - __author_name__ = "Walter Purcaro" - __author_mail__ = "vuolter@gmail.com" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + OFFLINE_PATTERN = r'>Unfortunately, the link you are looking for is not found' @@ -41,7 +30,7 @@ class DlProtectCom(SimpleCrypter): 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") + #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": ""} @@ -70,7 +59,10 @@ class DlProtectCom(SimpleCrypter): for errmsg in (">The password is incorrect", ">The security code is incorrect"): if errmsg in self.html: - self.fail(errmsg[1:]) + self.fail(_(errmsg[1:])) pattern = r'<a href="([^/].+?)" target="_blank">' return re.findall(pattern, self.html) + + +getInfo = create_getInfo(DlProtectCom) diff --git a/module/plugins/crypter/DontKnowMe.py b/module/plugins/crypter/DontKnowMe.py index dac385e7c..d656cde4c 100644 --- a/module/plugins/crypter/DontKnowMe.py +++ b/module/plugins/crypter/DontKnowMe.py @@ -1,25 +1,17 @@ # -*- coding: utf-8 -*- -import re -import urllib +from module.plugins.internal.SimpleDereferer import SimpleDereferer -from module.plugins.Crypter import Crypter +class DontKnowMe(SimpleDereferer): + __name__ = "DontKnowMe" + __type__ = "crypter" + __version__ = "0.11" -class DontKnowMe(Crypter): - __name__ = "DontKnowMe" - __version__ = "0.1" - __type__ = "crypter" - - __pattern__ = r'http://(?:www\.)?dontknow.me/at/\?.+$' + __pattern__ = r'http://(?:www\.)?dontknow\.me/at/\?(?P<LINK>.+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """DontKnow.me decrypter plugin""" - __author_name__ = "selaux" - __author_mail__ = None - - LINK_PATTERN = r'http://dontknow.me/at/\?(.+)$' - - - def decrypt(self, pyfile): - link = re.findall(self.LINK_PATTERN, pyfile.url)[0] - self.urls = [urllib.unquote(link)] + __license__ = "GPLv3" + __authors__ = [("selaux", "")] diff --git a/module/plugins/crypter/DuckCryptInfo.py b/module/plugins/crypter/DuckCryptInfo.py index 7e13a62f0..07cc5cdc4 100644 --- a/module/plugins/crypter/DuckCryptInfo.py +++ b/module/plugins/crypter/DuckCryptInfo.py @@ -1,57 +1,59 @@ # -*- coding: utf-8 -*- import re -from module.lib.BeautifulSoup import BeautifulSoup + +from BeautifulSoup import BeautifulSoup + from module.plugins.Crypter import Crypter class DuckCryptInfo(Crypter): - __name__ = "DuckCryptInfo" + __name__ = "DuckCryptInfo" + __type__ = "crypter" __version__ = "0.02" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?duckcrypt.info/(folder|wait|link)/(\w+)/?(\w*)' + __pattern__ = r'http://(?:www\.)?duckcrypt\.info/(folder|wait|link)/(\w+)/?(\w*)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """DuckCrypt.info decrypter plugin""" - __author_name__ = "godofdream" - __author_mail__ = "soilfiction@gmail.com" + __license__ = "GPLv3" + __authors__ = [("godofdream", "soilfiction@gmail.com")] + TIMER_PATTERN = r'<span id="timer">(.*)</span>' def decrypt(self, pyfile): url = pyfile.url - # seems we don't need to wait - #src = self.req.load(str(url)) - #m = re.search(self.TIMER_PATTERN, src) - #if m: - # self.logDebug("Sleeping for" % m.group(1)) - # self.setWait(int(m.group(1)) ,False) + m = re.match(self.__pattern__, url) if m is None: - self.fail('Weird error in link') + self.fail(_("Weird error in link")) if str(m.group(1)) == "link": self.handleLink(url) else: self.handleFolder(m) + def handleFolder(self, m): - src = self.load("http://duckcrypt.info/ajax/auth.php?hash=" + str(m.group(2))) - m = re.match(self.__pattern__, src) + html = self.load("http://duckcrypt.info/ajax/auth.php?hash=" + str(m.group(2))) + m = re.match(self.__pattern__, html) self.logDebug("Redirectet to " + str(m.group(0))) - src = self.load(str(m.group(0))) - soup = BeautifulSoup(src) + html = self.load(str(m.group(0))) + soup = BeautifulSoup(html) cryptlinks = soup.findAll("div", attrs={"class": "folderbox"}) self.logDebug("Redirectet to " + str(cryptlinks)) if not cryptlinks: - self.fail('no links m - (Plugin out of date?)') + self.error(_("No link found")) for clink in cryptlinks: if clink.find("a"): self.handleLink(clink.find("a")['href']) + def handleLink(self, url): - src = self.load(url) - soup = BeautifulSoup(src) - self.urls = [soup.find("iframe")["src"]] + html = self.load(url) + soup = BeautifulSoup(html) + self.urls = [soup.find("iframe")['src']] if not self.urls: - self.logDebug('no links m - (Plugin out of date?)') + self.logInfo(_("No link found")) diff --git a/module/plugins/crypter/DuploadOrgFolder.py b/module/plugins/crypter/DuploadOrgFolder.py index f2b8da2bd..066fbe3d7 100644 --- a/module/plugins/crypter/DuploadOrgFolder.py +++ b/module/plugins/crypter/DuploadOrgFolder.py @@ -1,31 +1,19 @@ # -*- 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.SimpleCrypter import SimpleCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo -class DuploadOrgFolder(SimpleCrypter): - __name__ = "DuploadOrgFolder" - __version__ = "0.01" - __type__ = "crypter" +class DuploadOrgFolder(DeadCrypter): + __name__ = "DuploadOrgFolder" + __type__ = "crypter" + __version__ = "0.02" - __pattern__ = r'http://(?:www\.)?dupload\.org/folder/\d+/' + __pattern__ = r'http://(?:www\.)?dupload\.org/folder/\d+' + __config__ = [] __description__ = """Dupload.org folder decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] - LINK_PATTERN = r'<td style="[^"]+"><a href="(http://[^"]+)" target="_blank">[^<]+</a></td>' + +getInfo = create_getInfo(DuploadOrgFolder) diff --git a/module/plugins/crypter/EasybytezComFolder.py b/module/plugins/crypter/EasybytezComFolder.py index 7c78b7946..04f9b853b 100644 --- a/module/plugins/crypter/EasybytezComFolder.py +++ b/module/plugins/crypter/EasybytezComFolder.py @@ -1,34 +1,25 @@ # -*- 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.SimpleCrypter import SimpleCrypter - - -class EasybytezComFolder(SimpleCrypter): - __name__ = "EasybytezComFolder" - __version__ = "0.06" - __type__ = "crypter" - - __pattern__ = r'http://(?:www\.)?easybytez\.com/users/(?P<ID>\d+/\d+)' - - __description__ = """Easybytez.com decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" - - URL_REPLACEMENTS = [(__pattern__, r"http://www.easybytez.com/users/\g<ID>?per_page=10000")] - - LINK_PATTERN = r'<td><a href="(http://www\.easybytez\.com/\w+)" target="_blank">.+(?:</a>)?</td>' - TITLE_PATTERN = r'<Title>Files of \d+: (?P<title>.+) folder</Title>' + +from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo + + +class EasybytezComFolder(XFSCrypter): + __name__ = "EasybytezComFolder" + __type__ = "crypter" + __version__ = "0.10" + + __pattern__ = r'http://(?:www\.)?easybytez\.com/users/\d+/\d+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """Easybytez.com folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] + + + HOSTER_DOMAIN = "easybytez.com" + + LOGIN_ACCOUNT = True + + +getInfo = create_getInfo(EasybytezComFolder) diff --git a/module/plugins/crypter/EmbeduploadCom.py b/module/plugins/crypter/EmbeduploadCom.py index 052f5ca84..be3181793 100644 --- a/module/plugins/crypter/EmbeduploadCom.py +++ b/module/plugins/crypter/EmbeduploadCom.py @@ -6,17 +6,20 @@ from module.network.HTTPRequest import BadHeader class EmbeduploadCom(Crypter): - __name__ = "EmbeduploadCom" + __name__ = "EmbeduploadCom" + __type__ = "crypter" __version__ = "0.02" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?embedupload.com/\?d=.*' - __config__ = [("preferedHoster", "str", "Prefered hoster list (bar-separated) ", "embedupload"), - ("ignoredHoster", "str", "Ignored hoster list (bar-separated) ", "")] + __pattern__ = r'http://(?:www\.)?embedupload\.com/\?d=.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True), + ("preferedHoster", "str", "Prefered hoster list (bar-separated)", "embedupload"), + ("ignoredHoster", "str", "Ignored hoster list (bar-separated)", "")] __description__ = """EmbedUpload.com decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + LINK_PATTERN = r'<div id="([^"]+)"[^>]*>\s*<a href="([^"]+)" target="_blank" (?:class="DownloadNow"|style="color:red")>' @@ -29,26 +32,28 @@ class EmbeduploadCom(Crypter): if m: prefered_set = set(self.getConfig("preferedHoster").split('|')) prefered_set = map(lambda s: s.lower().split('.')[0], prefered_set) - print "PF", prefered_set + + self.logDebug("PF: %s" % prefered_set) + tmp_links.extend([x[1] for x in m if x[0] in prefered_set]) self.urls = self.getLocation(tmp_links) if not self.urls: ignored_set = set(self.getConfig("ignoredHoster").split('|')) ignored_set = map(lambda s: s.lower().split('.')[0], ignored_set) - print "IG", ignored_set + + self.logDebug("IG: %s" % ignored_set) + tmp_links.extend([x[1] for x in m if x[0] not in ignored_set]) self.urls = self.getLocation(tmp_links) - if not self.urls: - self.fail('Could not extract any links') def getLocation(self, tmp_links): new_links = [] for link in tmp_links: try: header = self.load(link, just_header=True) - if "location" in header: + if 'location' in header: new_links.append(header['location']) except BadHeader: pass diff --git a/module/plugins/crypter/FilebeerInfoFolder.py b/module/plugins/crypter/FilebeerInfoFolder.py index 7a7528066..a3c7ee74c 100644 --- a/module/plugins/crypter/FilebeerInfoFolder.py +++ b/module/plugins/crypter/FilebeerInfoFolder.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class FilebeerInfoFolder(DeadCrypter): - __name__ = "FilebeerInfoFolder" + __name__ = "FilebeerInfoFolder" + __type__ = "crypter" __version__ = "0.02" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?filebeer\.info/(\d+~f).*' + __pattern__ = r'http://(?:www\.)?filebeer\.info/\d*~f\w+' + __config__ = [] __description__ = """Filebeer.info folder decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + + +getInfo = create_getInfo(FilebeerInfoFolder) diff --git a/module/plugins/crypter/FilecloudIoFolder.py b/module/plugins/crypter/FilecloudIoFolder.py index d3df7c469..83cce352d 100644 --- a/module/plugins/crypter/FilecloudIoFolder.py +++ b/module/plugins/crypter/FilecloudIoFolder.py @@ -1,32 +1,24 @@ # -*- 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.SimpleCrypter import SimpleCrypter + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FilecloudIoFolder(SimpleCrypter): - __name__ = "FilecloudIoFolder" - __version__ = "0.01" - __type__ = "crypter" + __name__ = "FilecloudIoFolder" + __type__ = "crypter" + __version__ = "0.03" __pattern__ = r'https?://(?:www\.)?(filecloud\.io|ifile\.it)/_\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Filecloud.io folder decrypter plugin""" - __author_name__ = "Walter Purcaro" - __author_mail__ = "vuolter@gmail.com" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + LINK_PATTERN = r'href="(http://filecloud\.io/\w+)" title' + NAME_PATTERN = r'>(?P<N>.+?) - filecloud\.io<' + - LINK_PATTERN = r'href="(http://filecloud.io/\w+)" title' - TITLE_PATTERN = r'>(?P<title>.+?) - filecloud.io<' +getInfo = create_getInfo(FilecloudIoFolder) diff --git a/module/plugins/crypter/FilecryptCc.py b/module/plugins/crypter/FilecryptCc.py new file mode 100644 index 000000000..087f377ff --- /dev/null +++ b/module/plugins/crypter/FilecryptCc.py @@ -0,0 +1,170 @@ +# -*- coding: utf-8 -*- + +import base64 +import binascii +import re + +from Crypto.Cipher import AES +from urlparse import urljoin + +from module.plugins.Crypter import Crypter + + +class FilecryptCc(Crypter): + __name__ = "FilecryptCc" + __type__ = "crypter" + __version__ = "0.07" + + __pattern__ = r'https?://(?:www\.)?filecrypt\.cc/Container/\w+' + + __description__ = """Filecrypt.cc decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("zapp-brannigan", "")] + + + # URL_REPLACEMENTS = [(r'.html$', ""), (r'$', ".html")] #@TODO: Extend SimpleCrypter + + DLC_LINK_PATTERN = r'<button class="dlcdownload" type="button" title="Download \*.dlc" onclick="DownloadDLC\(\'(.+)\'\);"><i></i><span>dlc<' + WEBLINK_PATTERN = r"openLink.?'([\w_-]*)'," + + CAPTCHA_PATTERN = r'<img id="nc" src="(.+?)"' + CIRCLE_CAPTCHA_PATTERN = r'<input type="image" src="(.+?)"' + + MIRROR_PAGE_PATTERN = r'"[\w]*" href="(http://filecrypt.cc/Container/\w+\.html\?mirror=\d+)">' + + + def setup(self): + self.links = [] + + + def decrypt(self, pyfile): + self.html = self.load(pyfile.url, cookies=True) + + if "content notfound" in self.html: #@NOTE: "content notfound" is NOT a typo + self.offline() + + self.handlePasswordProtection() + self.handleCaptcha() + self.handleMirrorPages() + + for handle in (self.handleCNL, self.handleWeblinks, self.handleDlcContainer): + handle() + if self.links: + self.packages = [(pyfile.package().name, self.links, pyfile.package().name)] + return + + + def handleMirrorPages(self): + if "mirror=" not in self.siteWithLinks: + return + + mirror = re.findall(self.MIRROR_PAGE_PATTERN, self.siteWithLinks) + + self.logInfo(_("Found %d mirrors") % len(mirror)) + + for i in mirror[1:]: + self.siteWithLinks = self.siteWithLinks + self.load(i, cookies=True).decode("utf-8", "replace") + + + def handlePasswordProtection(self): + if '<input type="text" name="password"' not in self.html: + return + + self.logInfo(_("Folder is password protected")) + + if not self.pyfile.package().password: + self.fail(_("Please enter the password in package section and try again")) + + self.html = self.load(self.pyfile.url, post={"password": self.password}, cookies=True) + + + def handleCaptcha(self): + m = re.search(self.CAPTCHA_PATTERN, self.html) + m2 = re.search(self.CIRCLE_CAPTCHA_PATTERN, self.html) + + if m: #: normal captcha + self.logDebug("Captcha-URL: %s" % m.group(1)) + + captcha_code = self.decryptCaptcha(urljoin("http://filecrypt.cc", m.group(1)), + forceUser=True, + imgtype="gif") + + self.siteWithLinks = self.load(self.pyfile.url, + post={'recaptcha_response_field': captcha_code}, + cookies=True, + decode=True) + elif m2: #: circle captcha + self.logDebug("Captcha-URL: %s" % m2.group(1)) + + captcha_code = self.decryptCaptcha(urljoin("http://filecrypt.cc", m2.group(1)), + forceUser=True, + imgtype="gif", + result_type='positional') + + self.siteWithLinks = self.load(self.pyfile.url, + post={'button.x': captcha_code[0], 'button.y': captcha_code[1]}, + cookies=True, + decode=True) + else: + self.logDebug("No captcha found") + self.siteWithLinks = self.html + + if "recaptcha_image" in self.siteWithLinks: + self.invalidCaptcha() + self.retry() + + + def handleDlcContainer(self): + dlc = re.findall(self.DLC_LINK_PATTERN, self.siteWithLinks) + + if not dlc: + return + + for i in dlc: + self.links.append("http://filecrypt.cc/DLC/%s.dlc" % i) + + + def handleWeblinks(self): + try: + weblinks = re.findall(self.WEBLINK_PATTERN, self.siteWithLinks) + + for link in weblinks: + res = self.load("http://filecrypt.cc/Link/%s.html" % link, cookies=True) + link2 = re.search('<iframe noresize src="(.*)"></iframe>', res) + res2 = self.load(link2.group(1), just_header=True, cookies=True) + self.links.append(res2['location']) + + except Exception, e: + self.logDebug("Error decrypting weblinks: %s" % e) + + + def handleCNL(self): + try: + vjk = re.findall('<input type="hidden" name="jk" value="function f\(\){ return \'(.*)\';}">', self.siteWithLinks) + vcrypted = re.findall('<input type="hidden" name="crypted" value="(.*)">', self.siteWithLinks) + + for i in xrange(len(vcrypted)): + self.links.extend(self._getLinks(vcrypted[i], vjk[i])) + + except Exception, e: + self.logDebug("Error decrypting CNL: %s" % e) + + + def _getLinks(self, crypted, jk): + # Get key + key = binascii.unhexlify(str(jk)) + + # Decode crypted + crypted = base64.standard_b64decode(crypted) + + # Decrypt + Key = key + IV = key + obj = AES.new(Key, AES.MODE_CBC, IV) + text = obj.decrypt(crypted) + + # Extract links + links = filter(lambda x: x != "", + text.replace("\x00", "").replace("\r", "").split("\n")) + + return links diff --git a/module/plugins/crypter/FilefactoryComFolder.py b/module/plugins/crypter/FilefactoryComFolder.py index ce20ee6eb..26e28acbd 100644 --- a/module/plugins/crypter/FilefactoryComFolder.py +++ b/module/plugins/crypter/FilefactoryComFolder.py @@ -1,25 +1,31 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FilefactoryComFolder(SimpleCrypter): - __name__ = "FilefactoryComFolder" - __version__ = "0.2" - __type__ = "crypter" + __name__ = "FilefactoryComFolder" + __type__ = "crypter" + __version__ = "0.31" __pattern__ = r'https?://(?:www\.)?filefactory\.com/(?:f|folder)/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Filefactory.com folder decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] + LINK_PATTERN = r'<td><a href="([^"]+)">' - TITLE_PATTERN = r'<h1>Files in <span>(?P<title>.+)</span></h1>' - PAGES_PATTERN = r'data-paginator-totalPages="(?P<pages>\d+)"' + NAME_PATTERN = r'<h1>Files in <span>(?P<N>.+)</span></h1>' + PAGES_PATTERN = r'data-paginator-totalPages="(\d+)"' - SH_COOKIES = [('.filefactory.com', 'locale', 'en_US.utf8')] + COOKIES = [("filefactory.com", "locale", "en_US.utf8")] def loadPage(self, page_n): return self.load(self.pyfile.url, get={'page': page_n}) + + +getInfo = create_getInfo(FilefactoryComFolder) diff --git a/module/plugins/crypter/FilerNetFolder.py b/module/plugins/crypter/FilerNetFolder.py index 77e7409e9..00db173bb 100644 --- a/module/plugins/crypter/FilerNetFolder.py +++ b/module/plugins/crypter/FilerNetFolder.py @@ -1,22 +1,29 @@ import re -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FilerNetFolder(SimpleCrypter): - __name__ = "FilerNetFolder" - __version__ = "0.3" - __type__ = "crypter" + __name__ = "FilerNetFolder" + __type__ = "crypter" + __version__ = "0.41" __pattern__ = r'https?://filer\.net/folder/\w{16}' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Filer.net decrypter plugin""" - __author_name_ = ("nath_schwarz", "stickell") - __author_mail_ = ("nathan.notwhite@gmail.com", "l.stickell@yahoo.it") + __license__ = "GPLv3" + __authors__ = [("nath_schwarz", "nathan.notwhite@gmail.com"), + ("stickell", "l.stickell@yahoo.it")] + LINK_PATTERN = r'href="(/get/\w{16})">(?!<)' - TITLE_PATTERN = r'<h3>(?P<title>.+) - <small' + NAME_PATTERN = r'<h3>(?P<N>.+?) - <small' def getLinks(self): return ['http://filer.net%s' % link for link in re.findall(self.LINK_PATTERN, self.html)] + + +getInfo = create_getInfo(FilerNetFolder) diff --git a/module/plugins/crypter/FileserveComFolder.py b/module/plugins/crypter/FileserveComFolder.py index 4a0d5a416..e6b35fd36 100644 --- a/module/plugins/crypter/FileserveComFolder.py +++ b/module/plugins/crypter/FileserveComFolder.py @@ -6,15 +6,18 @@ from module.plugins.Crypter import Crypter class FileserveComFolder(Crypter): - __name__ = "FileserveComFolder" + __name__ = "FileserveComFolder" + __type__ = "crypter" __version__ = "0.11" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?fileserve.com/list/\w+' + __pattern__ = r'http://(?:www\.)?fileserve\.com/list/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """FileServe.com folder decrypter plugin""" - __author_name__ = "fionnc" - __author_mail__ = "fionnc@gmail.com" + __license__ = "GPLv3" + __authors__ = [("fionnc", "fionnc@gmail.com")] + FOLDER_PATTERN = r'<table class="file_list">(.*?)</table>' LINK_PATTERN = r'<a href="([^"]+)" class="sheet_icon wbold">' @@ -25,13 +28,11 @@ class FileserveComFolder(Crypter): new_links = [] - folder = re.search(self.FOLDER_PATTERN, html, re.DOTALL) + folder = re.search(self.FOLDER_PATTERN, html, re.S) if folder is None: - self.fail("Parse error (FOLDER)") + self.error(_("FOLDER_PATTERN not found")) new_links.extend(re.findall(self.LINK_PATTERN, folder.group(1))) if new_links: self.urls = [map(lambda s: "http://fileserve.com%s" % s, new_links)] - else: - self.fail('Could not extract any links') diff --git a/module/plugins/crypter/FilesonicComFolder.py b/module/plugins/crypter/FilesonicComFolder.py new file mode 100644 index 000000000..d58516986 --- /dev/null +++ b/module/plugins/crypter/FilesonicComFolder.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo + + +class FilesonicComFolder(DeadCrypter): + __name__ = "FilesonicComFolder" + __type__ = "crypter" + __version__ = "0.12" + + __pattern__ = r'http://(?:www\.)?filesonic\.com/folder/\w+' + + __description__ = """Filesonic.com folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + + +getInfo = create_getInfo(FilesonicComFolder) diff --git a/module/plugins/crypter/FilestubeCom.py b/module/plugins/crypter/FilestubeCom.py index 7576319e0..16ebdda37 100644 --- a/module/plugins/crypter/FilestubeCom.py +++ b/module/plugins/crypter/FilestubeCom.py @@ -1,32 +1,24 @@ # -*- 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.SimpleCrypter import SimpleCrypter + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FilestubeCom(SimpleCrypter): - __name__ = "FilestubeCom" - __version__ = "0.03" - __type__ = "crypter" + __name__ = "FilestubeCom" + __type__ = "crypter" + __version__ = "0.05" __pattern__ = r'http://(?:www\.)?filestube\.(?:com|to)/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Filestube.com decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] + LINK_PATTERN = r'<a class=\"file-link-main(?: noref)?\" [^>]* href=\"(http://[^\"]+)' - TITLE_PATTERN = r'<h1\s*> (?P<title>.+) download\s*</h1>' + NAME_PATTERN = r'<h1\s*> (?P<N>.+) download\s*</h1>' + + +getInfo = create_getInfo(FilestubeCom) diff --git a/module/plugins/crypter/FiletramCom.py b/module/plugins/crypter/FiletramCom.py index 2491c1322..76530c589 100644 --- a/module/plugins/crypter/FiletramCom.py +++ b/module/plugins/crypter/FiletramCom.py @@ -1,32 +1,25 @@ # -*- 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.SimpleCrypter import SimpleCrypter + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FiletramCom(SimpleCrypter): - __name__ = "FiletramCom" - __version__ = "0.01" - __type__ = "crypter" + __name__ = "FiletramCom" + __type__ = "crypter" + __version__ = "0.03" - __pattern__ = r'http://(?:www\.)?filetram.com/[^/]+/.+' + __pattern__ = r'http://(?:www\.)?filetram\.com/[^/]+/.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Filetram.com decrypter plugin""" - __author_name__ = ("igel", "stickell") - __author_mail__ = ("igelkun@myopera.com", "l.stickell@yahoo.it") + __license__ = "GPLv3" + __authors__ = [("igel", "igelkun@myopera.com"), + ("stickell", "l.stickell@yahoo.it")] + LINK_PATTERN = r'\s+(http://.+)' - TITLE_PATTERN = r'<title>(?P<title>[^<]+) - Free Download[^<]*</title>' + NAME_PATTERN = r'<title>(?P<N>.+?) - Free Download' + + +getInfo = create_getInfo(FiletramCom) diff --git a/module/plugins/crypter/FiredriveComFolder.py b/module/plugins/crypter/FiredriveComFolder.py index c0db299b0..7d3a357fd 100644 --- a/module/plugins/crypter/FiredriveComFolder.py +++ b/module/plugins/crypter/FiredriveComFolder.py @@ -1,42 +1,19 @@ # -*- 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.DeadCrypter import DeadCrypter, create_getInfo -from module.plugins.internal.SimpleCrypter import SimpleCrypter - -class FiredriveComFolder(SimpleCrypter): - __name__ = "FiredriveComFolder" - __version__ = "0.01" - __type__ = "crypter" +class FiredriveComFolder(DeadCrypter): + __name__ = "FiredriveComFolder" + __type__ = "crypter" + __version__ = "0.03" __pattern__ = r'https?://(?:www\.)?(firedrive|putlocker)\.com/share/.+' + __config__ = [] __description__ = """Firedrive.com folder decrypter plugin""" - __author_name__ = "Walter Purcaro" - __author_mail__ = "vuolter@gmail.com" - - LINK_PATTERN = r'<div class="pf_item pf_(file|folder).+?public=\'(.+?)\'' - TITLE_PATTERN = r'>Shared Folder "(?P<title>.+)" | Firedrive<' - OFFLINE_PATTERN = r'class="sad_face_image"|>No such page here.<' - TEMP_OFFLINE_PATTERN = r'>(File Temporarily Unavailable|Server Error. Try again later)' + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - def getLinks(self): - return map(lambda x: "http://www.firedrive.com/%s/%s" % - ("share" if x[0] == "folder" else "file", x[1]), - re.findall(self.LINK_PATTERN, self.html)) +getInfo = create_getInfo(FiredriveComFolder) diff --git a/module/plugins/crypter/FourChanOrg.py b/module/plugins/crypter/FourChanOrg.py index a911c64d6..d6c5c86cc 100644 --- a/module/plugins/crypter/FourChanOrg.py +++ b/module/plugins/crypter/FourChanOrg.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Based on 4chandl by Roland Beermann -# https://gist.github.com/enkore/3492599 +# +# Based on 4chandl by Roland Beermann (https://gist.github.com/enkore/3492599) import re @@ -8,15 +8,17 @@ from module.plugins.Crypter import Crypter class FourChanOrg(Crypter): - __name__ = "FourChanOrg" - __version__ = "0.3" - __type__ = "crypter" + __name__ = "FourChanOrg" + __type__ = "crypter" + __version__ = "0.30" - __pattern__ = r'http://(?:www\.)?boards\.4chan.org/\w+/res/(\d+)' + __pattern__ = r'http://(?:www\.)?boards\.4chan\.org/\w+/res/(\d+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """4chan.org folder decrypter plugin""" - __author_name__ = None - __author_mail__ = None + __license__ = "GPLv3" + __authors__ = [] def decrypt(self, pyfile): diff --git a/module/plugins/crypter/FreakhareComFolder.py b/module/plugins/crypter/FreakhareComFolder.py index ddc05199b..7c1b7de2b 100644 --- a/module/plugins/crypter/FreakhareComFolder.py +++ b/module/plugins/crypter/FreakhareComFolder.py @@ -1,38 +1,27 @@ # -*- 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.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FreakhareComFolder(SimpleCrypter): - __name__ = "FreakhareComFolder" - __version__ = "0.01" - __type__ = "crypter" + __name__ = "FreakhareComFolder" + __type__ = "crypter" + __version__ = "0.03" __pattern__ = r'http://(?:www\.)?freakshare\.com/folder/.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Freakhare.com folder decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] - LINK_PATTERN = r'<a href="(http://freakshare.com/files/[^"]+)" target="_blank">' - TITLE_PATTERN = r'Folder:</b> (?P<title>.+)' - PAGES_PATTERN = r'Pages: +(?P<pages>\d+)' + + LINK_PATTERN = r'<a href="(http://freakshare\.com/files/[^"]+)" target="_blank">' + NAME_PATTERN = r'Folder:</b> (?P<N>.+)' + PAGES_PATTERN = r'Pages: +(\d+)' def loadPage(self, page_n): @@ -47,3 +36,6 @@ class FreakhareComFolder(SimpleCrypter): 'entrys': '20', 'page': page_n - 1, 'order': ''}, decode=True) + + +getInfo = create_getInfo(FreakhareComFolder) diff --git a/module/plugins/crypter/FreetexthostCom.py b/module/plugins/crypter/FreetexthostCom.py index a6fb78d8e..c33c9ff64 100644 --- a/module/plugins/crypter/FreetexthostCom.py +++ b/module/plugins/crypter/FreetexthostCom.py @@ -1,39 +1,30 @@ # -*- 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.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FreetexthostCom(SimpleCrypter): - __name__ = "FreetexthostCom" + __name__ = "FreetexthostCom" + __type__ = "crypter" __version__ = "0.01" - __type__ = "crypter" __pattern__ = r'http://(?:www\.)?freetexthost\.com/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Freetexthost.com decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] def getLinks(self): - m = re.search(r'<div id="contentsinner">\s*(.+)<div class="viewcount">', self.html, re.DOTALL) + m = re.search(r'<div id="contentsinner">\s*(.+)<div class="viewcount">', self.html, re.S) if m is None: - self.fail('Unable to extract links | Plugin may be out-of-date') + self.error(_("Unable to extract links")) links = m.group(1) return links.strip().split("<br />\r\n") + + +getInfo = create_getInfo(FreetexthostCom) diff --git a/module/plugins/crypter/FshareVnFolder.py b/module/plugins/crypter/FshareVnFolder.py index 9f5162125..474364e40 100644 --- a/module/plugins/crypter/FshareVnFolder.py +++ b/module/plugins/crypter/FshareVnFolder.py @@ -1,17 +1,23 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FshareVnFolder(SimpleCrypter): - __name__ = "FshareVnFolder" + __name__ = "FshareVnFolder" + __type__ = "crypter" __version__ = "0.01" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?fshare.vn/folder/.*' + __pattern__ = r'http://(?:www\.)?fshare\.vn/folder/.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Fshare.vn folder decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + LINK_PATTERN = r'<li class="w_80pc"><a href="([^"]+)" target="_blank">' + + +getInfo = create_getInfo(FshareVnFolder) diff --git a/module/plugins/crypter/Go4UpCom.py b/module/plugins/crypter/Go4UpCom.py new file mode 100644 index 000000000..102bc32b5 --- /dev/null +++ b/module/plugins/crypter/Go4UpCom.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +import re + +from urlparse import urljoin + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class Go4UpCom(SimpleCrypter): + __name__ = "Go4UpCom" + __type__ = "crypter" + __version__ = "0.11" + + __pattern__ = r'http://go4up\.com/(dl/\w{12}|rd/\w{12}/\d+)' + + __description__ = """Go4Up.com decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("rlindner81", "rlindner81@gmail.com"), + ("Walter Purcaro", "vuolter@gmail.com")] + + + LINK_PATTERN = r'(http://go4up\.com/rd/.+?)<' + + NAME_PATTERN = r'<title>Download (.+?)<' + + OFFLINE_PATTERN = r'>\s*(404 Page Not Found|File not Found|Mirror does not exist)' + + + def getLinks(self + links = [] + + m = re.search(r'(/download/gethosts/.+?)"') + if m: + self.html = self.load(urljoin("http://go4up.com/", m.group(1))) + pages = [self.load(url) for url in re.findall(self.LINK_PATTERN, self.html)] + else: + pages = [self.html] + + for html in pages: + try: + links.append(re.search(r'<b><a href="(.+?)"', html).group(1)) + except: + continue + + return links + + +getInfo = create_getInfo(Go4UpCom) diff --git a/module/plugins/crypter/GooGl.py b/module/plugins/crypter/GooGl.py index 52bf93ed3..d548a3375 100644 --- a/module/plugins/crypter/GooGl.py +++ b/module/plugins/crypter/GooGl.py @@ -1,43 +1,32 @@ # -*- 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.Crypter import Crypter from module.common.json_layer import json_loads class GooGl(Crypter): - __name__ = "GooGl" + __name__ = "GooGl" + __type__ = "crypter" __version__ = "0.01" - __type__ = "crypter" __pattern__ = r'https?://(?:www\.)?goo\.gl/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Goo.gl decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] + API_URL = "https://www.googleapis.com/urlshortener/v1/url" def decrypt(self, pyfile): rep = self.load(self.API_URL, get={'shortUrl': pyfile.url}) - self.logDebug('JSON data: ' + rep) + self.logDebug("JSON data: " + rep) rep = json_loads(rep) if 'longUrl' in rep: self.urls = [rep['longUrl']] else: - self.fail('Unable to expand shortened link') + self.fail(_("Unable to expand shortened link")) diff --git a/module/plugins/crypter/HoerbuchIn.py b/module/plugins/crypter/HoerbuchIn.py index 88fc57244..a347e4232 100644 --- a/module/plugins/crypter/HoerbuchIn.py +++ b/module/plugins/crypter/HoerbuchIn.py @@ -2,20 +2,25 @@ import re +from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup + from module.plugins.Crypter import Crypter -from module.lib.BeautifulSoup import BeautifulSoup, BeautifulStoneSoup class HoerbuchIn(Crypter): - __name__ = "HoerbuchIn" - __version__ = "0.6" - __type__ = "crypter" + __name__ = "HoerbuchIn" + __type__ = "crypter" + __version__ = "0.60" - __pattern__ = r'http://(?:www\.)?hoerbuch\.in/(wp/horbucher/\d+/.+/|tp/out.php\?.+|protection/folder_\d+\.html)' + __pattern__ = r'http://(?:www\.)?hoerbuch\.in/(wp/horbucher/\d+/.+/|tp/out\.php\?.+|protection/folder_\d+\.html)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Hoerbuch.in decrypter plugin""" - __author_name__ = ("spoob", "mkaay") - __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de") + __license__ = "GPLv3" + __authors__ = [("spoob", "spoob@pyload.org"), + ("mkaay", "mkaay@mkaay.de")] + article = re.compile("http://(?:www\.)?hoerbuch\.in/wp/horbucher/\d+/.+/") protection = re.compile("http://(?:www\.)?hoerbuch\.in/protection/folder_\d+.html") @@ -25,8 +30,8 @@ class HoerbuchIn(Crypter): self.pyfile = pyfile if self.article.match(pyfile.url): - src = self.load(pyfile.url) - soup = BeautifulSoup(src, convertEntities=BeautifulStoneSoup.HTML_ENTITIES) + html = self.load(pyfile.url) + soup = BeautifulSoup(html, convertEntities=BeautifulStoneSoup.HTML_ENTITIES) abookname = soup.find("a", attrs={"rel": "bookmark"}).text for a in soup.findAll("a", attrs={"href": self.protection}): @@ -37,18 +42,19 @@ class HoerbuchIn(Crypter): else: self.urls = self.decryptFolder(pyfile.url) + def decryptFolder(self, url): m = self.protection.search(url) if m is None: - self.fail("Bad URL") + self.fail(_("Bad URL")) url = m.group(0) self.pyfile.url = url - src = self.req.load(url, post={"viewed": "adpg"}) + html = self.load(url, post={"viewed": "adpg"}) links = [] pattern = re.compile("http://www\.hoerbuch\.in/protection/(\w+)/(.*?)\"") - for hoster, lid in pattern.findall(src): + for hoster, lid in pattern.findall(html): self.req.lastURL = url self.load("http://www.hoerbuch.in/protection/%s/%s" % (hoster, lid)) links.append(self.req.lastEffectiveURL) diff --git a/module/plugins/crypter/HotfileComFolder.py b/module/plugins/crypter/HotfileComFolder.py new file mode 100644 index 000000000..4f40587ad --- /dev/null +++ b/module/plugins/crypter/HotfileComFolder.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo + + +class HotfileComFolder(DeadCrypter): + __name__ = "HotfileComFolder" + __type__ = "crypter" + __version__ = "0.30" + + __pattern__ = r'https?://(?:www\.)?hotfile\.com/list/\w+/\w+' + __config__ = [] + + __description__ = """Hotfile.com folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("RaNaN", "RaNaN@pyload.org")] + + +getInfo = create_getInfo(HotfileComFolder) diff --git a/module/plugins/crypter/HotfileFolderCom.py b/module/plugins/crypter/HotfileFolderCom.py deleted file mode 100644 index 433dc9755..000000000 --- a/module/plugins/crypter/HotfileFolderCom.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.Crypter import Crypter - - -class HotfileFolderCom(Crypter): - __name__ = "HotfileFolderCom" - __version__ = "0.1" - __type__ = "crypter" - - __pattern__ = r'http://(?:www\.)?hotfile.com/list/\w+/\w+' - - __description__ = """Hotfile.com folder decrypter plugin""" - __author_name__ = "RaNaN" - __author_mail__ = "RaNaN@pyload.org" - - - def decrypt(self, pyfile): - html = self.load(pyfile.url) - - name = re.findall( - r'<img src="/i/folder.gif" width="23" height="14" style="margin-bottom: -2px;" />([^<]+)', html, - re.MULTILINE)[0].replace("/", "") - new_links = re.findall(r'href="(http://(www.)?hotfile\.com/dl/\d+/[0-9a-zA-Z]+[^"]+)', html) - - new_links = [x[0] for x in new_links] - - self.packages = [(name, new_links, name)] diff --git a/module/plugins/crypter/ILoadTo.py b/module/plugins/crypter/ILoadTo.py index e003e07f4..f3415706d 100644 --- a/module/plugins/crypter/ILoadTo.py +++ b/module/plugins/crypter/ILoadTo.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class ILoadTo(DeadCrypter): - __name__ = "ILoadTo" + __name__ = "ILoadTo" + __type__ = "crypter" __version__ = "0.11" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?iload\.to/go/\d+-[\w\.-]+/' + __pattern__ = r'http://(?:www\.)?iload\.to/go/\d+-[\w.-]+/' + __config__ = [] __description__ = """Iload.to decrypter plugin""" - __author_name__ = "hzpz" - __author_mail__ = None + __license__ = "GPLv3" + __authors__ = [("hzpz", None)] + + +getInfo = create_getInfo(ILoadTo) diff --git a/module/plugins/crypter/ImgurComAlbum.py b/module/plugins/crypter/ImgurComAlbum.py index 394673586..6c074f5f1 100644 --- a/module/plugins/crypter/ImgurComAlbum.py +++ b/module/plugins/crypter/ImgurComAlbum.py @@ -1,24 +1,30 @@ import re -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo from module.utils import uniqify class ImgurComAlbum(SimpleCrypter): - __name__ = "ImgurComAlbum" - __version__ = "0.4" - __type__ = "crypter" + __name__ = "ImgurComAlbum" + __type__ = "crypter" + __version__ = "0.51" __pattern__ = r'https?://(?:www\.|m\.)?imgur\.com/(a|gallery|)/?\w{5,7}' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Imgur.com decrypter plugin""" - __author_name_ = "nath_schwarz" - __author_mail_ = "nathan.notwhite@gmail.com" + __license__ = "GPLv3" + __authors__ = [("nath_schwarz", "nathan.notwhite@gmail.com")] - TITLE_PATTERN = r'(?P<title>.+) - Imgur' + + NAME_PATTERN = r'(?P<N>.+?) - Imgur' LINK_PATTERN = r'i\.imgur\.com/\w{7}s?\.(?:jpeg|jpg|png|gif|apng)' def getLinks(self): f = lambda url: "http://" + re.sub(r'(\w{7})s\.', r'\1.', url) return uniqify(map(f, re.findall(self.LINK_PATTERN, self.html))) + + +getInfo = create_getInfo(ImgurComAlbum) diff --git a/module/plugins/crypter/JunocloudMeFolder.py b/module/plugins/crypter/JunocloudMeFolder.py new file mode 100644 index 000000000..990f25902 --- /dev/null +++ b/module/plugins/crypter/JunocloudMeFolder.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo + + +class JunocloudMeFolder(XFSCrypter): + __name__ = "JunocloudMeFolder" + __type__ = "crypter" + __version__ = "0.03" + + __pattern__ = r'http://(?:www\.)?junocloud\.me/folders/(?P<ID>\d+/\w+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """Junocloud.me folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("guidobelix", "guidobelix@hotmail.it")] + + + HOSTER_DOMAIN = "junocloud.me" + + +getInfo = create_getInfo(JunocloudMeFolder) diff --git a/module/plugins/crypter/LetitbitNetFolder.py b/module/plugins/crypter/LetitbitNetFolder.py index adb2918a6..56ecbc7f8 100644 --- a/module/plugins/crypter/LetitbitNetFolder.py +++ b/module/plugins/crypter/LetitbitNetFolder.py @@ -5,15 +5,19 @@ from module.plugins.Crypter import Crypter class LetitbitNetFolder(Crypter): - __name__ = "LetitbitNetFolder" - __version__ = "0.1" - __type__ = "crypter" + __name__ = "LetitbitNetFolder" + __type__ = "crypter" + __version__ = "0.10" - __pattern__ = r'http://(?:www\.)?letitbit.net/folder/\w+' + __pattern__ = r'http://(?:www\.)?letitbit\.net/folder/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Letitbit.net folder decrypter plugin""" - __author_name__ = ("DHMH", "z00nx") - __author_mail__ = ("webmaster@pcProfil.de", "z00nx0@gmail.com") + __license__ = "GPLv3" + __authors__ = [("DHMH", "webmaster@pcProfil.de"), + ("z00nx", "z00nx0@gmail.com")] + FOLDER_PATTERN = r'<table>(.*)</table>' LINK_PATTERN = r'<a href="([^"]+)" target="_blank">' @@ -22,11 +26,8 @@ class LetitbitNetFolder(Crypter): def decrypt(self, pyfile): html = self.load(pyfile.url) - folder = re.search(self.FOLDER_PATTERN, html, re.DOTALL) + folder = re.search(self.FOLDER_PATTERN, html, re.S) if folder is None: - self.fail("Parse error (FOLDER)") + self.error(_("FOLDER_PATTERN not found")) self.urls.extend(re.findall(self.LINK_PATTERN, folder.group(0))) - - if not self.urls: - self.fail('Could not extract any links') diff --git a/module/plugins/crypter/LinkCryptWs.py b/module/plugins/crypter/LinkCryptWs.py new file mode 100644 index 000000000..835a549b2 --- /dev/null +++ b/module/plugins/crypter/LinkCryptWs.py @@ -0,0 +1,327 @@ +# -*- coding: utf-8 -*- + +import base64 +import binascii +import re + +import pycurl + +from Crypto.Cipher import AES + +from module.plugins.Crypter import Crypter +from module.utils import html_unescape + + +class LinkCryptWs(Crypter): + __name__ = "LinkCryptWs" + __type__ = "crypter" + __version__ = "0.07" + + __pattern__ = r'http://(?:www\.)?linkcrypt\.ws/(dir|container)/(?P<ID>\w+)' + + __description__ = """LinkCrypt.ws decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("kagenoshin", "kagenoshin[AT]gmx[DOT]ch"), + ("glukgluk", None), + ("Gummibaer", None)] + + + CRYPTED_KEY = "crypted" + JK_KEY = "jk" + + + def setup(self): + self.captcha = False + self.links = [] + self.sources = ['cnl', 'web', 'dlc', 'rsdf', 'ccf'] + + + def prepare(self): + # Init + self.fileid = re.match(self.__pattern__, self.pyfile.url).group('ID') + + self.req.cj.setCookie("linkcrypt.ws", "language", "en") + + # Request package + self.req.http.c.setopt(pycurl.USERAGENT, "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko") #: better chance to not get those key-captchas + self.html = self.load(self.pyfile.url) + + + def decrypt(self, pyfile): + if not self.js: + self.fail(_("Missing JS Engine")) + + self.prepare() + + if not self.isOnline(): + self.offline() + + if self.isKeyCaptchaProtected(): + self.retry(4, 30, _("Can't handle Key-Captcha")) + + if self.isCaptchaProtected(): + self.captcha = True + self.unlockCaptchaProtection() + self.handleCaptchaErrors() + + # Check for protection + if self.isPasswordProtected(): + self.unlockPasswordProtection() + self.handleErrors() + + # get unrar password + self.getunrarpw() + + # Get package name and folder + package_name, folder_name = self.getPackageInfo() + + #get the container definitions from script section + self.get_container_html() + + # Extract package links + for type in self.sources: + links = self.handleLinkSource(type) + + if links: + self.links.extend(links) + break + + if self.links: + self.packages = [(package_name, self.links, folder_name)] + + + def isOnline(self): + if "<title>Linkcrypt.ws // Error 404</title>" in self.html: + self.logDebug("folder doesen't exist anymore") + return False + else: + return True + + + def isPasswordProtected(self): + if "Authorizing" in self.html: + self.logDebug("Links are password protected") + return True + else: + return False + + + def isCaptchaProtected(self): + if 'id="captcha">' in self.html: + self.logDebug("Links are captcha protected") + return True + else: + return False + + + def isKeyCaptchaProtected(self): + if re.search(r'Key[ -]', self.html, re.I): + return True + else: + return False + + + def unlockPasswordProtection(self): + password = self.getPassword() + + if password: + self.logDebug("Submitting password [%s] for protected links" % password) + self.html = self.load(self.pyfile.url, post={"password": password, 'x': "0", 'y': "0"}) + else: + self.fail(_("Folder is password protected")) + + + def unlockCaptchaProtection(self): + captcha_url = re.search(r'<form.*?id\s*?=\s*?"captcha"[^>]*?>.*?<\s*?input.*?src="([^"]*?)"', self.html, re.I | re.S).group(1) + captcha_code = self.decryptCaptcha(captcha_url, forceUser=True, imgtype="gif", result_type='positional') + + self.html = self.load(self.pyfile.url, post={"x": captcha_code[0], "y": captcha_code[1]}) + + + def getPackageInfo(self): + name = self.pyfile.package().name + folder = self.pyfile.package().folder + + self.logDebug("Defaulting to pyfile name [%s] and folder [%s] for package" % (name, folder)) + + return name, folder + + + def getunrarpw(self): + sitein = self.html + indexi = sitein.find("|source|") + 8 + indexe = sitein.find("|",indexi) + + unrarpw = sitein[indexi:indexe] + + if not (unrarpw == "Password" or "Dateipasswort") : + self.logDebug("File password set to: [%s]"% unrarpw) + self.pyfile.package().password = unrarpw + + + def handleErrors(self): + if self.isPasswordProtected(): + self.fail(_("Incorrect password")) + + + def handleCaptchaErrors(self): + if self.captcha: + if "Your choice was wrong!" in self.html: + self.invalidCaptcha() + self.retry() + else: + self.correctCaptcha() + + + def handleLinkSource(self, type): + if type == 'cnl': + return self.handleCNL2() + + elif type == 'web': + return self.handleWebLinks() + + elif type in ('rsdf', 'ccf', 'dlc'): + return self.handleContainer(type) + + else: + self.fail(_("Unknown source type: %s") % type) #@TODO: Replace with self.error in 0.4.10 + + + def handleWebLinks(self): + self.logDebug("Search for Web links ") + + package_links = [] + pattern = r'<form action="http://linkcrypt.ws/out.html"[^>]*?>.*?<input[^>]*?value="([^"]*?)"[^>]*?name="file"' + ids = re.findall(pattern, self.html, re.I | re.S) + + self.logDebug("Decrypting %d Web links" % len(ids)) + + for idx, weblink_id in enumerate(ids): + try: + self.logDebug("Decrypting Web link %d, %s" % (idx + 1, weblink_id)) + + res = self.load("http://linkcrypt.ws/out.html", post = {'file':weblink_id}) + + indexs = res.find("window.location =") + 19 + indexe = res.find('"', indexs) + + link2 = res[indexs:indexe] + + self.logDebug(link2) + + link2 = html_unescape(link2) + package_links.append(link2) + + except Exception, detail: + self.logDebug("Error decrypting Web link %s, %s" % (weblink_id, detail)) + + return package_links + + + def get_container_html(self): + self.container_html = [] + + script = re.search(r'<div.*?id="ad_cont".*?<script.*?javascrip[^>]*?>(.*?)</script', self.html, re.I | re.S) + + if script: + container_html_text = script.group(1) + container_html_text.strip() + self.container_html = container_html_text.splitlines() + + + def handle_javascript(self, line): + return self.js.eval(line.replace('{}))',"{}).replace('document.open();document.write','').replace(';document.close();',''))")) + + + def handleContainer(self, type): + package_links = [] + type = type.lower() + + self.logDebug('Search for %s Container links' % type.upper()) + + if not type.isalnum(): # check to prevent broken re-pattern (cnl2,rsdf,ccf,dlc,web are all alpha-numeric) + self.fail(_("Unknown container type: %s") % type) #@TODO: Replace with self.error in 0.4.10 + + for line in self.container_html: + if type in line: + jseval = self.handle_javascript(line) + clink = re.search(r'href=["\']([^"\']*?)["\']',jseval,re.I) + + if not clink: + continue + + self.logDebug("clink avaible") + + package_name, folder_name = self.getPackageInfo() + self.logDebug("Added package with name %s.%s and container link %s" %( package_name, type, clink.group(1))) + self.core.api.uploadContainer( "%s.%s" %(package_name, type), self.load(clink.group(1))) + return "Found it" + + return package_links + + + def handleCNL2(self): + self.logDebug("Search for CNL links") + + package_links = [] + cnl_line = None + + for line in self.container_html: + if "cnl" in line: + cnl_line = line + break + + if cnl_line: + self.logDebug("cnl_line gefunden") + + try: + cnl_section = self.handle_javascript(cnl_line) + (vcrypted, vjk) = self._getCipherParams(cnl_section) + for (crypted, jk) in zip(vcrypted, vjk): + package_links.extend(self._getLinks(crypted, jk)) + except: + self.logError(_("Unable to decrypt CNL links (JS Error) try to get over links")) + return self.handleWebLinks() + + return package_links + + + def _getCipherParams(self, cnl_section): + # Get jk + jk_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkCryptWs.JK_KEY + vjk = re.findall(jk_re, cnl_section) + + # Get crypted + crypted_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkCryptWs.CRYPTED_KEY + vcrypted = re.findall(crypted_re, cnl_section) + + # Log and return + self.logDebug("Detected %d crypted blocks" % len(vcrypted)) + return vcrypted, vjk + + + def _getLinks(self, crypted, jk): + # Get key + jreturn = self.js.eval("%s f()" % jk) + key = binascii.unhexlify(jreturn) + + self.logDebug("JsEngine returns value [%s]" % jreturn) + + # Decode crypted + crypted = base64.standard_b64decode(crypted) + + # Decrypt + Key = key + IV = key + obj = AES.new(Key, AES.MODE_CBC, IV) + text = obj.decrypt(crypted) + + # Extract links + text = text.replace("\x00", "").replace("\r", "") + links = text.split("\n") + links = filter(lambda x: x != "", links) + + # Log and return + self.logDebug("Package has %d links" % len(links)) + + return links diff --git a/module/plugins/crypter/LinkSaveIn.py b/module/plugins/crypter/LinkSaveIn.py index 6e024c766..e96d0438e 100644 --- a/module/plugins/crypter/LinkSaveIn.py +++ b/module/plugins/crypter/LinkSaveIn.py @@ -1,228 +1,22 @@ # -*- coding: utf-8 -*- -# -# v2.01 - hagg -# * cnl2 and web links are skipped if JS is not available (instead of failing the package) -# * only best available link source is used (priority: cnl2>rsdf>ccf>dlc>web -# +from module.plugins.internal.SimpleDereferer import SimpleDereferer -import base64 -import binascii -import re -from Crypto.Cipher import AES -from module.plugins.Crypter import Crypter -from module.unescape import unescape +class LinkSaveIn(SimpleDereferer): + __name__ = "LinkSaveIn" + __type__ = "crypter" + __version__ = "2.03" - -class LinkSaveIn(Crypter): - __name__ = "LinkSaveIn" - __version__ = "2.01" - __type__ = "crypter" - - __pattern__ = r'http://(?:www\.)?linksave.in/(?P<id>\w+)$' + __pattern__ = r'https?://(?:www\.)?linksave\.in/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """LinkSave.in decrypter plugin""" - __author_name__ = "fragonib" - __author_mail__ = "fragonib[AT]yahoo[DOT]es" - - # Constants - _JK_KEY_ = "jk" - _CRYPTED_KEY_ = "crypted" - HOSTER_NAME = "linksave.in" - - - def setup(self): - self.html = None - self.fileid = None - self.captcha = False - self.package = None - self.preferred_sources = ["cnl2", "rsdf", "ccf", "dlc", "web"] - - def decrypt(self, pyfile): - # Init - self.package = pyfile.package() - self.fileid = re.match(self.__pattern__, pyfile.url).group('id') - self.req.cj.setCookie(self.HOSTER_NAME, "Linksave_Language", "english") - - # Request package - self.html = self.load(pyfile.url) - if not self.isOnline(): - self.offline() - - # Check for protection - if self.isPasswordProtected(): - self.unlockPasswordProtection() - self.handleErrors() - - if self.isCaptchaProtected(): - self.captcha = True - self.unlockCaptchaProtection() - self.handleErrors() - - # Get package name and folder - (package_name, folder_name) = self.getPackageInfo() - - # Extract package links - package_links = [] - for type_ in self.preferred_sources: - package_links.extend(self.handleLinkSource(type_)) - if package_links: # use only first source which provides links - break - package_links = set(package_links) - - # Pack - if package_links: - self.packages = [(package_name, package_links, folder_name)] - else: - self.fail('Could not extract any links') - - def isOnline(self): - if "<big>Error 404 - Folder not found!</big>" in self.html: - self.logDebug("File not found") - return False - return True - - def isPasswordProtected(self): - if re.search(r'''<input.*?type="password"''', self.html): - self.logDebug("Links are password protected") - return True - - def isCaptchaProtected(self): - if "<b>Captcha:</b>" in self.html: - self.logDebug("Links are captcha protected") - return True - return False - - def unlockPasswordProtection(self): - password = self.getPassword() - self.logDebug("Submitting password [%s] for protected links" % password) - post = {"id": self.fileid, "besucherpasswort": password, 'login': 'submit'} - self.html = self.load(self.pyfile.url, post=post) - - def unlockCaptchaProtection(self): - captcha_hash = re.search(r'name="hash" value="([^"]+)', self.html).group(1) - captcha_url = re.search(r'src=".(/captcha/cap.php\?hsh=[^"]+)', self.html).group(1) - captcha_code = self.decryptCaptcha("http://linksave.in" + captcha_url, forceUser=True) - self.html = self.load(self.pyfile.url, post={"id": self.fileid, "hash": captcha_hash, "code": captcha_code}) - - def getPackageInfo(self): - name = self.pyfile.package().name - folder = self.pyfile.package().folder - self.logDebug("Defaulting to pyfile name [%s] and folder [%s] for package" % (name, folder)) - return name, folder - - def handleErrors(self): - if "The visitorpassword you have entered is wrong" in self.html: - self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry") - self.fail("Incorrect password, please set right password on 'Edit package' form and retry") - - if self.captcha: - if "Wrong code. Please retry" in self.html: - self.logDebug("Invalid captcha, retrying") - self.invalidCaptcha() - self.retry() - else: - self.correctCaptcha() - - def handleLinkSource(self, type_): - if type_ == "cnl2": - return self.handleCNL2() - elif type_ in ("rsdf", "ccf", "dlc"): - return self.handleContainer(type_) - elif type_ == "web": - return self.handleWebLinks() - else: - self.fail('unknown source type "%s" (this is probably a bug)' % type_) - - def handleWebLinks(self): - package_links = [] - self.logDebug("Search for Web links") - if not self.js: - self.logDebug("no JS -> skip Web links") - else: - #@TODO: Gather paginated web links - pattern = r'<a href="http://linksave\.in/(\w{43})"' - ids = re.findall(pattern, self.html) - self.logDebug("Decrypting %d Web links" % len(ids)) - for i, weblink_id in enumerate(ids): - try: - webLink = "http://linksave.in/%s" % weblink_id - self.logDebug("Decrypting Web link %d, %s" % (i + 1, webLink)) - fwLink = "http://linksave.in/fw-%s" % weblink_id - response = self.load(fwLink) - jscode = re.findall(r'<script type="text/javascript">(.*)</script>', response)[-1] - jseval = self.js.eval("document = { write: function(e) { return e; } }; %s" % jscode) - dlLink = re.search(r'http://linksave\.in/dl-\w+', jseval).group(0) - self.logDebug("JsEngine returns value [%s] for redirection link" % dlLink) - response = self.load(dlLink) - link = unescape(re.search(r'<iframe src="(.+?)"', response).group(1)) - package_links.append(link) - except Exception, detail: - self.logDebug("Error decrypting Web link %s, %s" % (webLink, detail)) - return package_links - - def handleContainer(self, type_): - package_links = [] - type_ = type_.lower() - self.logDebug('Seach for %s Container links' % type_.upper()) - if not type_.isalnum(): # check to prevent broken re-pattern (cnl2,rsdf,ccf,dlc,web are all alpha-numeric) - self.fail('unknown container type "%s" (this is probably a bug)' % type_) - pattern = r"\('%s_link'\).href=unescape\('(.*?\.%s)'\)" % (type_, type_) - containersLinks = re.findall(pattern, self.html) - self.logDebug("Found %d %s Container links" % (len(containersLinks), type_.upper())) - for containerLink in containersLinks: - link = "http://linksave.in/%s" % unescape(containerLink) - package_links.append(link) - return package_links - - def handleCNL2(self): - package_links = [] - self.logDebug("Search for CNL2 links") - if not self.js: - self.logDebug("no JS -> skip CNL2 links") - elif 'cnl2_load' in self.html: - try: - (vcrypted, vjk) = self._getCipherParams() - for (crypted, jk) in zip(vcrypted, vjk): - package_links.extend(self._getLinks(crypted, jk)) - except: - self.fail("Unable to decrypt CNL2 links") - return package_links - - def _getCipherParams(self): - # Get jk - jk_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkSaveIn._JK_KEY_ - vjk = re.findall(jk_re, self.html) - - # Get crypted - crypted_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkSaveIn._CRYPTED_KEY_ - vcrypted = re.findall(crypted_re, self.html) - - # Log and return - self.logDebug("Detected %d crypted blocks" % len(vcrypted)) - return vcrypted, vjk - - def _getLinks(self, crypted, jk): - # Get key - jreturn = self.js.eval("%s f()" % jk) - self.logDebug("JsEngine returns value [%s]" % jreturn) - key = binascii.unhexlify(jreturn) - - # Decode crypted - crypted = base64.standard_b64decode(crypted) + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - # Decrypt - Key = key - IV = key - obj = AES.new(Key, AES.MODE_CBC, IV) - text = obj.decrypt(crypted) - # Extract links - text = text.replace("\x00", "").replace("\r", "") - links = text.split("\n") - links = filter(lambda x: x != "", links) + COOKIES = [("linksave.in", "Linksave_Language", "english")] - # Log and return - self.logDebug("Package has %d links" % len(links)) - return links + OFFLINE_PATTERN = r'>(Error )?404 -' diff --git a/module/plugins/crypter/LinkdecrypterCom.py b/module/plugins/crypter/LinkdecrypterCom.py index 2671c19c6..91318eadf 100644 --- a/module/plugins/crypter/LinkdecrypterCom.py +++ b/module/plugins/crypter/LinkdecrypterCom.py @@ -1,34 +1,23 @@ # -*- 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/>. -""" - import re from module.plugins.Crypter import Crypter class LinkdecrypterCom(Crypter): - __name__ = "LinkdecrypterCom" + __name__ = "LinkdecrypterCom" + __type__ = "crypter" __version__ = "0.27" - __type__ = "crypter" - __pattern__ = None + __pattern__ = r'^unmatchable$' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Linkdecrypter.com""" - __author_name__ = ("zoidberg", "flowlee") - __author_mail__ = ("zoidberg@mujmail.cz", "") + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz"), + ("flowlee", None)] + TEXTAREA_PATTERN = r'<textarea name="links" wrap="off" readonly="1" class="caja_des">(.+)</textarea>' PASSWORD_PATTERN = r'<input type="text" name="password"' @@ -37,16 +26,13 @@ class LinkdecrypterCom(Crypter): def decrypt(self, pyfile): - self.passwords = self.getPassword().splitlines() # API not working anymore self.urls = self.decryptHTML() - if not self.urls: - self.fail('Could not extract any links') - def decryptAPI(self): + def decryptAPI(self): get_dict = {"t": "link", "url": self.pyfile.url, "lcache": "1"} self.html = self.load('http://linkdecrypter.com/api', get=get_dict) if self.html.startswith('http://'): @@ -58,21 +44,21 @@ class LinkdecrypterCom(Crypter): if self.html.startswith('http://'): return self.html.splitlines() - self.logError('API', self.html) + self.logError("API", self.html) if self.html == 'INTERRUPTION(PASSWORD)': - self.fail("No or incorrect password") + self.fail(_("No or incorrect password")) return None - def decryptHTML(self): + def decryptHTML(self): retries = 5 post_dict = {"link_cache": "on", "pro_links": self.pyfile.url, "modo_links": "text"} self.html = self.load('http://linkdecrypter.com/', post=post_dict, cookies=True, decode=True) while self.passwords or retries: - m = re.search(self.TEXTAREA_PATTERN, self.html, flags=re.DOTALL) + m = re.search(self.TEXTAREA_PATTERN, self.html, flags=re.S) if m: return [x for x in m.group(1).splitlines() if '[LINK-ERROR]' not in x] @@ -83,7 +69,7 @@ class LinkdecrypterCom(Crypter): m = re.search(r"<p><i><b>([^<]+)</b></i></p>", self.html) msg = m.group(1) if m else "" - self.logInfo("Captcha protected link", result_type, msg) + self.logInfo(_("Captcha protected link"), result_type, msg) captcha = self.decryptCaptcha(captcha_url, result_type=result_type) if result_type == "positional": @@ -94,10 +80,10 @@ class LinkdecrypterCom(Crypter): elif self.PASSWORD_PATTERN in self.html: if self.passwords: password = self.passwords.pop(0) - self.logInfo("Password protected link, trying " + password) + self.logInfo(_("Password protected link, trying ") + password) self.html = self.load('http://linkdecrypter.com/', post={'password': password}, decode=True) else: - self.fail("No or incorrect password") + self.fail(_("No or incorrect password")) else: retries -= 1 diff --git a/module/plugins/crypter/LixIn.py b/module/plugins/crypter/LixIn.py index a39173903..d899d58c7 100644 --- a/module/plugins/crypter/LixIn.py +++ b/module/plugins/crypter/LixIn.py @@ -6,19 +6,22 @@ from module.plugins.Crypter import Crypter class LixIn(Crypter): - __name__ = "LixIn" + __name__ = "LixIn" + __type__ = "crypter" __version__ = "0.22" - __type__ = "crypter" - __pattern__ = r'http://(www.)?lix.in/(?P<id>.*)' + __pattern__ = r'http://(?:www\.)?lix\.in/(?P<ID>.+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Lix.in decrypter plugin""" - __author_name__ = "spoob" - __author_mail__ = "spoob@pyload.org" + __license__ = "GPLv3" + __authors__ = [("spoob", "spoob@pyload.org")] - CAPTCHA_PATTERN = r'<img src="(?P<image>captcha_img.php\?.*?)"' - SUBMIT_PATTERN = r"value='continue.*?'" - LINK_PATTERN = r'name="ifram" src="(?P<link>.*?)"' + + CAPTCHA_PATTERN = r'<img src="(captcha_img\.php\?.*?)"' + SUBMIT_PATTERN = r'value=\'continue.*?\'' + LINK_PATTERN = r'name="ifram" src="(.*?)"' def decrypt(self, pyfile): @@ -26,34 +29,34 @@ class LixIn(Crypter): m = re.match(self.__pattern__, url) if m is None: - self.fail("couldn't identify file id") + self.error(_("Unable to identify file ID")) - id = m.group("id") + id = m.group('ID') self.logDebug("File id is %s" % id) - self.html = self.req.load(url, decode=True) + self.html = self.load(url, decode=True) m = re.search(self.SUBMIT_PATTERN, self.html) if m is None: - self.fail("link doesn't seem valid") + self.error(_("Link doesn't seem valid")) m = re.search(self.CAPTCHA_PATTERN, self.html) if m: - for _ in xrange(5): + for _i in xrange(5): m = re.search(self.CAPTCHA_PATTERN, self.html) if m: - self.logDebug("trying captcha") - captcharesult = self.decryptCaptcha("http://lix.in/" + m.group("image")) - self.html = self.req.load(url, decode=True, + self.logDebug("Trying captcha") + captcharesult = self.decryptCaptcha("http://lix.in/" + m.group(1)) + self.html = self.load(url, decode=True, post={"capt": captcharesult, "submit": "submit", "tiny": id}) else: - self.logDebug("no captcha/captcha solved") + self.logDebug("No captcha/captcha solved") else: - self.html = self.req.load(url, decode=True, post={"submit": "submit", "tiny": id}) + self.html = self.load(url, decode=True, post={"submit": "submit", "tiny": id}) m = re.search(self.LINK_PATTERN, self.html) if m is None: - self.fail("can't find destination url") + self.error(_("Unable to find destination url")) else: - self.urls = [m.group("link")] + self.urls = [m.group(1)] self.logDebug("Found link %s, adding to package" % self.urls[0]) diff --git a/module/plugins/crypter/LofCc.py b/module/plugins/crypter/LofCc.py index 91106dc51..3cac0fbf2 100644 --- a/module/plugins/crypter/LofCc.py +++ b/module/plugins/crypter/LofCc.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class LofCc(DeadCrypter): - __name__ = "LofCc" + __name__ = "LofCc" + __type__ = "crypter" __version__ = "0.21" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?lof.cc/(.*)' + __pattern__ = r'http://(?:www\.)?lof\.cc/(.+)' + __config__ = [] __description__ = """Lof.cc decrypter plugin""" - __author_name__ = "mkaay" - __author_mail__ = "mkaay@mkaay.de" + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] + + +getInfo = create_getInfo(LofCc) diff --git a/module/plugins/crypter/MBLinkInfo.py b/module/plugins/crypter/MBLinkInfo.py index 0162c111d..82c2d9719 100644 --- a/module/plugins/crypter/MBLinkInfo.py +++ b/module/plugins/crypter/MBLinkInfo.py @@ -1,15 +1,20 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class MBLinkInfo(DeadCrypter): - __name__ = "MBLinkInfo" + __name__ = "MBLinkInfo" + __type__ = "crypter" __version__ = "0.03" - __type__ = "crypter" __pattern__ = r'http://(?:www\.)?mblink\.info/?\?id=(\d+)' + __config__ = [] __description__ = """MBLink.info decrypter plugin""" - __author_name__ = ("Gummibaer", "stickell") - __author_mail__ = ("Gummibaer@wiki-bierkiste.de", "l.stickell@yahoo.it") + __license__ = "GPLv3" + __authors__ = [("Gummibaer", "Gummibaer@wiki-bierkiste.de"), + ("stickell", "l.stickell@yahoo.it")] + + +getInfo = create_getInfo(MBLinkInfo) diff --git a/module/plugins/crypter/MediafireComFolder.py b/module/plugins/crypter/MediafireComFolder.py index 5dd4e555b..d1dc89518 100644 --- a/module/plugins/crypter/MediafireComFolder.py +++ b/module/plugins/crypter/MediafireComFolder.py @@ -7,28 +7,31 @@ from module.common.json_layer import json_loads class MediafireComFolder(Crypter): - __name__ = "MediafireComFolder" + __name__ = "MediafireComFolder" + __type__ = "crypter" __version__ = "0.14" - __type__ = "crypter" __pattern__ = r'http://(?:www\.)?mediafire\.com/(folder/|\?sharekey=|\?\w{13}($|[/#]))' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Mediafire.com folder decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - FOLDER_KEY_PATTERN = r"var afI= '(\w+)';" - FILE_URL_PATTERN = r'<meta property="og:url" content="http://www.mediafire.com/\?(\w+)"/>' + + FOLDER_KEY_PATTERN = r'var afI= \'(\w+)' + LINK_PATTERN = r'<meta property="og:url" content="http://www\.mediafire\.com/\?(\w+)"/>' def decrypt(self, pyfile): url, result = checkHTMLHeader(pyfile.url) - self.logDebug('Location (%d): %s' % (result, url)) + self.logDebug("Location (%d): %s" % (result, url)) if result == 0: - # load and parse html + # load and parse html html = self.load(pyfile.url) - m = re.search(self.FILE_URL_PATTERN, html) + m = re.search(self.LINK_PATTERN, html) if m: # file page self.urls.append("http://www.mediafire.com/file/%s" % m.group(1)) @@ -39,8 +42,10 @@ class MediafireComFolder(Crypter): folder_key = m.group(1) self.logDebug("FOLDER KEY: %s" % folder_key) - json_resp = json_loads(self.load( - "http://www.mediafire.com/api/folder/get_info.php?folder_key=%s&response_format=json&version=1" % folder_key)) + json_resp = json_loads(self.load("http://www.mediafire.com/api/folder/get_info.php", + get={'folder_key' : folder_key, + 'response_format': "json", + 'version' : 1})) #self.logInfo(json_resp) if json_resp['response']['result'] == "Success": for link in json_resp['response']['folder_info']['files']: @@ -51,6 +56,3 @@ class MediafireComFolder(Crypter): self.offline() else: self.urls.append(url) - - if not self.urls: - self.fail('Could not extract any links') diff --git a/module/plugins/crypter/MegaRapidCzFolder.py b/module/plugins/crypter/MegaRapidCzFolder.py new file mode 100644 index 000000000..e7dff6c8a --- /dev/null +++ b/module/plugins/crypter/MegaRapidCzFolder.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class MegaRapidCzFolder(SimpleCrypter): + __name__ = "MegaRapidCzFolder" + __type__ = "crypter" + __version__ = "0.02" + + __pattern__ = r'http://(?:www\.)?(share|mega)rapid\.cz/slozka/\d+/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """Share-Rapid.com folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + + + LINK_PATTERN = r'<td class="soubor"[^>]*><a href="([^"]+)">' + + +getInfo = create_getInfo(MegaRapidCzFolder) diff --git a/module/plugins/crypter/MegauploadComFolder.py b/module/plugins/crypter/MegauploadComFolder.py new file mode 100644 index 000000000..08f96700d --- /dev/null +++ b/module/plugins/crypter/MegauploadComFolder.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo + + +class MegauploadComFolder(DeadCrypter): + __name__ = "MegauploadComFolder" + __type__ = "crypter" + __version__ = "0.02" + + __pattern__ = r'http://(?:www\.)?megaupload\.com/(\?f|xml/folderfiles\.php\?.*&?folderid)=\w+' + + __description__ = """Megaupload.com folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + + +getInfo = create_getInfo(MegauploadComFolder) diff --git a/module/plugins/crypter/Movie2kTo.py b/module/plugins/crypter/Movie2kTo.py index dcebf5e03..7d71950fd 100644 --- a/module/plugins/crypter/Movie2kTo.py +++ b/module/plugins/crypter/Movie2kTo.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class Movie2kTo(DeadCrypter): - __name__ = "Movie2kTo" + __name__ = "Movie2kTo" + __type__ = "crypter" __version__ = "0.51" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?movie2k\.to/(.*)\.html' + __pattern__ = r'http://(?:www\.)?movie2k\.to/(.+)\.html' + __config__ = [] __description__ = """Movie2k.to decrypter plugin""" - __author_name__ = "4Christopher" - __author_mail__ = "4Christopher@gmx.de" + __license__ = "GPLv3" + __authors__ = [("4Christopher", "4Christopher@gmx.de")] + + +getInfo = create_getInfo(Movie2kTo) diff --git a/module/plugins/crypter/MultiUpOrg.py b/module/plugins/crypter/MultiUpOrg.py index ab23def8d..5209ebf09 100644 --- a/module/plugins/crypter/MultiUpOrg.py +++ b/module/plugins/crypter/MultiUpOrg.py @@ -1,42 +1,30 @@ # -*- 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 urlparse import urljoin -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class MultiUpOrg(SimpleCrypter): - __name__ = "MultiUpOrg" - __version__ = "0.01" - __type__ = "crypter" + __name__ = "MultiUpOrg" + __type__ = "crypter" + __version__ = "0.03" __pattern__ = r'http://(?:www\.)?multiup\.org/(en|fr)/(?P<TYPE>project|download|miror)/\w+(/\w+)?' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """MultiUp.org crypter plugin""" - __author_name__ = "Walter Purcaro" - __author_mail__ = "vuolter@gmail.com" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + - TITLE_PATTERN = r'<title>.*(Project|Projet|ownload|élécharger) (?P<title>.+?) (\(|- )' + NAME_PATTERN = r'<title>.*(?:Project|Projet|ownload|élécharger) (?P<N>.+?) (\(|- )' def getLinks(self): - m_type = re.match(self.__pattern__, self.pyfile.url).group("TYPE") + 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/.*)' @@ -48,3 +36,6 @@ class MultiUpOrg(SimpleCrypter): self.html = self.load(miror_page) return re.findall(pattern, self.html) + + +getInfo = create_getInfo(MultiUpOrg) diff --git a/module/plugins/crypter/MultiloadCz.py b/module/plugins/crypter/MultiloadCz.py index 4b39872a7..fa1eb02d7 100644 --- a/module/plugins/crypter/MultiloadCz.py +++ b/module/plugins/crypter/MultiloadCz.py @@ -5,17 +5,20 @@ from module.plugins.Crypter import Crypter class MultiloadCz(Crypter): - __name__ = "MultiloadCz" - __version__ = "0.4" - __type__ = "crypter" + __name__ = "MultiloadCz" + __type__ = "crypter" + __version__ = "0.40" - __pattern__ = r'http://(?:[^/]*\.)?multiload.cz/(stahnout|slozka)/.*' - __config__ = [("usedHoster", "str", "Prefered hoster list (bar-separated) ", ""), - ("ignoredHoster", "str", "Ignored hoster list (bar-separated) ", "")] + __pattern__ = r'http://(?:[^/]*\.)?multiload\.cz/(stahnout|slozka)/.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True), + ("usedHoster", "str", "Prefered hoster list (bar-separated)", ""), + ("ignoredHoster", "str", "Ignored hoster list (bar-separated)", "")] __description__ = """Multiload.cz decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + FOLDER_PATTERN = r'<form action="" method="get"><textarea[^>]*>([^>]*)</textarea></form>' LINK_PATTERN = r'<p class="manager-server"><strong>([^<]+)</strong></p><p class="manager-linky"><a href="([^"]+)">' @@ -37,6 +40,3 @@ class MultiloadCz(Crypter): if not self.urls: ignored_set = set(self.getConfig("ignoredHoster").split('|')) self.urls.extend([x[1] for x in m if x[0] not in ignored_set]) - - if not self.urls: - self.fail('Could not extract any links') diff --git a/module/plugins/crypter/MultiuploadCom.py b/module/plugins/crypter/MultiuploadCom.py index f5c0e292b..347b7e5af 100644 --- a/module/plugins/crypter/MultiuploadCom.py +++ b/module/plugins/crypter/MultiuploadCom.py @@ -1,64 +1,19 @@ # -*- coding: utf-8 -*- -import re -from time import time +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo -from module.plugins.Crypter import Crypter -from module.common.json_layer import json_loads +class MultiuploadCom(DeadCrypter): + __name__ = "MultiuploadCom" + __type__ = "crypter" + __version__ = "0.02" -class MultiuploadCom(Crypter): - __name__ = "MultiuploadCom" - __version__ = "0.01" - __type__ = "crypter" + __pattern__ = r'http://(?:www\.)?multiupload\.(com|nl)/\w+' + __config__ = [] - __pattern__ = r'http://(?:www\.)?multiupload.com/(\w+)' - __config__ = [("preferedHoster", "str", "Prefered hoster list (bar-separated) ", "multiupload"), - ("ignoredHoster", "str", "Ignored hoster list (bar-separated) ", "")] + __description__ = """ MultiUpload.com decrypter plugin """ + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - __description__ = """MultiUpload.com decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" - ML_LINK_PATTERN = r'<div id="downloadbutton_" style=""><a href="([^"]+)"' - - - def decrypt(self, pyfile): - self.html = self.load(pyfile.url) - m = re.search(self.ML_LINK_PATTERN, self.html) - ml_url = m.group(1) if m else None - - json_list = json_loads(self.load("http://multiupload.com/progress/", get={ - "d": re.match(self.__pattern__, pyfile.url).group(1), - "r": str(int(time() * 1000)) - })) - - prefered_set = map(lambda s: s.lower().split('.')[0], set(self.getConfig("preferedHoster").split('|'))) - - if ml_url and 'multiupload' in prefered_set: - self.urls.append(ml_url) - - for link in json_list: - if link['service'].lower() in prefered_set and int(link['status']) and not int(link['deleted']): - url = self.getLocation(link['url']) - if url: - self.urls.append(url) - - if not self.urls: - ignored_set = map(lambda s: s.lower().split('.')[0], set(self.getConfig("ignoredHoster").split('|'))) - - if 'multiupload' not in ignored_set: - self.urls.append(ml_url) - - for link in json_list: - if link['service'].lower() not in ignored_set and int(link['status']) and not int(link['deleted']): - url = self.getLocation(link['url']) - if url: - self.urls.append(url) - - if not self.urls: - self.fail('Could not extract any links') - - def getLocation(self, url): - header = self.load(url, just_header=True) - return header['location'] if "location" in header else None +getInfo = create_getInfo(MultiuploadCom) diff --git a/module/plugins/crypter/NCryptIn.py b/module/plugins/crypter/NCryptIn.py index 9a9d76f51..8b7214157 100644 --- a/module/plugins/crypter/NCryptIn.py +++ b/module/plugins/crypter/NCryptIn.py @@ -11,15 +11,19 @@ from module.plugins.internal.CaptchaService import ReCaptcha class NCryptIn(Crypter): - __name__ = "NCryptIn" - __version__ = "1.32" - __type__ = "crypter" + __name__ = "NCryptIn" + __type__ = "crypter" + __version__ = "1.33" - __pattern__ = r'http://(?:www\.)?ncrypt.in/(?P<type>folder|link|frame)-([^/\?]+)' + __pattern__ = r'http://(?:www\.)?ncrypt\.in/(?P<TYPE>folder|link|frame)-([^/\?]+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """NCrypt.in decrypter plugin""" - __author_name__ = ("fragonib", "stickell") - __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "l.stickell@yahoo.it") + __license__ = "GPLv3" + __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es"), + ("stickell", "l.stickell@yahoo.it")] + JK_KEY = "jk" CRYPTED_KEY = "crypted" @@ -29,11 +33,11 @@ class NCryptIn(Crypter): def setup(self): self.package = None - self.html = None self.cleanedHtml = None self.links_source_order = ["cnl2", "rsdf", "ccf", "dlc", "web"] self.protection_type = None + def decrypt(self, pyfile): # Init self.package = pyfile.package() @@ -54,7 +58,7 @@ class NCryptIn(Crypter): if not self.isOnline(): self.offline() - # Check for folder protection + # Check for folder protection if self.isProtected(): self.html = self.unlockProtection() self.cleanedHtml = self.removeHtmlCrap(self.html) @@ -71,17 +75,19 @@ class NCryptIn(Crypter): package_links = set(package_links) # Pack and return links - if not package_links: - self.fail('Could not extract any links') - self.packages = [(package_name, package_links, folder_name)] + if package_links: + self.packages = [(package_name, package_links, folder_name)] + def isSingleLink(self): - link_type = re.match(self.__pattern__, self.pyfile.url).group('type') + link_type = re.match(self.__pattern__, self.pyfile.url).group('TYPE') return link_type in ("link", "frame") + def requestFolderHome(self): return self.load(self.pyfile.url, decode=True) + def removeHtmlCrap(self, content): patterns = (r'(type="hidden".*?(name=".*?")?.*?value=".*?")', r'display:none;">(.*?)</(div|span)>', @@ -89,18 +95,20 @@ class NCryptIn(Crypter): r'<table class="global">(.*?)</table>', r'<iframe\s+style="display:none(.*?)</iframe>') for pattern in patterns: - rexpr = re.compile(pattern, re.DOTALL) + rexpr = re.compile(pattern, re.S) content = re.sub(rexpr, "", content) return content + def isOnline(self): if "Your folder does not exist" in self.cleanedHtml: self.logDebug("File not m") return False return True + def isProtected(self): - form = re.search(r'<form.*?name.*?protected.*?>(.*?)</form>', self.cleanedHtml, re.DOTALL) + form = re.search(r'<form.*?name.*?protected.*?>(.*?)</form>', self.cleanedHtml, re.S) if form is not None: content = form.group(1) for keyword in ("password", "captcha"): @@ -110,6 +118,7 @@ class NCryptIn(Crypter): return True return False + def getPackageInfo(self): m = re.search(self.NAME_PATTERN, self.html) if m: @@ -121,11 +130,11 @@ class NCryptIn(Crypter): self.logDebug("Package info not m, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) return name, folder - def unlockProtection(self): + def unlockProtection(self): postData = {} - form = re.search(r'<form name="protected"(.*?)</form>', self.cleanedHtml, re.DOTALL).group(1) + form = re.search(r'<form name="protected"(.*?)</form>', self.cleanedHtml, re.S).group(1) # Submit package password if "password" in form: @@ -141,15 +150,15 @@ class NCryptIn(Crypter): self.logDebug("Captcha resolved [%s]" % captcha) postData['captcha'] = captcha - # Resolve recaptcha + # Resolve recaptcha if "recaptcha" in form: self.logDebug("ReCaptcha protected") captcha_key = re.search(r'\?k=(.*?)"', form).group(1) self.logDebug("Resolving ReCaptcha with key [%s]" % captcha_key) recaptcha = ReCaptcha(self) - challenge, code = recaptcha.challenge(captcha_key) + challenge, response = recaptcha.challenge(captcha_key) postData['recaptcha_challenge_field'] = challenge - postData['recaptcha_response_field'] = code + postData['recaptcha_response_field'] = response # Resolve circlecaptcha if "circlecaptcha" in form: @@ -164,20 +173,21 @@ class NCryptIn(Crypter): postData['submit_protected'] = 'Continue to folder' return self.load(self.pyfile.url, post=postData, decode=True) + def handleErrors(self): if self.protection_type == "password": if "This password is invalid!" in self.cleanedHtml: self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry") - self.fail("Incorrect password, please set right password on 'Edit package' form and retry") + self.fail(_("Incorrect password, please set right password on 'Edit package' form and retry")) if self.protection_type == "captcha": if "The securitycheck was wrong!" in self.cleanedHtml: - self.logDebug("Invalid captcha, retrying") self.invalidCaptcha() self.retry() else: self.correctCaptcha() + def handleLinkSource(self, link_source_type): # Check for JS engine require_js_engine = link_source_type in ("cnl2", "rsdf", "ccf", "dlc") @@ -195,10 +205,10 @@ class NCryptIn(Crypter): elif link_source_type == "web": return self.handleWebLinks() else: - self.fail('unknown source type "%s" (this is probably a bug)' % link_source_type) + self.error('Unknown source type "%s" (this is probably a bug)' % link_source_type) - def handleSingleLink(self): + def handleSingleLink(self): self.logDebug("Handling Single link") package_links = [] @@ -209,8 +219,8 @@ class NCryptIn(Crypter): return package_links - def handleCNL2(self): + def handleCNL2(self): self.logDebug("Handling CNL2 links") package_links = [] @@ -220,16 +230,16 @@ class NCryptIn(Crypter): for (crypted, jk) in zip(vcrypted, vjk): package_links.extend(self._getLinks(crypted, jk)) except: - self.fail("Unable to decrypt CNL2 links") + self.fail(_("Unable to decrypt CNL2 links")) return package_links - def handleContainers(self): + def handleContainers(self): self.logDebug("Handling Container links") package_links = [] - pattern = r"/container/(rsdf|dlc|ccf)/([a-z0-9]+)" + pattern = r'/container/(rsdf|dlc|ccf)/(\w+)' containersLinks = re.findall(pattern, self.html) self.logDebug("Decrypting %d Container links" % len(containersLinks)) for containerLink in containersLinks: @@ -238,10 +248,10 @@ class NCryptIn(Crypter): return package_links - def handleWebLinks(self): + def handleWebLinks(self): self.logDebug("Handling Web links") - pattern = r"(http://ncrypt\.in/link-.*?=)" + pattern = r'(http://ncrypt\.in/link-.*?=)' links = re.findall(pattern, self.html) package_links = [] @@ -254,6 +264,7 @@ class NCryptIn(Crypter): return package_links + def decryptLink(self, link): try: url = link.replace("link-", "frame-") @@ -262,8 +273,8 @@ class NCryptIn(Crypter): except Exception, detail: self.logDebug("Error decrypting link %s, %s" % (link, detail)) - def _getCipherParams(self): + def _getCipherParams(self): pattern = r'<input.*?name="%s".*?value="(.*?)"' # Get jk @@ -278,6 +289,7 @@ class NCryptIn(Crypter): self.logDebug("Detected %d crypted blocks" % len(vcrypted)) return vcrypted, vjk + def _getLinks(self, crypted, jk): # Get key jreturn = self.js.eval("%s f()" % jk) diff --git a/module/plugins/crypter/NetfolderIn.py b/module/plugins/crypter/NetfolderIn.py index 4c7660ab5..62dc5c914 100644 --- a/module/plugins/crypter/NetfolderIn.py +++ b/module/plugins/crypter/NetfolderIn.py @@ -2,41 +2,36 @@ import re -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class NetfolderIn(SimpleCrypter): - __name__ = "NetfolderIn" - __version__ = "0.6" - __type__ = "crypter" + __name__ = "NetfolderIn" + __type__ = "crypter" + __version__ = "0.72" - __pattern__ = r'http://(?:www\.)?netfolder.in/((?P<id1>\w+)/\w+|folder.php\?folder_id=(?P<id2>\w+))' + __pattern__ = r'http://(?:www\.)?netfolder\.in/(folder\.php\?folder_id=)?(?P<ID>\w+)(?(1)|/\w+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """NetFolder.in decrypter plugin""" - __author_name__ = ("RaNaN", "fragonib") - __author_mail__ = ("RaNaN@pyload.org", "fragonib[AT]yahoo[DOT]es") + __license__ = "GPLv3" + __authors__ = [("RaNaN", "RaNaN@pyload.org"), + ("fragonib", "fragonib[AT]yahoo[DOT]es")] - TITLE_PATTERN = r'<div class="Text">Inhalt des Ordners <span(.*)>(?P<title>.+)</span></div>' + NAME_PATTERN = r'<div class="Text">Inhalt des Ordners <span.*>(?P<N>.+)</span></div>' - def decrypt(self, pyfile): - # Request package - self.html = self.load(pyfile.url) - # Check for password protection + def prepare(self): + super(NetfolderIn, self).prepare() + + # Check for password protection if self.isPasswordProtected(): self.html = self.submitPassword() if not self.html: - self.fail("Incorrect password, please set right password on Add package form and retry") - - # Get package name and folder - (package_name, folder_name) = self.getPackageNameAndFolder() + self.fail(_("Incorrect password, please set right password on Add package form and retry")) - # Get package links - package_links = self.getLinks() - - # Set package - self.packages = [(package_name, package_links, folder_name)] def isPasswordProtected(self): if '<input type="password" name="password"' in self.html: @@ -44,18 +39,19 @@ class NetfolderIn(SimpleCrypter): return True return False + def submitPassword(self): # Gather data try: - m = re.match(self.__pattern__, self.pyfile.url) - id = max(m.group('id1'), m.group('id2')) + m = re.match(self.__pattern__, self.pyfile.url) + id = m.group('ID') except AttributeError: self.logDebug("Unable to get package id from url [%s]" % self.pyfile.url) return url = "http://netfolder.in/folder.php?folder_id=" + id password = self.getPassword() - # Submit package password + # Submit package password post = {'password': password, 'save': 'Absenden'} self.logDebug("Submitting password [%s] for protected links with id [%s]" % (password, id)) html = self.load(url, {}, post) @@ -67,7 +63,11 @@ class NetfolderIn(SimpleCrypter): return html + def getLinks(self): links = re.search(r'name="list" value="(.*?)"', self.html).group(1).split(",") self.logDebug("Package has %d links" % len(links)) return links + + +getInfo = create_getInfo(NetfolderIn) diff --git a/module/plugins/crypter/NosvideoCom.py b/module/plugins/crypter/NosvideoCom.py index 2656b9374..1e280abd2 100644 --- a/module/plugins/crypter/NosvideoCom.py +++ b/module/plugins/crypter/NosvideoCom.py @@ -1,18 +1,24 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class NosvideoCom(SimpleCrypter): - __name__ = "NosvideoCom" - __version__ = "0.01" - __type__ = "crypter" + __name__ = "NosvideoCom" + __type__ = "crypter" + __version__ = "0.03" __pattern__ = r'http://(?:www\.)?nosvideo\.com/\?v=\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Nosvideo.com decrypter plugin""" - __author_name__ = "igel" - __author_mail__ = "igelkun@myopera.com" + __license__ = "GPLv3" + __authors__ = [("igel", "igelkun@myopera.com")] - LINK_PATTERN = r'href="(http://(?:w{3}\.)?nosupload.com/\?d=\w+)"' - TITLE_PATTERN = r'<[tT]itle>Watch (?P<title>.+)</[tT]itle>' + + LINK_PATTERN = r'href="(http://(?:w{3}\.)?nosupload\.com/\?d=\w+)"' + NAME_PATTERN = r'<[tT]itle>Watch (?P<N>.+?)<' + + +getInfo = create_getInfo(NosvideoCom) diff --git a/module/plugins/crypter/OneKhDe.py b/module/plugins/crypter/OneKhDe.py index 91c591ec1..cfb084da8 100644 --- a/module/plugins/crypter/OneKhDe.py +++ b/module/plugins/crypter/OneKhDe.py @@ -7,32 +7,35 @@ from module.plugins.Crypter import Crypter class OneKhDe(Crypter): - __name__ = "OneKhDe" - __version__ = "0.1" - __type__ = "crypter" + __name__ = "OneKhDe" + __type__ = "crypter" + __version__ = "0.10" - __pattern__ = r'http://(?:www\.)?1kh.de/f/' + __pattern__ = r'http://(?:www\.)?1kh\.de/f/' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """1kh.de decrypter plugin""" - __author_name__ = "spoob" - __author_mail__ = "spoob@pyload.org" + __license__ = "GPLv3" + __authors__ = [("spoob", "spoob@pyload.org")] def __init__(self, parent): Crypter.__init__(self, parent) self.parent = parent - self.html = None + def file_exists(self): """ returns True or False """ return True + def proceed(self, url, location): url = self.parent.url - self.html = self.req.load(url) + self.html = self.load(url) link_ids = re.findall(r"<a id=\"DownloadLink_(\d*)\" href=\"http://1kh.de/", self.html) for id in link_ids: new_link = unescape( - re.search("width=\"100%\" src=\"(.*)\"></iframe>", self.req.load("http://1kh.de/l/" + id)).group(1)) + re.search("width=\"100%\" src=\"(.*)\"></iframe>", self.load("http://1kh.de/l/" + id)).group(1)) self.urls.append(new_link) diff --git a/module/plugins/crypter/OronComFolder.py b/module/plugins/crypter/OronComFolder.py index 988c5c959..9e06bdf32 100755 --- a/module/plugins/crypter/OronComFolder.py +++ b/module/plugins/crypter/OronComFolder.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class OronComFolder(DeadCrypter): - __name__ = "OronComFolder" + __name__ = "OronComFolder" + __type__ = "crypter" __version__ = "0.11" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?oron.com/folder/\w+' + __pattern__ = r'http://(?:www\.)?oron\.com/folder/\w+' + __config__ = [] __description__ = """Oron.com folder decrypter plugin""" - __author_name__ = "DHMH" - __author_mail__ = "webmaster@pcProfil.de" + __license__ = "GPLv3" + __authors__ = [("DHMH", "webmaster@pcProfil.de")] + + +getInfo = create_getInfo(OronComFolder) diff --git a/module/plugins/crypter/PastebinCom.py b/module/plugins/crypter/PastebinCom.py index 172a4183f..b3d5a4bea 100644 --- a/module/plugins/crypter/PastebinCom.py +++ b/module/plugins/crypter/PastebinCom.py @@ -1,32 +1,24 @@ # -*- 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.SimpleCrypter import SimpleCrypter + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class PastebinCom(SimpleCrypter): - __name__ = "PastebinCom" - __version__ = "0.01" - __type__ = "crypter" + __name__ = "PastebinCom" + __type__ = "crypter" + __version__ = "0.03" __pattern__ = r'http://(?:www\.)?pastebin\.com/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Pastebin.com decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] + LINK_PATTERN = r'<div class="de\d+">(https?://[^ <]+)(?:[^<]*)</div>' - TITLE_PATTERN = r'<div class="paste_box_line1" title="(?P<title>[^"]+)">' + NAME_PATTERN = r'<div class="paste_box_line1" title="(?P<N>[^"]+)">' + + +getInfo = create_getInfo(PastebinCom) diff --git a/module/plugins/crypter/QuickshareCzFolder.py b/module/plugins/crypter/QuickshareCzFolder.py index 1e569a20a..70666b55a 100644 --- a/module/plugins/crypter/QuickshareCzFolder.py +++ b/module/plugins/crypter/QuickshareCzFolder.py @@ -5,27 +5,27 @@ from module.plugins.Crypter import Crypter class QuickshareCzFolder(Crypter): - __name__ = "QuickshareCzFolder" - __version__ = "0.1" - __type__ = "crypter" + __name__ = "QuickshareCzFolder" + __type__ = "crypter" + __version__ = "0.10" - __pattern__ = r'http://(?:www\.)?quickshare.cz/slozka-\d+.*' + __pattern__ = r'http://(?:www\.)?quickshare\.cz/slozka-\d+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Quickshare.cz folder decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + FOLDER_PATTERN = r'<textarea[^>]*>(.*?)</textarea>' - LINK_PATTERN = r'(http://www.quickshare.cz/\S+)' + LINK_PATTERN = r'(http://www\.quickshare\.cz/\S+)' def decrypt(self, pyfile): html = self.load(pyfile.url) - m = re.search(self.FOLDER_PATTERN, html, re.DOTALL) + m = re.search(self.FOLDER_PATTERN, html, re.S) if m is None: - self.fail("Parse error (FOLDER)") + self.error(_("FOLDER_PATTERN not found")) self.urls.extend(re.findall(self.LINK_PATTERN, m.group(1))) - - if not self.urls: - self.fail('Could not extract any links') diff --git a/module/plugins/crypter/RSLayerCom.py b/module/plugins/crypter/RSLayerCom.py index 637caf2ce..cc3b23bbc 100644 --- a/module/plugins/crypter/RSLayerCom.py +++ b/module/plugins/crypter/RSLayerCom.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class RSLayerCom(DeadCrypter): - __name__ = "RSLayerCom" + __name__ = "RSLayerCom" + __type__ = "crypter" __version__ = "0.21" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?rs-layer.com/directory-' + __pattern__ = r'http://(?:www\.)?rs-layer\.com/directory-' + __config__ = [] __description__ = """RS-Layer.com decrypter plugin""" - __author_name__ = "hzpz" - __author_mail__ = None + __license__ = "GPLv3" + __authors__ = [("hzpz", None)] + + +getInfo = create_getInfo(RSLayerCom) diff --git a/module/plugins/crypter/RapidfileshareNetFolder.py b/module/plugins/crypter/RapidfileshareNetFolder.py new file mode 100644 index 000000000..fc3d4241e --- /dev/null +++ b/module/plugins/crypter/RapidfileshareNetFolder.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo + + +class RapidfileshareNetFolder(XFSCrypter): + __name__ = "RapidfileshareNetFolder" + __type__ = "crypter" + __version__ = "0.03" + + __pattern__ = r'http://(?:www\.)?rapidfileshare\.net/users/\w+/\d+/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """Rapidfileshare.net folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("guidobelix", "guidobelix@hotmail.it")] + + + HOSTER_DOMAIN = "rapidfileshare.net" + + +getInfo = create_getInfo(RapidfileshareNetFolder) diff --git a/module/plugins/crypter/RelinkUs.py b/module/plugins/crypter/RelinkUs.py index 160900144..5933839ec 100644 --- a/module/plugins/crypter/RelinkUs.py +++ b/module/plugins/crypter/RelinkUs.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +from __future__ import with_statement + import base64 import binascii import re @@ -10,48 +12,56 @@ from module.plugins.Crypter import Crypter class RelinkUs(Crypter): - __name__ = "RelinkUs" - __version__ = "3.0" - __type__ = "crypter" + __name__ = "RelinkUs" + __type__ = "crypter" + __version__ = "3.11" - __pattern__ = r'http://(?:www\.)?relink.us/(f/|((view|go).php\?id=))(?P<id>.+)' + __pattern__ = r'http://(?:www\.)?relink\.us/(f/|((view|go)\.php\?id=))(?P<ID>.+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Relink.us decrypter plugin""" - __author_name__ = "fragonib" - __author_mail__ = "fragonib[AT]yahoo[DOT]es" + __license__ = "GPLv3" + __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es"), + ("AndroKev", "neureither.kevin@gmail.com")] + - # Constants PREFERRED_LINK_SOURCES = ["cnl2", "dlc", "web"] OFFLINE_TOKEN = r'<title>Tattooside' - PASSWORD_TOKEN = r'container_password\.php' + + PASSWORD_TOKEN = r'container_password.php' PASSWORD_ERROR_ROKEN = r'You have entered an incorrect password' - PASSWORD_SUBMIT_URL = r'http://www\.relink\.us/container_password\.php' - CAPTCHA_TOKEN = r'container_captcha\.php' + PASSWORD_SUBMIT_URL = r'http://www.relink.us/container_password.php' + + CAPTCHA_TOKEN = r'container_captcha.php' CAPTCHA_ERROR_ROKEN = r'You have solved the captcha wrong' - CAPTCHA_IMG_URL = r'http://www\.relink\.us/core/captcha/circlecaptcha\.php' - CAPTCHA_SUBMIT_URL = r'http://www\.relink\.us/container_captcha\.php' - FILE_TITLE_REGEX = r'<th>Title</th><td><i>(.*)</i></td></tr>' + CAPTCHA_IMG_URL = r'http://www.relink.us/core/captcha/circlecaptcha.php' + CAPTCHA_SUBMIT_URL = r'http://www.relink.us/container_captcha.php' + + FILE_TITLE_REGEX = r'<th>Title</th><td>(.*)</td></tr>' FILE_NOTITLE = r'No title' CNL2_FORM_REGEX = r'<form id="cnl_form-(.*?)</form>' CNL2_FORMINPUT_REGEX = r'<input.*?name="%s".*?value="(.*?)"' CNL2_JK_KEY = "jk" CNL2_CRYPTED_KEY = "crypted" + DLC_LINK_REGEX = r'<a href=".*?" class="dlc_button" target="_blank">' - DLC_DOWNLOAD_URL = r'http://www\.relink\.us/download\.php' - WEB_FORWARD_REGEX = r"getFile\('(?P<link>.+)'\)" - WEB_FORWARD_URL = r'http://www\.relink\.us/frame\.php' - WEB_LINK_REGEX = r'<iframe name="Container" height="100%" frameborder="no" width="100%" src="(?P<link>.+)"></iframe>' + DLC_DOWNLOAD_URL = r'http://www.relink.us/download.php' + + WEB_FORWARD_REGEX = r'getFile\(\'(.+)\'\)' + WEB_FORWARD_URL = r'http://www.relink.us/frame.php' + WEB_LINK_REGEX = r'<iframe name="Container" height="100%" frameborder="no" width="100%" src="(.+)"></iframe>' def setup(self): self.fileid = None self.package = None self.password = None - self.html = None self.captcha = False + def decrypt(self, pyfile): # Init self.initPackage(pyfile) @@ -63,7 +73,7 @@ class RelinkUs(Crypter): if not self.isOnline(): self.offline() - # Check for protection + # Check for protection if self.isPasswordProtected(): self.unlockPasswordProtection() self.handleErrors() @@ -87,40 +97,45 @@ class RelinkUs(Crypter): # Pack if package_links: self.packages = [(package_name, package_links, folder_name)] - else: - self.fail('Could not extract any links') + def initPackage(self, pyfile): - self.fileid = re.match(self.__pattern__, pyfile.url).group('id') + self.fileid = re.match(self.__pattern__, pyfile.url).group('ID') self.package = pyfile.package() self.password = self.getPassword() + def requestPackage(self): self.html = self.load(self.pyfile.url, decode=True) + def isOnline(self): if self.OFFLINE_TOKEN in self.html: self.logDebug("File not found") return False return True + def isPasswordProtected(self): if self.PASSWORD_TOKEN in self.html: self.logDebug("Links are password protected") return True + def isCaptchaProtected(self): if self.CAPTCHA_TOKEN in self.html: self.logDebug("Links are captcha protected") return True return False + def unlockPasswordProtection(self): self.logDebug("Submitting password [%s] for protected links" % self.password) passwd_url = self.PASSWORD_SUBMIT_URL + "?id=%s" % self.fileid passwd_data = {'id': self.fileid, 'password': self.password, 'pw': 'submit'} self.html = self.load(passwd_url, post=passwd_data, decode=True) + def unlockCaptchaProtection(self): self.logDebug("Request user positional captcha resolving") captcha_img_url = self.CAPTCHA_IMG_URL + "?id=%s" % self.fileid @@ -130,10 +145,11 @@ class RelinkUs(Crypter): captcha_post_data = {'button.x': coords[0], 'button.y': coords[1], 'captcha': 'submit'} self.html = self.load(captcha_post_url, post=captcha_post_data, decode=True) + def getPackageInfo(self): name = folder = None - # Try to get info from web + # Try to get info from web m = re.search(self.FILE_TITLE_REGEX, self.html) if m is not None: title = m.group(1).strip() @@ -147,23 +163,24 @@ class RelinkUs(Crypter): folder = self.package.folder self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) - # Return package info + # Return package info return name, folder + def handleErrors(self): if self.PASSWORD_ERROR_ROKEN in self.html: msg = "Incorrect password, please set right password on 'Edit package' form and retry" self.logDebug(msg) - self.fail(msg) + self.fail(_(msg)) if self.captcha: if self.CAPTCHA_ERROR_ROKEN in self.html: - self.logDebug("Invalid captcha, retrying") self.invalidCaptcha() self.retry() else: self.correctCaptcha() + def handleLinkSource(self, source): if source == 'cnl2': return self.handleCNL2Links() @@ -172,12 +189,13 @@ class RelinkUs(Crypter): elif source == 'web': return self.handleWEBLinks() else: - self.fail('Unknown source [%s] (this is probably a bug)' % source) + self.error('Unknown source type "%s" (this is probably a bug)' % source) + def handleCNL2Links(self): self.logDebug("Search for CNL2 links") package_links = [] - m = re.search(self.CNL2_FORM_REGEX, self.html, re.DOTALL) + m = re.search(self.CNL2_FORM_REGEX, self.html, re.S) if m is not None: cnl2_form = m.group(1) try: @@ -188,8 +206,9 @@ class RelinkUs(Crypter): self.logDebug("Unable to decrypt CNL2 links") return package_links + def handleDLCLinks(self): - self.logDebug('Search for DLC links') + self.logDebug("Search for DLC links") package_links = [] m = re.search(self.DLC_LINK_REGEX, self.html) if m is not None: @@ -199,45 +218,56 @@ class RelinkUs(Crypter): dlc = self.load(container_url) dlc_filename = self.fileid + ".dlc" dlc_filepath = os.path.join(self.config['general']['download_folder'], dlc_filename) - f = open(dlc_filepath, "wb") - f.write(dlc) - f.close() + with open(dlc_filepath, "wb") as f: + f.write(dlc) package_links.append(dlc_filepath) except: - self.logDebug("Unable to download DLC container") + self.fail("Unable to download DLC container") return package_links + def handleWEBLinks(self): self.logDebug("Search for WEB links") + package_links = [] - fw_params = re.findall(self.WEB_FORWARD_REGEX, self.html) - self.logDebug("Decrypting %d Web links" % len(fw_params)) - for index, fw_param in enumerate(fw_params): + params = re.findall(self.WEB_FORWARD_REGEX, self.html) + + self.logDebug("Decrypting %d Web links" % len(params)) + + for index, param in enumerate(params): try: - fw_url = self.WEB_FORWARD_URL + "?%s" % fw_param - self.logDebug("Decrypting Web link %d, %s" % (index + 1, fw_url)) - fw_response = self.load(fw_url, decode=True) - dl_link = re.search(self.WEB_LINK_REGEX, fw_response).group('link') - package_links.append(dl_link) + url = self.WEB_FORWARD_URL + "?%s" % param + + self.logDebug("Decrypting Web link %d, %s" % (index + 1, url)) + + res = self.load(url, decode=True) + link = re.search(self.WEB_LINK_REGEX, res).group(1) + + package_links.append(link) + except Exception, detail: self.logDebug("Error decrypting Web link %s, %s" % (index, detail)) + self.setWait(4) self.wait() + return package_links + def _getCipherParams(self, cnl2_form): # Get jk jk_re = self.CNL2_FORMINPUT_REGEX % self.CNL2_JK_KEY - vjk = re.findall(jk_re, cnl2_form, re.IGNORECASE) + vjk = re.findall(jk_re, cnl2_form, re.I) # Get crypted crypted_re = self.CNL2_FORMINPUT_REGEX % RelinkUs.CNL2_CRYPTED_KEY - vcrypted = re.findall(crypted_re, cnl2_form, re.IGNORECASE) + vcrypted = re.findall(crypted_re, cnl2_form, re.I) # Log and return self.logDebug("Detected %d crypted blocks" % len(vcrypted)) return vcrypted, vjk + def _getLinks(self, crypted, jk): # Get key jreturn = self.js.eval("%s f()" % jk) diff --git a/module/plugins/crypter/SafelinkingNet.py b/module/plugins/crypter/SafelinkingNet.py index 2687ed2f2..709083b51 100644 --- a/module/plugins/crypter/SafelinkingNet.py +++ b/module/plugins/crypter/SafelinkingNet.py @@ -1,66 +1,67 @@ # -*- coding: utf-8 -*- import re + from pycurl import FOLLOWLOCATION +from BeautifulSoup import BeautifulSoup + from module.common.json_layer import json_loads from module.plugins.Crypter import Crypter from module.plugins.internal.CaptchaService import SolveMedia -from module.lib.BeautifulSoup import BeautifulSoup class SafelinkingNet(Crypter): - __name__ = "SafelinkingNet" - __version__ = "0.1" - __type__ = "crypter" + __name__ = "SafelinkingNet" + __type__ = "crypter" + __version__ = "0.11" - __pattern__ = r'https?://(?:www\.)?safelinking.net/([pd])/\w+' + __pattern__ = r'https?://(?:www\.)?safelinking\.net/([pd])/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Safelinking.net decrypter plugin""" - __author_name__ = "quareevo" - __author_mail__ = "quareevo@arcor.de" + __license__ = "GPLv3" + __authors__ = [("quareevo", "quareevo@arcor.de")] - SOLVEMEDIA_PATTERN = "solvemediaApiKey = '([\w\.\-_]+)';" + + SOLVEMEDIA_PATTERN = "solvemediaApiKey = '([\w.-]+)';" def decrypt(self, pyfile): url = pyfile.url + if re.match(self.__pattern__, url).group(1) == "d": - self.req.http.c.setopt(FOLLOWLOCATION, 0) - self.load(url) - m = re.search("^Location: (.+)$", self.req.http.header, re.MULTILINE) - if m: - self.urls = [m.group(1)] + + header = self.load(url, just_header=True) + if 'location' in header: + self.urls = [header['location']] else: - self.fail("Couldn't find forwarded Link") + self.error(_("Couldn't find forwarded Link")) else: - password = "" postData = {"post-protect": "1"} - self.html = self.load(url) - if "link-password" in self.html: - password = pyfile.package().password - postData['link-password'] = password + postData['link-password'] = self.getPassword() if "altcaptcha" in self.html: - for _ in xrange(5): + for _i in xrange(5): m = re.search(self.SOLVEMEDIA_PATTERN, self.html) if m: captchaKey = m.group(1) captcha = SolveMedia(self) captchaProvider = "Solvemedia" else: - self.fail("Error parsing captcha") + self.fail(_("Error parsing captcha")) challenge, response = captcha.challenge(captchaKey) postData['adcopy_challenge'] = challenge - postData['adcopy_response'] = response + postData['adcopy_response'] = response self.html = self.load(url, post=postData) if "The password you entered was incorrect" in self.html: - self.fail("Incorrect Password") + self.fail(_("Incorrect Password")) if not "The CAPTCHA code you entered was wrong" in self.html: break diff --git a/module/plugins/crypter/SecuredIn.py b/module/plugins/crypter/SecuredIn.py index 1a6650195..cbfa919ac 100644 --- a/module/plugins/crypter/SecuredIn.py +++ b/module/plugins/crypter/SecuredIn.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class SecuredIn(DeadCrypter): - __name__ = "SecuredIn" + __name__ = "SecuredIn" + __type__ = "crypter" __version__ = "0.21" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?secured\.in/download-[\d]+-[\w]{8}\.html' + __pattern__ = r'http://(?:www\.)?secured\.in/download-[\d]+-\w{8}\.html' + __config__ = [] __description__ = """Secured.in decrypter plugin""" - __author_name__ = "mkaay" - __author_mail__ = "mkaay@mkaay.de" + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] + + +getInfo = create_getInfo(SecuredIn) diff --git a/module/plugins/crypter/SerienjunkiesOrg.py b/module/plugins/crypter/SerienjunkiesOrg.py deleted file mode 100644 index ea76d30d0..000000000 --- a/module/plugins/crypter/SerienjunkiesOrg.py +++ /dev/null @@ -1,323 +0,0 @@ -# -*- coding: utf-8 -*- - -import random -import re - -from time import sleep - -from module.lib.BeautifulSoup import BeautifulSoup -from module.plugins.Crypter import Crypter -from module.unescape import unescape - - -class SerienjunkiesOrg(Crypter): - __name__ = "SerienjunkiesOrg" - __version__ = "0.39" - __type__ = "crypter" - - __pattern__ = r'http://(?:www\.)?(serienjunkies.org|dokujunkies.org)/.*?' - __config__ = [("changeNameSJ", "Packagename;Show;Season;Format;Episode", "Take SJ.org name", "Show"), - ("changeNameDJ", "Packagename;Show;Format;Episode", "Take DJ.org name", "Show"), - ("randomPreferred", "bool", "Randomize Preferred-List", False), - ("hosterListMode", "OnlyOne;OnlyPreferred(One);OnlyPreferred(All);All", - "Use for hosters (if supported)", "All"), - ("hosterList", "str", "Preferred Hoster list (comma separated)", - "RapidshareCom,UploadedTo,NetloadIn,FilefactoryCom,FreakshareNet,FilebaseTo,HotfileCom,DepositfilesCom,EasyshareCom,KickloadCom"), - ("ignoreList", "str", "Ignored Hoster list (comma separated)", "MegauploadCom")] - - __description__ = """Serienjunkies.org decrypter plugin""" - __author_name__ = ("mkaay", "godofdream") - __author_mail__ = ("mkaay@mkaay.de", "soilfiction@gmail.com") - - - def setup(self): - self.multiDL = False - - def getSJSrc(self, url): - src = self.req.load(str(url)) - if "This website is not available in your country" in src: - self.fail("Not available in your country") - if not src.find("Enter Serienjunkies") == -1: - sleep(1) - src = self.req.load(str(url)) - return src - - def handleShow(self, url): - src = self.getSJSrc(url) - soup = BeautifulSoup(src) - packageName = self.pyfile.package().name - if self.getConfig("changeNameSJ") == "Show": - found = unescape(soup.find("h2").find("a").string.split(' –')[0]) - if found: - packageName = found - - nav = soup.find("div", attrs={"id": "scb"}) - - package_links = [] - for a in nav.findAll("a"): - if self.getConfig("changeNameSJ") == "Show": - package_links.append(a['href']) - else: - package_links.append(a['href'] + "#hasName") - if self.getConfig("changeNameSJ") == "Show": - self.packages.append((packageName, package_links, packageName)) - else: - self.core.files.addLinks(package_links, self.pyfile.package().id) - - def handleSeason(self, url): - src = self.getSJSrc(url) - soup = BeautifulSoup(src) - post = soup.find("div", attrs={"class": "post-content"}) - ps = post.findAll("p") - - seasonName = unescape(soup.find("a", attrs={"rel": "bookmark"}).string).replace("–", "-") - groups = {} - gid = -1 - for p in ps: - if re.search("<strong>Sprache|<strong>Format", str(p)): - var = p.findAll("strong") - opts = {"Sprache": "", "Format": ""} - for v in var: - n = unescape(v.string).strip() - n = re.sub(r"^([:]?)(.*?)([:]?)$", r'\2', n) - if n.strip() not in opts: - continue - val = v.nextSibling - if not val: - continue - val = val.replace("|", "").strip() - val = re.sub(r"^([:]?)(.*?)([:]?)$", r'\2', val) - opts[n.strip()] = val.strip() - gid += 1 - groups[gid] = {} - groups[gid]['ep'] = {} - groups[gid]['opts'] = opts - elif re.search("<strong>Download:", str(p)): - parts = str(p).split("<br />") - if re.search("<strong>", parts[0]): - ename = re.search('<strong>(.*?)</strong>', parts[0]).group(1).strip().decode("utf-8").replace( - "–", "-") - groups[gid]['ep'][ename] = {} - parts.remove(parts[0]) - for part in parts: - hostername = re.search(r" \| ([-a-zA-Z0-9]+\.\w+)", part) - if hostername: - hostername = hostername.group(1) - groups[gid]['ep'][ename][hostername] = [] - links = re.findall('href="(.*?)"', part) - for link in links: - groups[gid]['ep'][ename][hostername].append(link + "#hasName") - - links = [] - for g in groups.values(): - for ename in g['ep']: - links.extend(self.getpreferred(g['ep'][ename])) - if self.getConfig("changeNameSJ") == "Episode": - self.packages.append((ename, links, ename)) - links = [] - package = "%s (%s, %s)" % (seasonName, g['opts']['Format'], g['opts']['Sprache']) - if self.getConfig("changeNameSJ") == "Format": - self.packages.append((package, links, package)) - links = [] - if (self.getConfig("changeNameSJ") == "Packagename") or re.search("#hasName", url): - self.core.files.addLinks(links, self.pyfile.package().id) - elif (self.getConfig("changeNameSJ") == "Season") or not re.search("#hasName", url): - self.packages.append((seasonName, links, seasonName)) - - def handleEpisode(self, url): - src = self.getSJSrc(url) - if not src.find( - "Du hast das Download-Limit überschritten! Bitte versuche es später nocheinmal.") == -1: - self.fail(_("Downloadlimit reached")) - else: - soup = BeautifulSoup(src) - form = soup.find("form") - h1 = soup.find("h1") - - if h1.get("class") == "wrap": - captchaTag = soup.find(attrs={"src": re.compile("^/secure/")}) - if not captchaTag: - sleep(5) - self.retry() - - captchaUrl = "http://download.serienjunkies.org" + captchaTag['src'] - result = self.decryptCaptcha(str(captchaUrl), imgtype="png") - sinp = form.find(attrs={"name": "s"}) - - self.req.lastURL = str(url) - sj = self.load(str(url), post={'s': sinp['value'], 'c': result, 'action': "Download"}) - - soup = BeautifulSoup(sj) - rawLinks = soup.findAll(attrs={"action": re.compile("^http://download.serienjunkies.org/")}) - - if not len(rawLinks) > 0: - sleep(1) - self.retry() - return - - self.correctCaptcha() - - links = [] - for link in rawLinks: - frameUrl = link['action'].replace("/go-", "/frame/go-") - links.append(self.handleFrame(frameUrl)) - if re.search("#hasName", url) or ((self.getConfig("changeNameSJ") == "Packagename") and - (self.getConfig("changeNameDJ") == "Packagename")): - self.core.files.addLinks(links, self.pyfile.package().id) - else: - if h1.text[2] == "_": - eName = h1.text[3:] - else: - eName = h1.text - self.packages.append((eName, links, eName)) - - def handleOldStyleLink(self, url): - sj = self.req.load(str(url)) - soup = BeautifulSoup(sj) - form = soup.find("form", attrs={"action": re.compile("^http://serienjunkies.org")}) - captchaTag = form.find(attrs={"src": re.compile("^/safe/secure/")}) - captchaUrl = "http://serienjunkies.org" + captchaTag['src'] - result = self.decryptCaptcha(str(captchaUrl)) - url = form['action'] - sinp = form.find(attrs={"name": "s"}) - - self.req.load(str(url), post={'s': sinp['value'], 'c': result, 'dl.start': "Download"}, cookies=False, - just_header=True) - decrypted = self.req.lastEffectiveURL - if decrypted == str(url): - self.retry() - self.core.files.addLinks([decrypted], self.pyfile.package().id) - - def handleFrame(self, url): - self.req.load(str(url)) - return self.req.lastEffectiveURL - - def handleShowDJ(self, url): - src = self.getSJSrc(url) - soup = BeautifulSoup(src) - post = soup.find("div", attrs={"id": "page_post"}) - ps = post.findAll("p") - found = unescape(soup.find("h2").find("a").string.split(' –')[0]) - if found: - seasonName = found - - groups = {} - gid = -1 - for p in ps: - if re.search("<strong>Sprache|<strong>Format", str(p)): - var = p.findAll("strong") - opts = {"Sprache": "", "Format": ""} - for v in var: - n = unescape(v.string).strip() - n = re.sub(r"^([:]?)(.*?)([:]?)$", r'\2', n) - if n.strip() not in opts: - continue - val = v.nextSibling - if not val: - continue - val = val.replace("|", "").strip() - val = re.sub(r"^([:]?)(.*?)([:]?)$", r'\2', val) - opts[n.strip()] = val.strip() - gid += 1 - groups[gid] = {} - groups[gid]['ep'] = {} - groups[gid]['opts'] = opts - elif re.search("<strong>Download:", str(p)): - parts = str(p).split("<br />") - if re.search("<strong>", parts[0]): - ename = re.search('<strong>(.*?)</strong>', parts[0]).group(1).strip().decode("utf-8").replace( - "–", "-") - groups[gid]['ep'][ename] = {} - parts.remove(parts[0]) - for part in parts: - hostername = re.search(r" \| ([-a-zA-Z0-9]+\.\w+)", part) - if hostername: - hostername = hostername.group(1) - groups[gid]['ep'][ename][hostername] = [] - links = re.findall('href="(.*?)"', part) - for link in links: - groups[gid]['ep'][ename][hostername].append(link + "#hasName") - - links = [] - for g in groups.values(): - for ename in g['ep']: - links.extend(self.getpreferred(g['ep'][ename])) - if self.getConfig("changeNameDJ") == "Episode": - self.packages.append((ename, links, ename)) - links = [] - package = "%s (%s, %s)" % (seasonName, g['opts']['Format'], g['opts']['Sprache']) - if self.getConfig("changeNameDJ") == "Format": - self.packages.append((package, links, package)) - links = [] - if (self.getConfig("changeNameDJ") == "Packagename") or re.search("#hasName", url): - self.core.files.addLinks(links, self.pyfile.package().id) - elif (self.getConfig("changeNameDJ") == "Show") or not re.search("#hasName", url): - self.packages.append((seasonName, links, seasonName)) - - def handleCategoryDJ(self, url): - package_links = [] - src = self.getSJSrc(url) - soup = BeautifulSoup(src) - content = soup.find("div", attrs={"id": "content"}) - for a in content.findAll("a", attrs={"rel": "bookmark"}): - package_links.append(a['href']) - self.core.files.addLinks(package_links, self.pyfile.package().id) - - def decrypt(self, pyfile): - showPattern = re.compile("^http://serienjunkies.org/serie/(.*)/$") - seasonPattern = re.compile("^http://serienjunkies.org/.*?/(.*)/$") - episodePattern = re.compile("^http://download.serienjunkies.org/f-.*?.html(#hasName)?$") - oldStyleLink = re.compile("^http://serienjunkies.org/safe/(.*)$") - categoryPatternDJ = re.compile("^http://dokujunkies.org/.*?(.*)$") - showPatternDJ = re.compile(r"^http://dokujunkies.org/.*?/(.*)\.html(#hasName)?$") - framePattern = re.compile("^http://download.(serienjunkies.org|dokujunkies.org)/frame/go-.*?/$") - url = pyfile.url - if framePattern.match(url): - self.packages.append((pyfile.package().name, [self.handleFrame(url)], pyfile.package().name)) - elif episodePattern.match(url): - self.handleEpisode(url) - elif oldStyleLink.match(url): - self.handleOldStyleLink(url) - elif showPattern.match(url): - self.handleShow(url) - elif showPatternDJ.match(url): - self.handleShowDJ(url) - elif seasonPattern.match(url): - self.handleSeason(url) - elif categoryPatternDJ.match(url): - self.handleCategoryDJ(url) - - #selects the preferred hoster, after that selects any hoster (ignoring the one to ignore) - def getpreferred(self, hosterlist): - - result = [] - preferredList = self.getConfig("hosterList").strip().lower().replace( - '|', ',').replace('.', '').replace(';', ',').split(',') - if (self.getConfig("randomPreferred") is True) and ( - self.getConfig("hosterListMode") in ["OnlyOne", "OnlyPreferred(One)"]): - random.shuffle(preferredList) - # we don't want hosters be read two times - hosterlist2 = hosterlist.copy() - - for preferred in preferredList: - for Hoster in hosterlist: - if preferred == Hoster.lower().replace('.', ''): - for Part in hosterlist[Hoster]: - self.logDebug("selected " + Part) - result.append(str(Part)) - del (hosterlist2[Hoster]) - if self.getConfig("hosterListMode") in ["OnlyOne", "OnlyPreferred(One)"]: - return result - - ignorelist = self.getConfig("ignoreList").strip().lower().replace( - '|', ',').replace('.', '').replace(';', ',').split(',') - if self.getConfig('hosterListMode') in ["OnlyOne", "All"]: - for Hoster in hosterlist2: - if Hoster.strip().lower().replace('.', '') not in ignorelist: - for Part in hosterlist2[Hoster]: - self.logDebug("selected2 " + Part) - result.append(str(Part)) - - if self.getConfig('hosterListMode') == "OnlyOne": - return result - return result diff --git a/module/plugins/crypter/SexuriaCom.py b/module/plugins/crypter/SexuriaCom.py new file mode 100644 index 000000000..3c952fd6b --- /dev/null +++ b/module/plugins/crypter/SexuriaCom.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.Crypter import Crypter + + +class SexuriaCom(Crypter): + __name__ = "SexuriaCom" + __type__ = "crypter" + __version__ = "0.01" + + __pattern__ = r'http://(?:www\.)?sexuria\.com/(v1/)?(Pornos_Kostenlos_.+?_(\d+)\.html|dl_links_\d+_\d+\.html|id=\d+\&part=\d+\&link=\d+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """Sexuria.com decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("NETHead", "NETHead.AT.gmx.DOT.net")] + + + PATTERN_SUPPORTED_MAIN = re.compile(r'http://(www\.)?sexuria\.com/(v1/)?Pornos_Kostenlos_.+?_(\d+)\.html', flags=re.I) + PATTERN_SUPPORTED_CRYPT = re.compile(r'http://(www\.)?sexuria\.com/(v1/)?dl_links_\d+_(?P<ID>\d+)\.html', flags=re.I) + PATTERN_SUPPORTED_REDIRECT = re.compile(r'http://(www\.)?sexuria\.com/out\.php\?id=(?P<ID>\d+)\&part=\d+\&link=\d+', flags=re.I) + PATTERN_TITLE = re.compile(r'<title> - (?P<TITLE>.*) Sexuria - Kostenlose Pornos - Rapidshare XXX Porn</title>', flags=re.I) + PATTERN_PASSWORD = re.compile(r'<strong>Passwort: </strong></div></td>.*?bgcolor="#EFEFEF">(?P<PWD>.*?)</td>', flags=re.I | re.S) + PATTERN_DL_LINK_PAGE = re.compile(r'"(dl_links_\d+_\d+\.html)"', flags=re.I) + PATTERN_REDIRECT_LINKS = re.compile(r'value="(http://sexuria\.com/out\.php\?id=\d+\&part=\d+\&link=\d+)" readonly', flags=re.I) + + + def decrypt(self, pyfile): + # Init + self.pyfile = pyfile + self.package = pyfile.package() + + # Get package links + package_name, self.links, folder_name, package_pwd = self.decryptLinks(self.pyfile.url) + self.packages = [(package_name, self.links, folder_name)] + + + def decryptLinks(self, url): + linklist = [] + name = self.package.name + folder = self.package.folder + password = None + + if re.match(self.PATTERN_SUPPORTED_MAIN, url): + # Processing main page + html = self.load(url) + links = re.findall(self.PATTERN_DL_LINK_PAGE, html) + for link in links: + linklist.append("http://sexuria.com/v1/" + link) + + elif re.match(self.PATTERN_SUPPORTED_REDIRECT, url): + # Processing direct redirect link (out.php), redirecting to main page + id = re.search(self.PATTERN_SUPPORTED_REDIRECT, url).group('ID') + if id: + linklist.append("http://sexuria.com/v1/Pornos_Kostenlos_liebe_%s.html" % id) + + elif re.match(self.PATTERN_SUPPORTED_CRYPT, url): + # Extract info from main file + id = re.search(self.PATTERN_SUPPORTED_CRYPT, url).group('ID') + html = self.load("http://sexuria.com/v1/Pornos_Kostenlos_info_%s.html" % id, decode=True) + + title = re.search(self.PATTERN_TITLE, html).group('TITLE').strip() + if title: + name = folder = title + self.logDebug("Package info found, name [%s] and folder [%s]" % (name, folder)) + + pwd = re.search(self.PATTERN_PASSWORD, html).group('PWD') + if pwd: + password = pwd.strip() + self.logDebug("Password info [%s] found" % password) + + # Process link (dl_link) + html = self.load(url) + links = re.findall(self.PATTERN_REDIRECT_LINKS, html) + if len(links) == 0: + self.LogError("Broken for link %s" % link) + else: + for link in links: + link = link.replace("http://sexuria.com/", "http://www.sexuria.com/") + finallink = self.load(link, just_header=True)['location'] + if not finallink or "sexuria.com/" in finallink: + self.LogError("Broken for link %s" % link) + else: + linklist.append(finallink) + + # Debug log + self.logDebug("%d supported links" % len(linklist)) + for i, link in enumerate(linklist): + self.logDebug("Supported link %d, %s" % (i + 1, link)) + + return name, linklist, folder, password diff --git a/module/plugins/crypter/ShareLinksBiz.py b/module/plugins/crypter/ShareLinksBiz.py index b56f90e15..d2e8138f6 100644 --- a/module/plugins/crypter/ShareLinksBiz.py +++ b/module/plugins/crypter/ShareLinksBiz.py @@ -9,24 +9,26 @@ from module.plugins.Crypter import Crypter class ShareLinksBiz(Crypter): - __name__ = "ShareLinksBiz" - __version__ = "1.13" - __type__ = "crypter" + __name__ = "ShareLinksBiz" + __type__ = "crypter" + __version__ = "1.14" __pattern__ = r'http://(?:www\.)?(share-links|s2l)\.biz/(?P<ID>_?\w+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Share-Links.biz decrypter plugin""" - __author_name__ = "fragonib" - __author_mail__ = "fragonib[AT]yahoo[DOT]es" + __license__ = "GPLv3" + __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es")] def setup(self): self.baseUrl = None self.fileId = None self.package = None - self.html = None self.captcha = False + def decrypt(self, pyfile): # Init self.initFile(pyfile) @@ -61,6 +63,7 @@ class ShareLinksBiz(Crypter): # Pack self.packages = [(package_name, package_links, package_folder)] + def initFile(self, pyfile): url = pyfile.url if 's2l.biz' in url: @@ -69,29 +72,34 @@ class ShareLinksBiz(Crypter): self.fileId = re.match(self.__pattern__, url).group('ID') self.package = pyfile.package() + def isOnline(self): if "No usable content was found" in self.html: self.logDebug("File not found") return False return True + def isPasswordProtected(self): if re.search(r'''<form.*?id="passwordForm".*?>''', self.html): self.logDebug("Links are protected") return True return False + def isCaptchaProtected(self): if '<map id="captchamap"' in self.html: self.logDebug("Links are captcha protected") return True return False + def unblockServer(self): imgs = re.findall(r"(/template/images/.*?\.gif)", self.html) for img in imgs: self.load(self.baseUrl + img) + def unlockPasswordProtection(self): password = self.getPassword() self.logDebug("Submitting password [%s] for protected links" % password) @@ -99,6 +107,7 @@ class ShareLinksBiz(Crypter): url = self.baseUrl + '/' + self.fileId self.html = self.load(url, post=post, decode=True) + def unlockCaptchaProtection(self): # Get captcha map captchaMap = self._getCaptchaMap() @@ -114,14 +123,12 @@ class ShareLinksBiz(Crypter): # Resolve captcha href = self._resolveCoords(coords, captchaMap) if href is None: - self.logDebug("Invalid captcha resolving, retrying") self.invalidCaptcha() - self.setWait(5, False) - self.wait() - self.retry() + self.retry(wait_time=5) url = self.baseUrl + href self.html = self.load(url, decode=True) + def _getCaptchaMap(self): mapp = {} for m in re.finditer(r'<area shape="rect" coords="(.*?)" href="(.*?)"', self.html): @@ -130,34 +137,34 @@ class ShareLinksBiz(Crypter): mapp[rect] = href return mapp + def _resolveCoords(self, coords, captchaMap): x, y = coords - for rect, href in captchaMap.items(): + for rect, href in captchaMap.iteritems(): x1, y1, x2, y2 = rect if (x >= x1 and x <= x2) and (y >= y1 and y <= y2): return href + def handleErrors(self): if "The inserted password was wrong" in self.html: self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry") - self.fail("Incorrect password, please set right password on 'Edit package' form and retry") + self.fail(_("Incorrect password, please set right password on 'Edit package' form and retry")) if self.captcha: if "Your choice was wrong" in self.html: - self.logDebug("Invalid captcha, retrying") self.invalidCaptcha() - self.setWait(5) - self.wait() - self.retry() + self.retry(wait_time=5) else: self.correctCaptcha() + def getPackageInfo(self): name = folder = None # Extract from web package header title_re = r'<h2><img.*?/>(.*)</h2>' - m = re.search(title_re, self.html, re.DOTALL) + m = re.search(title_re, self.html, re.S) if m is not None: title = m.group(1).strip() if 'unnamed' not in title: @@ -173,38 +180,45 @@ class ShareLinksBiz(Crypter): # Return package info return name, folder + def handleWebLinks(self): package_links = [] self.logDebug("Handling Web links") #@TODO: Gather paginated web links - pattern = r"javascript:_get\('(.*?)', \d+, ''\)" + pattern = r'javascript:_get\(\'(.*?)\', \d+, \'\'\)' ids = re.findall(pattern, self.html) self.logDebug("Decrypting %d Web links" % len(ids)) for i, ID in enumerate(ids): try: self.logDebug("Decrypting Web link %d, [%s]" % (i + 1, ID)) + dwLink = self.baseUrl + "/get/lnk/" + ID - response = self.load(dwLink) - code = re.search(r'frm/(\d+)', response).group(1) + res = self.load(dwLink) + + code = re.search(r'frm/(\d+)', res).group(1) fwLink = self.baseUrl + "/get/frm/" + code - response = self.load(fwLink) - jscode = re.search(r'<script language="javascript">\s*eval\((.*)\)\s*</script>', response, - re.DOTALL).group(1) + res = self.load(fwLink) + + jscode = re.search(r'<script language="javascript">\s*eval\((.*)\)\s*</script>', res, re.S).group(1) jscode = self.js.eval("f = %s" % jscode) jslauncher = "window=''; parent={frames:{Main:{location:{href:''}}},location:''}; %s; parent.frames.Main.location.href" + dlLink = self.js.eval(jslauncher % jscode) + self.logDebug("JsEngine returns value [%s] for redirection link" % dlLink) + package_links.append(dlLink) except Exception, detail: self.logDebug("Error decrypting Web link [%s], %s" % (ID, detail)) return package_links + def handleContainers(self): package_links = [] self.logDebug("Handling Container links") - pattern = r"javascript:_get\('(.*?)', 0, '(rsdf|ccf|dlc)'\)" + pattern = r'javascript:_get\(\'(.*?)\', 0, \'(rsdf|ccf|dlc)\'\)' containersLinks = re.findall(pattern, self.html) self.logDebug("Decrypting %d Container links" % len(containersLinks)) for containerLink in containersLinks: @@ -212,6 +226,7 @@ class ShareLinksBiz(Crypter): package_links.append(link) return package_links + def handleCNL2(self): package_links = [] self.logDebug("Handling CNL2 links") @@ -221,15 +236,16 @@ class ShareLinksBiz(Crypter): (crypted, jk) = self._getCipherParams() package_links.extend(self._getLinks(crypted, jk)) except: - self.fail("Unable to decrypt CNL2 links") + self.fail(_("Unable to decrypt CNL2 links")) return package_links + def _getCipherParams(self): # Request CNL2 - code = re.search(r'ClicknLoad.swf\?code=(.*?)"', self.html).group(1) - url = "%s/get/cnl2/%s" % (self.baseUrl, code) - response = self.load(url) - params = response.split(";;") + code = re.search(r'ClicknLoad.swf\?code=(.*?)"', self.html).group(1) + url = "%s/get/cnl2/%s" % (self.baseUrl, code) + res = self.load(url) + params = res.split(";;") # Get jk strlist = list(base64.standard_b64decode(params[1])) @@ -244,6 +260,7 @@ class ShareLinksBiz(Crypter): # Log and return return crypted, jk + def _getLinks(self, crypted, jk): # Get key jreturn = self.js.eval("%s f()" % jk) diff --git a/module/plugins/crypter/ShareRapidComFolder.py b/module/plugins/crypter/ShareRapidComFolder.py deleted file mode 100644 index e44402a52..000000000 --- a/module/plugins/crypter/ShareRapidComFolder.py +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.SimpleCrypter import SimpleCrypter - - -class ShareRapidComFolder(SimpleCrypter): - __name__ = "ShareRapidComFolder" - __version__ = "0.01" - __type__ = "crypter" - - __pattern__ = r'http://(?:www\.)?((share(-?rapid\.(biz|com|cz|info|eu|net|org|pl|sk)|-(central|credit|free|net)\.cz|-ms\.net)|(s-?rapid|rapids)\.(cz|sk))|(e-stahuj|mediatack|premium-rapidshare|rapidshare-premium|qiuck)\.cz|kadzet\.com|stahuj-zdarma\.eu|strelci\.net|universal-share\.com)/(slozka/.+)' - - __description__ = """Share-Rapid.com folder decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" - - LINK_PATTERN = r'<td class="soubor"[^>]*><a href="([^"]+)">' diff --git a/module/plugins/crypter/SharingmatrixComFolder.py b/module/plugins/crypter/SharingmatrixComFolder.py new file mode 100644 index 000000000..e16bdf814 --- /dev/null +++ b/module/plugins/crypter/SharingmatrixComFolder.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo + + +class SharingmatrixComFolder(DeadCrypter): + __name__ = "SharingmatrixComFolder" + __type__ = "crypter" + __version__ = "0.01" + + __pattern__ = r'http://(?:www\.)?sharingmatrix\.com/folder/\w+' + + __description__ = """Sharingmatrix.com folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + + +getInfo = create_getInfo(SharingmatrixComFolder) diff --git a/module/plugins/crypter/SpeedLoadOrgFolder.py b/module/plugins/crypter/SpeedLoadOrgFolder.py index 305397d3c..ddde7dec2 100644 --- a/module/plugins/crypter/SpeedLoadOrgFolder.py +++ b/module/plugins/crypter/SpeedLoadOrgFolder.py @@ -1,29 +1,19 @@ # -*- 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.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class SpeedLoadOrgFolder(DeadCrypter): - __name__ = "SpeedLoadOrgFolder" - __version__ = "0.3" - __type__ = "crypter" + __name__ = "SpeedLoadOrgFolder" + __type__ = "crypter" + __version__ = "0.30" __pattern__ = r'http://(?:www\.)?speedload\.org/(\d+~f$|folder/\d+/)' + __config__ = [] __description__ = """Speedload decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] + + +getInfo = create_getInfo(SpeedLoadOrgFolder) diff --git a/module/plugins/crypter/StealthTo.py b/module/plugins/crypter/StealthTo.py index 9cae7ba20..5173421f1 100644 --- a/module/plugins/crypter/StealthTo.py +++ b/module/plugins/crypter/StealthTo.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class StealthTo(DeadCrypter): - __name__ = "StealthTo" - __version__ = "0.2" - __type__ = "crypter" + __name__ = "StealthTo" + __type__ = "crypter" + __version__ = "0.20" __pattern__ = r'http://(?:www\.)?stealth\.to/folder/.+' + __config__ = [] __description__ = """Stealth.to decrypter plugin""" - __author_name__ = "spoob" - __author_mail__ = "spoob@pyload.org" + __license__ = "GPLv3" + __authors__ = [("spoob", "spoob@pyload.org")] + + +getInfo = create_getInfo(StealthTo) diff --git a/module/plugins/crypter/TnyCz.py b/module/plugins/crypter/TnyCz.py index 3ff9aa5dd..d36128550 100644 --- a/module/plugins/crypter/TnyCz.py +++ b/module/plugins/crypter/TnyCz.py @@ -1,39 +1,30 @@ # -*- 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/>. -""" - -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo import re class TnyCz(SimpleCrypter): - __name__ = "TnyCz" - __version__ = "0.01" - __type__ = "crypter" + __name__ = "TnyCz" + __type__ = "crypter" + __version__ = "0.03" __pattern__ = r'http://(?:www\.)?tny\.cz/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Tny.cz decrypter plugin""" - __author_name__ = "Walter Purcaro" - __author_mail__ = "vuolter@gmail.com" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - TITLE_PATTERN = r'<title>(?P<title>.+) - .+</title>' + + NAME_PATTERN = r'<title>(?P<N>.+) - .+</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 + + +getInfo = create_getInfo(TnyCz) diff --git a/module/plugins/crypter/TrailerzoneInfo.py b/module/plugins/crypter/TrailerzoneInfo.py index 2c7bb2c9f..10780dd45 100644 --- a/module/plugins/crypter/TrailerzoneInfo.py +++ b/module/plugins/crypter/TrailerzoneInfo.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class TrailerzoneInfo(DeadCrypter): - __name__ = "TrailerzoneInfo" + __name__ = "TrailerzoneInfo" + __type__ = "crypter" __version__ = "0.03" - __type__ = "crypter" - __pattern__ = r'http://(?:www\.)?trailerzone.info/.*?' + __pattern__ = r'http://(?:www\.)?trailerzone\.info/.+' + __config__ = [] __description__ = """TrailerZone.info decrypter plugin""" - __author_name__ = "godofdream" - __author_mail__ = "soilfiction@gmail.com" + __license__ = "GPLv3" + __authors__ = [("godofdream", "soilfiction@gmail.com")] + + +getInfo = create_getInfo(TrailerzoneInfo) diff --git a/module/plugins/crypter/TurbobitNetFolder.py b/module/plugins/crypter/TurbobitNetFolder.py index 26923e8d4..c6734c997 100644 --- a/module/plugins/crypter/TurbobitNetFolder.py +++ b/module/plugins/crypter/TurbobitNetFolder.py @@ -1,37 +1,27 @@ # -*- 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.SimpleCrypter import SimpleCrypter +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo from module.common.json_layer import json_loads class TurbobitNetFolder(SimpleCrypter): - __name__ = "TurbobitNetFolder" - __version__ = "0.03" - __type__ = "crypter" + __name__ = "TurbobitNetFolder" + __type__ = "crypter" + __version__ = "0.05" __pattern__ = r'http://(?:www\.)?turbobit\.net/download/folder/(?P<ID>\w+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Turbobit.net folder decrypter plugin""" - __author_name__ = ("stickell", "Walter Purcaro") - __author_mail__ = ("l.stickell@yahoo.it", "vuolter@gmail.com") + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it"), + ("Walter Purcaro", "vuolter@gmail.com")] - TITLE_PATTERN = r"src='/js/lib/grid/icon/folder.png'> <span>(?P<title>.+?)</span>" + + NAME_PATTERN = r'src=\'/js/lib/grid/icon/folder.png\'> <span>(?P<N>.+?)</span>' def _getLinks(self, id, page=1): @@ -47,7 +37,11 @@ class TurbobitNetFolder(SimpleCrypter): else: return + def getLinks(self): - id = re.match(self.__pattern__, self.pyfile.url).group("ID") + id = re.match(self.__pattern__, self.pyfile.url).group('ID') fixurl = lambda id: "http://turbobit.net/%s.html" % id return map(fixurl, self._getLinks(id)) + + +getInfo = create_getInfo(TurbobitNetFolder) diff --git a/module/plugins/crypter/TusfilesNetFolder.py b/module/plugins/crypter/TusfilesNetFolder.py index 70b7bd4b9..0db3470cc 100644 --- a/module/plugins/crypter/TusfilesNetFolder.py +++ b/module/plugins/crypter/TusfilesNetFolder.py @@ -1,47 +1,38 @@ # -*- 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 math import re from urlparse import urljoin -from module.plugins.internal.SimpleCrypter import SimpleCrypter +from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo -class TusfilesNetFolder(SimpleCrypter): - __name__ = "TusfilesNetFolder" - __version__ = "0.02" - __type__ = "crypter" +class TusfilesNetFolder(XFSCrypter): + __name__ = "TusfilesNetFolder" + __type__ = "crypter" + __version__ = "0.07" - __pattern__ = r'https?://(?:www\.)?tusfiles\.net/go/(?P<ID>\w+)/?' + __pattern__ = r'https?://(?:www\.)?tusfiles\.net/go/(?P<ID>\w+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Tusfiles.net folder decrypter plugin""" - __author_name__ = ("Walter Purcaro", "stickell") - __author_mail__ = ("vuolter@gmail.com", "l.stickell@yahoo.it") + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com"), + ("stickell", "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+\)<' - URL_REPLACEMENTS = [(__pattern__, r'https://www.tusfiles.net/go/\g<ID>/')] + HOSTER_DOMAIN = "tusfiles.net" + + PAGES_PATTERN = r'>\((\d+) \w+\)<' + + 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: @@ -51,4 +42,7 @@ class TusfilesNetFolder(SimpleCrypter): for p in xrange(2, pages + 1): self.html = self.loadPage(p) - self.package_links += self.getLinks() + self.links += self.getLinks() + + +getInfo = create_getInfo(TusfilesNetFolder) diff --git a/module/plugins/crypter/UlozToFolder.py b/module/plugins/crypter/UlozToFolder.py index dfa1bb8c4..a1f3ed5ea 100644 --- a/module/plugins/crypter/UlozToFolder.py +++ b/module/plugins/crypter/UlozToFolder.py @@ -5,15 +5,18 @@ from module.plugins.Crypter import Crypter class UlozToFolder(Crypter): - __name__ = "UlozToFolder" - __version__ = "0.2" - __type__ = "crypter" + __name__ = "UlozToFolder" + __type__ = "crypter" + __version__ = "0.20" - __pattern__ = r'http://(?:www\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj.cz|zachowajto.pl)/(m|soubory)/.*' + __pattern__ = r'http://(?:www\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj\.cz|zachowajto\.pl)/(m|soubory)/.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Uloz.to folder decrypter plugin""" - __author_name__ = "zoidberg" - __author_mail__ = "zoidberg@mujmail.cz" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + FOLDER_PATTERN = r'<ul class="profile_files">(.*?)</ul>' LINK_PATTERN = r'<br /><a href="/([^"]+)">[^<]+</a>' @@ -25,10 +28,10 @@ class UlozToFolder(Crypter): new_links = [] for i in xrange(1, 100): - self.logInfo("Fetching links from page %i" % i) - m = re.search(self.FOLDER_PATTERN, html, re.DOTALL) + self.logInfo(_("Fetching links from page %i") % i) + m = re.search(self.FOLDER_PATTERN, html, re.S) if m is None: - self.fail("Parse error (FOLDER)") + self.error(_("FOLDER_PATTERN not found")) new_links.extend(re.findall(self.LINK_PATTERN, m.group(1))) m = re.search(self.NEXT_PAGE_PATTERN, html) @@ -37,9 +40,7 @@ class UlozToFolder(Crypter): else: break else: - self.logInfo("Limit of 99 pages reached, aborting") + self.logInfo(_("Limit of 99 pages reached, aborting")) if new_links: self.urls = [map(lambda s: "http://ulozto.net/%s" % s, new_links)] - else: - self.fail('Could not extract any links') diff --git a/module/plugins/crypter/UploadableChFolder.py b/module/plugins/crypter/UploadableChFolder.py new file mode 100644 index 000000000..22f9ca2ed --- /dev/null +++ b/module/plugins/crypter/UploadableChFolder.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class UploadableChFolder(SimpleCrypter): + __name__ = "UploadableChFolder" + __type__ = "crypter" + __version__ = "0.03" + + __pattern__ = r'http://(?:www\.)?uploadable\.ch/list/\w+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """ Uploadable.ch folder decrypter plugin """ + __license__ = "GPLv3" + __authors__ = [("guidobelix", "guidobelix@hotmail.it"), + ("Walter Purcaro", "vuolter@gmail.com")] + + + LINK_PATTERN = r'"(.+?)" class="icon_zipfile">' + NAME_PATTERN = r'<div class="folder"><span> </span>(?P<N>.+?)</div>' + OFFLINE_PATTERN = r'We are sorry... The URL you entered cannot be found on the server.' + TEMP_OFFLINE_PATTERN = r'<div class="icon_err">' + + +getInfo = create_getInfo(UploadableChFolder) diff --git a/module/plugins/crypter/UploadedToFolder.py b/module/plugins/crypter/UploadedToFolder.py index 36dd9714a..0a71add70 100644 --- a/module/plugins/crypter/UploadedToFolder.py +++ b/module/plugins/crypter/UploadedToFolder.py @@ -1,52 +1,37 @@ # -*- 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.SimpleCrypter import SimpleCrypter +from urlparse import urljoin + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class UploadedToFolder(SimpleCrypter): - __name__ = "UploadedToFolder" - __version__ = "0.3" - __type__ = "crypter" + __name__ = "UploadedToFolder" + __type__ = "crypter" + __version__ = "0.42" - __pattern__ = r'http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/(?P<id>\w+)' + __pattern__ = r'http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/(?P<ID>\w+)' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """UploadedTo decrypter plugin""" - __author_name__ = "stickell" - __author_mail__ = "l.stickell@yahoo.it" - - PLAIN_PATTERN = r'<small class="date"><a href="(?P<plain>[\w/]+)" onclick=' - TITLE_PATTERN = r'<title>(?P<title>[^<]+)</title>' + __license__ = "GPLv3" + __authors__ = [("stickell", "l.stickell@yahoo.it")] - def decrypt(self, pyfile): - self.html = self.load(pyfile.url) + PLAIN_PATTERN = r'<small class="date"><a href="([\w/]+)" onclick=' + NAME_PATTERN = r'<title>(?P<N>.+?)<' - package_name, folder_name = self.getPackageNameAndFolder() + def getLinks(self): m = re.search(self.PLAIN_PATTERN, self.html) - if m: - plain_link = 'http://uploaded.net/' + m.group('plain') - else: - self.fail('Parse error - Unable to find plain url list') + if m is None: + self.error(_("PLAIN_PATTERN not found")) + + plain_link = urljoin("http://uploaded.net/", m.group(1)) + return self.load(plain_link).split('\n')[:-1] - self.html = self.load(plain_link) - package_links = self.html.split('\n')[:-1] - self.logDebug('Package has %d links' % len(package_links)) - self.packages = [(package_name, package_links, folder_name)] +getInfo = create_getInfo(UploadedToFolder) diff --git a/module/plugins/crypter/WiiReloadedOrg.py b/module/plugins/crypter/WiiReloadedOrg.py index 9cb0751d8..c3c5b8222 100644 --- a/module/plugins/crypter/WiiReloadedOrg.py +++ b/module/plugins/crypter/WiiReloadedOrg.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.DeadCrypter import DeadCrypter +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class WiiReloadedOrg(DeadCrypter): - __name__ = "WiiReloadedOrg" + __name__ = "WiiReloadedOrg" + __type__ = "crypter" __version__ = "0.11" - __type__ = "crypter" __pattern__ = r'http://(?:www\.)?wii-reloaded\.org/protect/get\.php\?i=.+' + __config__ = [] __description__ = """Wii-Reloaded.org decrypter plugin""" - __author_name__ = "hzpz" - __author_mail__ = None + __license__ = "GPLv3" + __authors__ = [("hzpz", None)] + + +getInfo = create_getInfo(WiiReloadedOrg) diff --git a/module/plugins/crypter/WuploadComFolder.py b/module/plugins/crypter/WuploadComFolder.py new file mode 100644 index 000000000..873c71fad --- /dev/null +++ b/module/plugins/crypter/WuploadComFolder.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo + + +class WuploadComFolder(DeadCrypter): + __name__ = "WuploadComFolder" + __type__ = "crypter" + __version__ = "0.01" + + __pattern__ = r'http://(?:www\.)?wupload\.com/folder/\w+' + + __description__ = """Wupload.com folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + + +getInfo = create_getInfo(WuploadComFolder) diff --git a/module/plugins/crypter/XFileSharingProFolder.py b/module/plugins/crypter/XFileSharingProFolder.py new file mode 100644 index 000000000..10e4d8c83 --- /dev/null +++ b/module/plugins/crypter/XFileSharingProFolder.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo + + +class XFileSharingProFolder(XFSCrypter): + __name__ = "XFileSharingProFolder" + __type__ = "crypter" + __version__ = "0.03" + + __pattern__ = r'^unmatchable$' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """XFileSharingPro dummy folder decrypter plugin for hook""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + def _log(self, type, args): + msg = " | ".join([str(a).strip() for a in args if a]) + logger = getattr(self.log, type) + logger("%s: %s: %s" % (self.__name__, self.HOSTER_NAME, msg or _("%s MARK" % type.upper()))) + + + def init(self): + super(XFileSharingProFolder, self).init() + + self.__pattern__ = self.core.pluginManager.crypterPlugins[self.__name__]['pattern'] + + self.HOSTER_DOMAIN = re.match(self.__pattern__, self.pyfile.url).group(1).lower() + self.HOSTER_NAME = "".join([str.capitalize() for str in self.HOSTER_DOMAIN.split('.')]) + + account = self.core.accountManager.getAccountPlugin(self.HOSTER_NAME) + + if account and account.canUse(): + self.account = account + elif self.account: + self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN + else: + return + + self.user, data = self.account.selectAccount() + self.req = self.account.getAccountRequest(self.user) + self.premium = self.account.isPremium(self.user) + + +getInfo = create_getInfo(XFileSharingProFolder) diff --git a/module/plugins/crypter/XupPl.py b/module/plugins/crypter/XupPl.py index e89f4ccb0..f2ecbee5a 100644 --- a/module/plugins/crypter/XupPl.py +++ b/module/plugins/crypter/XupPl.py @@ -4,15 +4,17 @@ from module.plugins.Crypter import Crypter class XupPl(Crypter): - __name__ = "XupPl" - __version__ = "0.1" - __type__ = "crypter" + __name__ = "XupPl" + __type__ = "crypter" + __version__ = "0.10" - __pattern__ = r'https?://(?:[^/]*\.)?xup\.pl/.*' + __pattern__ = r'https?://(?:[^/]*\.)?xup\.pl/.+' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] __description__ = """Xup.pl decrypter plugin""" - __author_name__ = "z00nx" - __author_mail__ = "z00nx0@gmail.com" + __license__ = "GPLv3" + __authors__ = [("z00nx", "z00nx0@gmail.com")] def decrypt(self, pyfile): @@ -20,4 +22,4 @@ class XupPl(Crypter): if 'location' in header: self.urls = [header['location']] else: - self.fail('Unable to find link') + self.fail(_("Unable to find link")) diff --git a/module/plugins/crypter/YoutubeBatch.py b/module/plugins/crypter/YoutubeBatch.py index 216fbb670..73ebf5fb3 100644 --- a/module/plugins/crypter/YoutubeBatch.py +++ b/module/plugins/crypter/YoutubeBatch.py @@ -1,20 +1,5 @@ # -*- 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/>. -""" - import re from urlparse import urljoin @@ -23,30 +8,34 @@ from module.common.json_layer import json_loads from module.plugins.Crypter import Crypter from module.utils import save_join -API_URL = "AIzaSyCKnWLNlkX-L4oD1aEzqqhRw1zczeD6_k0" - class YoutubeBatch(Crypter): - __name__ = "YoutubeBatch" - __version__ = "1.00" - __type__ = "crypter" + __name__ = "YoutubeBatch" + __type__ = "crypter" + __version__ = "1.01" __pattern__ = r'https?://(?:www\.|m\.)?youtube\.com/(?P<TYPE>user|playlist|view_play_list)(/|.*?[?&](?:list|p)=)(?P<ID>[\w-]+)' - __config__ = [("likes", "bool", "Grab user (channel) liked videos", False), + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), + ("subfolder_per_package", "bool", "Create a subfolder for each package", True), + ("likes", "bool", "Grab user (channel) liked videos", False), ("favorites", "bool", "Grab user (channel) favorite videos", False), ("uploads", "bool", "Grab channel unplaylisted videos", True)] __description__ = """Youtube.com channel & playlist decrypter plugin""" - __author_name__ = "Walter Purcaro" - __author_mail__ = "vuolter@gmail.com" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + API_KEY = "AIzaSyCKnWLNlkX-L4oD1aEzqqhRw1zczeD6_k0" def api_response(self, ref, req): - req.update({"key": API_KEY}) + req.update({"key": self.API_KEY}) url = urljoin("https://www.googleapis.com/youtube/v3/", ref) page = self.load(url, get=req) return json_loads(page) + def getChannel(self, user): channels = self.api_response("channels", {"part": "id,snippet,contentDetails", "forUsername": user, "maxResults": "50"}) if channels['items']: @@ -56,6 +45,7 @@ class YoutubeBatch(Crypter): "relatedPlaylists": channel['contentDetails']['relatedPlaylists'], "user": user} # One lone channel for user? + def getPlaylist(self, p_id): playlists = self.api_response("playlists", {"part": "snippet", "id": p_id}) if playlists['items']: @@ -65,6 +55,7 @@ class YoutubeBatch(Crypter): "channelId": playlist['snippet']['channelId'], "channelTitle": playlist['snippet']['channelTitle']} + def _getPlaylists(self, id, token=None): req = {"part": "id", "maxResults": "50", "channelId": id} if token: @@ -79,9 +70,11 @@ class YoutubeBatch(Crypter): for item in self._getPlaylists(id, playlists['nextPageToken']): yield item + def getPlaylists(self, ch_id): return map(self.getPlaylist, self._getPlaylists(ch_id)) + def _getVideosId(self, id, token=None): req = {"part": "contentDetails", "maxResults": "50", "playlistId": id} if token: @@ -96,13 +89,15 @@ class YoutubeBatch(Crypter): for item in self._getVideosId(id, playlist['nextPageToken']): yield item + def getVideosId(self, p_id): return list(self._getVideosId(p_id)) + def decrypt(self, pyfile): m = re.match(self.__pattern__, pyfile.url) - m_id = m.group("ID") - m_type = m.group("TYPE") + m_id = m.group('ID') + m_type = m.group('TYPE') if m_type == "user": self.logDebug("Url recognized as Channel") @@ -130,7 +125,7 @@ class YoutubeBatch(Crypter): playlists = [self.getPlaylist(m_id)] if not playlists: - self.fail("No playlist available") + self.fail(_("No playlist available")) addedvideos = [] urlize = lambda x: "https://www.youtube.com/watch?v=" + x |