diff options
Diffstat (limited to 'module/plugins')
74 files changed, 1101 insertions, 880 deletions
diff --git a/module/plugins/accounts/AlldebridCom.py b/module/plugins/accounts/AlldebridCom.py index f9c1f2ca6..d09086907 100644 --- a/module/plugins/accounts/AlldebridCom.py +++ b/module/plugins/accounts/AlldebridCom.py @@ -2,7 +2,7 @@ import re import time -import xml.dom.minidom as dom +import xml.dom.minidom from BeautifulSoup import BeautifulSoup @@ -43,7 +43,7 @@ class AlldebridCom(Account): self.logDebug(html) - xml = dom.parseString(html) + xml = xml.dom.minidom.parseString(html) exp_time = time.time() + int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue) * 24 * 60 * 60 account_info = {"validuntil": exp_time, "trafficleft": -1} diff --git a/module/plugins/accounts/CatShareNet.py b/module/plugins/accounts/CatShareNet.py index bb42f443f..3ddadca8e 100644 --- a/module/plugins/accounts/CatShareNet.py +++ b/module/plugins/accounts/CatShareNet.py @@ -11,7 +11,7 @@ class CatShareNet(Account): __type__ = "account" __version__ = "0.05" - __description__ = """CatShareNet account plugin""" + __description__ = """Catshare.net account plugin""" __license__ = "GPLv3" __authors__ = [("prOq", None)] diff --git a/module/plugins/accounts/FilerNet.py b/module/plugins/accounts/FilerNet.py index ac5fd11da..149ff7d89 100644 --- a/module/plugins/accounts/FilerNet.py +++ b/module/plugins/accounts/FilerNet.py @@ -9,14 +9,14 @@ from module.plugins.Account import Account class FilerNet(Account): __name__ = "FilerNet" __type__ = "account" - __version__ = "0.04" + __version__ = "0.05" __description__ = """Filer.net account plugin""" __license__ = "GPLv3" __authors__ = [("stickell", "l.stickell@yahoo.it")] - TOKEN_PATTERN = r'_csrf_token" value="(.+?)" />' + TOKEN_PATTERN = r'name="_csrf_token" value="(.+?)"' WALID_UNTIL_PATTERN = r'Der Premium-Zugang ist gültig bis (.+)\.\s*</td>' TRAFFIC_PATTERN = r'Traffic</th>\s*<td>([^<]+)</td>' FREE_PATTERN = r'Account Status</th>\s*<td>\s*Free' @@ -43,15 +43,15 @@ class FilerNet(Account): def login(self, user, data, req): - html = req.load("https://filer.net/login") + html = req.load("https://filer.net/login", decode=True) token = re.search(self.TOKEN_PATTERN, html).group(1) html = req.load("https://filer.net/login_check", - post={"_username": user, - "_password": data['password'], + post={"_username" : user, + "_password" : data['password'], "_remember_me": "on", - "_csrf_token": token, + "_csrf_token" : token, "_target_path": "https://filer.net/"}, decode=True) diff --git a/module/plugins/accounts/NitroflareCom.py b/module/plugins/accounts/NitroflareCom.py new file mode 100644 index 000000000..57f2b9ae8 --- /dev/null +++ b/module/plugins/accounts/NitroflareCom.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- + +import re +import time + +from module.plugins.Account import Account + + +class NitroflareCom(Account): + __name__ = "NitroflareCom" + __type__ = "account" + __version__ = "0.04" + + __description__ = """Nitroflare.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com" )] + + + VALID_UNTIL_PATTERN = r'>Time Left</label><strong>(.+?)</' + TRAFFIC_LEFT_PATTERN = r'>Daily Limit</label><strong>([\d.,]+)' + LOGIN_FAIL_PATTERN = r'<ul class="errors">\s*<li>' + + TOKEN_PATTERN = r'name="token" value="(.+?)"' + + + def loadAccountInfo(self, user, req): + validuntil = -1 + trafficleft = None + premium = False + + html = req.load("https://nitroflare.com/member", + get={'s': "premium"}, + decode=True) + + m = re.search(self.VALID_UNTIL_PATTERN, html) + if m: + expiredate = m.group(1).strip() + self.logDebug("Time Left: " + expiredate) + + try: + validuntil = sum(int(v) * {'day': 24 * 3600, 'hour': 3600, 'minute': 60}[u.lower()] for v, u in + re.findall(r'(\d+)\s*(day|hour|minute)', expiredate, re.I)) + except Exception, e: + self.logError(e) + + else: + self.logDebug("Valid until: %s" % validuntil) + + if validuntil: + validuntil += time.time() + premium = True + else: + validuntil = -1 + + m = re.search(self.TRAFFIC_LEFT_PATTERN, html) + if m: + try: + trafficleft = self.parseTraffic(str(max(0, 50 - float(m.group(1)))) + " GB") + + except Exception, e: + self.logError(e) + else: + self.logDebug("TRAFFIC_LEFT_PATTERN not found") + + return {'validuntil' : validuntil, + 'trafficleft': trafficleft, + 'premium' : premium} + + + def login(self, user, data, req): + html = req.load("https://nitroflare.com/login", decode=True) + + token = re.search(self.TOKEN_PATTERN, html).group(1) + + html = req.load("https://nitroflare.com/login", + post={'login' : "", + 'email' : user, + 'password': data['password'], + 'token' : token}, + decode=True) + + if re.search(self.LOGIN_FAIL_PATTERN, html): + self.wrongPassword() diff --git a/module/plugins/accounts/NoPremiumPl.py b/module/plugins/accounts/NoPremiumPl.py index 7e3f757d3..6c034b31f 100644 --- a/module/plugins/accounts/NoPremiumPl.py +++ b/module/plugins/accounts/NoPremiumPl.py @@ -4,37 +4,37 @@ import datetime import hashlib import time +from module.common.json_layer import json_loads from module.plugins.Account import Account -from module.common.json_layer import json_loads as loads class NoPremiumPl(Account): - __name__ = "NoPremiumPl" + __name__ = "NoPremiumPl" + __type__ = "account" __version__ = "0.01" - __type__ = "account" + __description__ = "NoPremium.pl account plugin" - __license__ = "GPLv3" - __authors__ = [("goddie", "dev@nopremium.pl")] + __license__ = "GPLv3" + __authors__ = [("goddie", "dev@nopremium.pl")] - _api_url = "http://crypt.nopremium.pl" - _api_query = { - "site": "nopremium", - "username": "", - "password": "", - "output": "json", - "loc": "1", - "info": "1" - } + API_URL = "http://crypt.nopremium.pl" + API_QUERY = {'site' : "nopremium", + 'username': "" , + 'password': "" , + 'output' : "json" , + 'loc' : "1" , + 'info' : "1" } _req = None _usr = None _pwd = None + def loadAccountInfo(self, name, req): self._req = req try: - result = loads(self.runAuthQuery()) + result = json_loads(self.runAuthQuery()) except Exception: # todo: return or let it be thrown? return @@ -45,13 +45,13 @@ class NoPremiumPl(Account): if "expire" in result.keys() and result["expire"]: premium = True valid_untill = time.mktime(datetime.datetime.fromtimestamp(int(result["expire"])).timetuple()) + traffic_left = result["balance"] * 1024 - return ({ - "validuntil": valid_untill, - "trafficleft": traffic_left, - "premium": premium - }) + return {'validuntil' : valid_untill, + 'trafficleft': traffic_left, + 'premium' : premium } + def login(self, user, data, req): self._usr = user @@ -59,23 +59,23 @@ class NoPremiumPl(Account): self._req = req try: - response = loads(self.runAuthQuery()) + response = json_loads(self.runAuthQuery()) except Exception: self.wrongPassword() if "errno" in response.keys(): self.wrongPassword() + data['usr'] = self._usr data['pwd'] = self._pwd + def createAuthQuery(self): - query = self._api_query + query = self.API_QUERY query["username"] = self._usr query["password"] = self._pwd - return query - def runAuthQuery(self): - data = self._req.load(self._api_url, post=self.createAuthQuery()) - return data
\ No newline at end of file + def runAuthQuery(self): + return self._req.load(self.API_URL, post=self.createAuthQuery()) diff --git a/module/plugins/accounts/PremiumizeMe.py b/module/plugins/accounts/PremiumizeMe.py index 7d061ec2d..da31d93ee 100644 --- a/module/plugins/accounts/PremiumizeMe.py +++ b/module/plugins/accounts/PremiumizeMe.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account - from module.common.json_layer import json_loads +from module.plugins.Account import Account class PremiumizeMe(Account): __name__ = "PremiumizeMe" __type__ = "account" - __version__ = "0.13" + __version__ = "0.16" __description__ = """Premiumize.me account plugin""" __license__ = "GPLv3" @@ -42,7 +41,7 @@ class PremiumizeMe(Account): def getAccountStatus(self, user, req): # Use premiumize.me API v1 (see https://secure.premiumize.me/?show=api) # to retrieve account info and return the parsed json answer - answer = req.load("https://api.premiumize.me/pm-api/v1.php", + answer = req.load("http://api.premiumize.me/pm-api/v1.php", get={'method' : "accountstatus", 'params[login]': user, 'params[pass]' : self.getAccountData(user)['password']}) diff --git a/module/plugins/accounts/RapideoPl.py b/module/plugins/accounts/RapideoPl.py index 3e9d52fe8..92736cba0 100644 --- a/module/plugins/accounts/RapideoPl.py +++ b/module/plugins/accounts/RapideoPl.py @@ -4,77 +4,78 @@ import datetime import hashlib import time +from module.common.json_layer import json_loads from module.plugins.Account import Account -from module.common.json_layer import json_loads as loads class RapideoPl(Account): - __name__ = "RapideoPl" + __name__ = "RapideoPl" + __type__ = "account" __version__ = "0.01" - __type__ = "account" + __description__ = "Rapideo.pl account plugin" - __license__ = "GPLv3" - __authors__ = [("goddie", "dev@rapideo.pl")] + __license__ = "GPLv3" + __authors__ = [("goddie", "dev@rapideo.pl")] - _api_url = "http://enc.rapideo.pl" - _api_query = { - "site": "newrd", - "username": "", - "password": "", - "output": "json", - "loc": "1", - "info": "1" - } + API_URL = "http://enc.rapideo.pl" + API_QUERY = {'site' : "newrd", + 'username': "" , + 'password': "" , + 'output' : "json" , + 'loc' : "1" , + 'info' : "1" } _req = None _usr = None _pwd = None + def loadAccountInfo(self, name, req): self._req = req try: - result = loads(self.runAuthQuery()) + result = json_loads(self.runAuthQuery()) except Exception: # todo: return or let it be thrown? return premium = False valid_untill = -1 + if "expire" in result.keys() and result["expire"]: premium = True valid_untill = time.mktime(datetime.datetime.fromtimestamp(int(result["expire"])).timetuple()) traffic_left = result["balance"] - return ({ - "validuntil": valid_untill, - "trafficleft": traffic_left, - "premium": premium - }) + return {'validuntil' : valid_untill, + 'trafficleft': traffic_left, + 'premium' : premium } + def login(self, user, data, req): self._usr = user self._pwd = hashlib.md5(data["password"]).hexdigest() self._req = req + try: - response = loads(self.runAuthQuery()) + response = json_loads(self.runAuthQuery()) except Exception: self.wrongPassword() if "errno" in response.keys(): self.wrongPassword() + data['usr'] = self._usr data['pwd'] = self._pwd + def createAuthQuery(self): - query = self._api_query + query = self.API_QUERY query["username"] = self._usr query["password"] = self._pwd - return query - def runAuthQuery(self): - data = self._req.load(self._api_url, post=self.createAuthQuery()) - return data
\ No newline at end of file + def runAuthQuery(self): + return self._req.load(self.API_URL, post=self.createAuthQuery()) diff --git a/module/plugins/accounts/RapidgatorNet.py b/module/plugins/accounts/RapidgatorNet.py index 23d7aff53..5ff30e061 100644 --- a/module/plugins/accounts/RapidgatorNet.py +++ b/module/plugins/accounts/RapidgatorNet.py @@ -24,7 +24,7 @@ class RapidgatorNet(Account): sid = None try: - sid = self.getAccountData(user).get('sid') + sid = self.getAccountData(user).get('sid', None) assert sid html = req.load("%s/info" % self.API_URL, get={'sid': sid}) diff --git a/module/plugins/accounts/RealdebridCom.py b/module/plugins/accounts/RealdebridCom.py index 41d8a0975..ad2975aa9 100644 --- a/module/plugins/accounts/RealdebridCom.py +++ b/module/plugins/accounts/RealdebridCom.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -import xml.dom.minidom as dom +import xml.dom.minidom from module.plugins.Account import Account @@ -19,7 +19,7 @@ class RealdebridCom(Account): if self.pin_code: return {"premium": False} html = req.load("https://real-debrid.com/api/account.php") - xml = dom.parseString(html) + xml = xml.dom.minidom.parseString(html) account_info = {"validuntil": float(xml.getElementsByTagName("expiration")[0].childNodes[0].nodeValue), "trafficleft": -1} diff --git a/module/plugins/accounts/WebshareCz.py b/module/plugins/accounts/WebshareCz.py index f032e2317..8c53dd41e 100644 --- a/module/plugins/accounts/WebshareCz.py +++ b/module/plugins/accounts/WebshareCz.py @@ -12,7 +12,7 @@ from module.plugins.Account import Account class WebshareCz(Account): __name__ = "WebshareCz" __type__ = "account" - __version__ = "0.07" + __version__ = "0.08" __description__ = """Webshare.cz account plugin""" __license__ = "GPLv3" @@ -26,7 +26,7 @@ class WebshareCz(Account): def loadAccountInfo(self, user, req): html = req.load("https://webshare.cz/api/user_data/", - post={'wst': self.infos['wst']}, + post={'wst': self.getAccountData(user).get('wst', None)}, decode=True) self.logDebug("Response: " + html) @@ -65,4 +65,4 @@ class WebshareCz(Account): if "<status>OK</status>" not in login: self.wrongPassword() - self.infos['wst'] = re.search('<token>(.+)</token>', login).group(1) + data['wst'] = re.search('<token>(.+)</token>', login).group(1) diff --git a/module/plugins/accounts/WorldbytezCom.py b/module/plugins/accounts/WorldbytezCom.py new file mode 100644 index 000000000..a90dbea56 --- /dev/null +++ b/module/plugins/accounts/WorldbytezCom.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSAccount import XFSAccount + + +class WorldbytezCom(XFSAccount): + __name__ = "WorldbytezCom" + __type__ = "account" + __version__ = "0.01" + + __description__ = """Worldbytez.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + HOSTER_DOMAIN = "worldbytez.com" diff --git a/module/plugins/crypter/Dereferer.py b/module/plugins/crypter/Dereferer.py index 8427c1540..85b84a242 100644 --- a/module/plugins/crypter/Dereferer.py +++ b/module/plugins/crypter/Dereferer.py @@ -1,17 +1,42 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleDereferer import SimpleDereferer +import re +from module.plugins.internal.SimpleCrypter import SimpleCrypter -class Dereferer(SimpleDereferer): + +class Dereferer(SimpleCrypter): __name__ = "Dereferer" __type__ = "crypter" - __version__ = "0.11" + __version__ = "0.14" - __pattern__ = r'https?://([^/]+)/.*?(?P<LINK>(ht|f)tps?(://|%3A%2F%2F).+)' + __pattern__ = r'https?://(?:www\.)?(?:\w+\.)*?(?P<DOMAIN>(?:[\d.]+|[\w\-]{3,}(?:\.[a-zA-Z]{2,}){1,2})(?:\:\d+)?)/.*?(?P<LINK>(?:ht|f)tps?://.+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] __description__ = """Crypter for dereferers""" __license__ = "GPLv3" - __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + HOSTER_DOMAIN = None + HOSTER_NAME = None + + + 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(Dereferer, self).init() + + self.__pattern__ = self.core.pluginManager.crypterPlugins[self.__name__]['pattern'] #@TODO: Recheck in 0.4.10 + + self.HOSTER_DOMAIN = re.match(self.__pattern__, self.pyfile.url).group("DOMAIN").lower() + self.HOSTER_NAME = "".join(part.capitalize() for part in re.split(r'(\.|\d+)', self.HOSTER_DOMAIN) if part != '.') + + + def getLinks(self): + return [re.match(self.__pattern__, self.pyfile.url).group('LINK').strip()] diff --git a/module/plugins/crypter/DontKnowMe.py b/module/plugins/crypter/DontKnowMe.py deleted file mode 100644 index e56751972..000000000 --- a/module/plugins/crypter/DontKnowMe.py +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- - -from module.plugins.internal.SimpleDereferer import SimpleDereferer - - -class DontKnowMe(SimpleDereferer): - __name__ = "DontKnowMe" - __type__ = "crypter" - __version__ = "0.11" - - __pattern__ = r'http://(?:www\.)?dontknow\.me/at/\?(?P<LINK>.+)' - __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), - ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] - - __description__ = """DontKnow.me decrypter plugin""" - __license__ = "GPLv3" - __authors__ = [("selaux", "")] diff --git a/module/plugins/crypter/FilecryptCc.py b/module/plugins/crypter/FilecryptCc.py index a1a94b6f6..4d2b42f90 100644 --- a/module/plugins/crypter/FilecryptCc.py +++ b/module/plugins/crypter/FilecryptCc.py @@ -10,13 +10,13 @@ import urlparse from Crypto.Cipher import AES from module.plugins.Crypter import Crypter -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha class FilecryptCc(Crypter): __name__ = "FilecryptCc" __type__ = "crypter" - __version__ = "0.14" + __version__ = "0.15" __pattern__ = r'https?://(?:www\.)?filecrypt\.cc/Container/\w+' diff --git a/module/plugins/crypter/FurLy.py b/module/plugins/crypter/FurLy.py new file mode 100644 index 000000000..b8e9332e2 --- /dev/null +++ b/module/plugins/crypter/FurLy.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class FurLy(SimpleCrypter): + __name__ = "FurLy" + __type__ = "crypter" + __version__ = "0.01" + + __pattern__ = r'http://(?:www\.)?fur\.ly/(\d/)?\w+' + + __description__ = """Fur.ly decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + URL_REPLACEMENTS = [(r'fur\.ly/', r'fur\.ly/bar/')] + + LINK_PATTERN = r'urls\[\d+\] = "(.+?)"' + OFFLINE_PATTERN = r'var output;\s*var total' + + +getInfo = create_getInfo(FurLy) diff --git a/module/plugins/crypter/GooGl.py b/module/plugins/crypter/GooGl.py index 30e193b9d..b36e22884 100644 --- a/module/plugins/crypter/GooGl.py +++ b/module/plugins/crypter/GooGl.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleDereferer import SimpleDereferer, create_getInfo +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo from module.common.json_layer import json_loads -class GooGl(SimpleDereferer): +class GooGl(SimpleCrypter): __name__ = "GooGl" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.03" __pattern__ = r'https?://(?:www\.)?goo\.gl/([a-zA-Z]+/)?\w+' @@ -22,11 +22,11 @@ class GooGl(SimpleDereferer): OFFLINE_PATTERN = r'has been disabled|does not exist' - def getLink(self): + def getLinks(self): rep = self.load(self.API_URL, get={'shortUrl': self.pyfile.url}) self.logDebug("JSON data: " + rep) rep = json_loads(rep) - return rep['longUrl'] if "longUrl" in rep else None + return [rep['longUrl']] if "longUrl" in rep else None getInfo = create_getInfo(GooGl) diff --git a/module/plugins/crypter/LinkSaveIn.py b/module/plugins/crypter/LinkSaveIn.py index 95652096d..dce74b689 100644 --- a/module/plugins/crypter/LinkSaveIn.py +++ b/module/plugins/crypter/LinkSaveIn.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleDereferer import SimpleDereferer, create_getInfo +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo -class LinkSaveIn(SimpleDereferer): +class LinkSaveIn(SimpleCrypter): __name__ = "LinkSaveIn" __type__ = "crypter" - __version__ = "2.04" + __version__ = "2.05" __pattern__ = r'https?://(?:www\.)?linksave\.in/\w+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/MegaCoNzFolder.py b/module/plugins/crypter/MegaCoNzFolder.py index bd135ac5f..0c6f224a4 100644 --- a/module/plugins/crypter/MegaCoNzFolder.py +++ b/module/plugins/crypter/MegaCoNzFolder.py @@ -10,7 +10,7 @@ class MegaCoNzFolder(Crypter): __type__ = "crypter" __version__ = "0.04" - __pattern__ = r'(?:https?://(?:www\.)?mega\.co\.nz/|mega:|chrome:.+?)#F!(?P<ID>[\w^_]+)!(?P<KEY>[\w,\\-]+)' + __pattern__ = r'(?:https?://(?:www\.)?mega(\.co)?\.nz/|mega:|chrome:.+?)#F!(?P<ID>[\w^_]+)!(?P<KEY>[\w,\\-]+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] @@ -26,7 +26,7 @@ class MegaCoNzFolder(Crypter): def decrypt(self, pyfile): url = "https://mega.co.nz/#F!%s!%s" % re.match(self.__pattern__, pyfile.url).groups() self.html = self.load("http://rapidgen.org/linkfinder", post={'linklisturl': url}) - self.urls = re.findall(r'(https://mega.co.nz/#N!.+?)<', self.html) + self.urls = re.findall(r'(https://mega(\.co)?\.nz/#N!.+?)<', self.html) if not self.urls: #@TODO: Remove in 0.4.10 self.fail(_("No link grabbed")) diff --git a/module/plugins/crypter/NCryptIn.py b/module/plugins/crypter/NCryptIn.py index 8ceb9d3c8..593e9b506 100644 --- a/module/plugins/crypter/NCryptIn.py +++ b/module/plugins/crypter/NCryptIn.py @@ -6,13 +6,13 @@ import re from Crypto.Cipher import AES from module.plugins.Crypter import Crypter -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha class NCryptIn(Crypter): __name__ = "NCryptIn" __type__ = "crypter" - __version__ = "1.34" + __version__ = "1.35" __pattern__ = r'http://(?:www\.)?ncrypt\.in/(?P<TYPE>folder|link|frame)-([^/\?]+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/SafelinkingNet.py b/module/plugins/crypter/SafelinkingNet.py index 7f0915065..5d822af11 100644 --- a/module/plugins/crypter/SafelinkingNet.py +++ b/module/plugins/crypter/SafelinkingNet.py @@ -6,13 +6,13 @@ 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.plugins.internal.SolveMedia import SolveMedia class SafelinkingNet(Crypter): __name__ = "SafelinkingNet" __type__ = "crypter" - __version__ = "0.14" + __version__ = "0.15" __pattern__ = r'https?://(?:www\.)?safelinking\.net/([pd])/\w+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/TinyurlCom.py b/module/plugins/crypter/TinyurlCom.py new file mode 100644 index 000000000..e2cf50358 --- /dev/null +++ b/module/plugins/crypter/TinyurlCom.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class TinyurlCom(SimpleCrypter): + __name__ = "TinyurlCom" + __type__ = "crypter" + __version__ = "0.02" + + __pattern__ = r'https?://(?:www\.)?(preview\.)?tinyurl\.com/[\w-]+' + + __description__ = """Tinyurl.com decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + URL_REPLACEMENTS = [(r'preview\.', r'')] + + OFFLINE_PATTERN = r">Error: Unable to find site's URL to redirect to" + + +getInfo = create_getInfo(TinyurlCom) diff --git a/module/plugins/crypter/XFileSharingProFolder.py b/module/plugins/crypter/XFileSharingProFolder.py index 8b850271d..2e1a2f022 100644 --- a/module/plugins/crypter/XFileSharingProFolder.py +++ b/module/plugins/crypter/XFileSharingProFolder.py @@ -8,9 +8,9 @@ from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo class XFileSharingProFolder(XFSCrypter): __name__ = "XFileSharingProFolder" __type__ = "crypter" - __version__ = "0.05" + __version__ = "0.06" - __pattern__ = r'^unmatchable$' + __pattern__ = r'https?://(?:www\.)?(?:\w+\.)*?(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,}(?:\.[a-zA-Z]{2,}){1,2})(?:\:\d+)?)/(?:user|folder)s?/\w+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] diff --git a/module/plugins/hooks/UserAgentSwitcher.py b/module/plugins/hooks/UserAgentSwitcher.py index 5f9fd5212..74c43f7c4 100644 --- a/module/plugins/hooks/UserAgentSwitcher.py +++ b/module/plugins/hooks/UserAgentSwitcher.py @@ -8,10 +8,12 @@ from module.plugins.Hook import Hook class UserAgentSwitcher(Hook): __name__ = "UserAgentSwitcher" __type__ = "hook" - __version__ = "0.07" + __version__ = "0.08" - __config__ = [("activated", "bool", "Activated" , True ), - ("useragent", "str" , "Custom user-agent string" , "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0")] + __config__ = [("activated" , "bool", "Activated" , True ), + ("connecttimeout", "int" , "Connection timeout in seconds" , 60 ), + ("maxredirs" , "int" , "Maximum number of redirects to follow" , 10 ), + ("useragent" , "str" , "Custom user-agent string" , "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0")] __description__ = """Custom user-agent""" __license__ = "GPLv3" @@ -26,7 +28,16 @@ class UserAgentSwitcher(Hook): def downloadPreparing(self, pyfile): - useragent = self.getConfig('useragent').encode("utf8", "replace") #@TODO: Remove `encode` in 0.4.10 + connecttimeout = self.getConfig('connecttimeout') + maxredirs = self.getConfig('maxredirs') + useragent = self.getConfig('useragent').encode("utf8", "replace") #@TODO: Remove `encode` in 0.4.10 + + if connecttimeout: + pyfile.plugin.req.http.c.setopt(pycurl.CONNECTTIMEOUT, connecttimeout) + + if maxredirs: + pyfile.plugin.req.http.c.setopt(pycurl.MAXREDIRS, maxredirs) + if useragent: self.logDebug("Use custom user-agent string: " + useragent) pyfile.plugin.req.http.c.setopt(pycurl.USERAGENT, useragent) diff --git a/module/plugins/hooks/XFileSharingPro.py b/module/plugins/hooks/XFileSharingPro.py index 7443266b3..62872992c 100644 --- a/module/plugins/hooks/XFileSharingPro.py +++ b/module/plugins/hooks/XFileSharingPro.py @@ -8,7 +8,7 @@ from module.plugins.Hook import Hook class XFileSharingPro(Hook): __name__ = "XFileSharingPro" __type__ = "hook" - __version__ = "0.37" + __version__ = "0.38" __config__ = [("activated" , "bool", "Activated" , True ), ("use_hoster_list" , "bool", "Load listed hosters only" , False), @@ -17,25 +17,25 @@ class XFileSharingPro(Hook): ("hoster_list" , "str" , "Hoster list (comma separated)" , "" ), ("crypter_list" , "str" , "Crypter list (comma separated)", "" )] - __description__ = """Load XFileSharingPro based hosters and crypter which don't need a own plugin to run""" + __description__ = """Load XFileSharingPro based hosters and crypters which don't need a own plugin to run""" __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] interval = 0 #@TODO: Remove in 0.4.10 - regexp = {'hoster' : (r'https?://(?:www\.)?(?P<DOMAIN>[\w\-.^_]{3,63}(?:\.[a-zA-Z]{2,})(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)', + regexp = {'hoster' : (r'https?://(?:www\.)?(?:\w+\.)*?(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,}(?:\.[a-zA-Z]{2,}){1,2})(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)', r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:embed-)?\w+'), - 'crypter': (r'https?://(?:www\.)?(?P<DOMAIN>[\w\-.^_]{3,63}(?:\.[a-zA-Z]{2,})(?:\:\d+)?)/(?:user|folder)s?/\w+', + 'crypter': (r'https?://(?:www\.)?(?:\w+\.)*?(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,}(?:\.[a-zA-Z]{2,}){1,2})(?:\:\d+)?)/(?:user|folder)s?/\w+', r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:user|folder)s?/\w+')} HOSTER_BUILTIN = [#WORKING HOSTERS: "backin.net", "eyesfile.ca", "file4safe.com", "fileband.com", "filedwon.com", "fileparadox.in", "filevice.com", "hostingbulk.com", "junkyvideo.com", "linestorage.com", "ravishare.com", "ryushare.com", - "salefiles.com", "sendmyway.com", "sharesix.com", "thefile.me", "verzend.be", "xvidstage.com", + "salefiles.com", "sendmyway.com", "sharesix.com", "thefile.me", "verzend.be", "worldbytez.com", "xvidstage.com", #NOT TESTED: "101shared.com", "4upfiles.com", "filemaze.ws", "filenuke.com", "linkzhost.com", "mightyupload.com", "rockdizfile.com", "sharebeast.com", "sharerepo.com", "shareswift.com", "uploadbaz.com", "uploadc.com", - "vidbull.com", "worldbytez.com", "zalaa.com", "zomgupload.com", + "vidbull.com", "zalaa.com", "zomgupload.com", #NOT WORKING: "amonshare.com", "banicrazy.info", "boosterking.com", "host4desi.com", "laoupload.com", "rd-fs.com"] CRYPTER_BUILTIN = ["junocloud.me", "rapidfileshare.net"] diff --git a/module/plugins/hoster/BitshareCom.py b/module/plugins/hoster/BitshareCom.py index 79aaedcd9..5c709e4f7 100644 --- a/module/plugins/hoster/BitshareCom.py +++ b/module/plugins/hoster/BitshareCom.py @@ -4,14 +4,14 @@ from __future__ import with_statement import re -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class BitshareCom(SimpleHoster): __name__ = "BitshareCom" __type__ = "hoster" - __version__ = "0.53" + __version__ = "0.54" __pattern__ = r'http://(?:www\.)?bitshare\.com/(files/)?(?(1)|\?f=)(?P<ID>\w+)(?(1)/(?P<NAME>.+?)\.html)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/CatShareNet.py b/module/plugins/hoster/CatShareNet.py index 868be4033..c966dbe1a 100644 --- a/module/plugins/hoster/CatShareNet.py +++ b/module/plugins/hoster/CatShareNet.py @@ -3,13 +3,13 @@ import re from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha class CatShareNet(SimpleHoster): __name__ = "CatShareNet" __type__ = "hoster" - __version__ = "0.14" + __version__ = "0.15" __pattern__ = r'http://(?:www\.)?catshare\.net/\w{16}' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/CrockoCom.py b/module/plugins/hoster/CrockoCom.py index 4f872f60a..098ba5fab 100644 --- a/module/plugins/hoster/CrockoCom.py +++ b/module/plugins/hoster/CrockoCom.py @@ -3,14 +3,14 @@ import re import urlparse -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class CrockoCom(SimpleHoster): __name__ = "CrockoCom" __type__ = "hoster" - __version__ = "0.19" + __version__ = "0.20" __pattern__ = r'http://(?:www\.)?(crocko|easy-share)\.com/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/DateiTo.py b/module/plugins/hoster/DateiTo.py index f0ad95d1e..92a96b9ec 100644 --- a/module/plugins/hoster/DateiTo.py +++ b/module/plugins/hoster/DateiTo.py @@ -2,14 +2,14 @@ import re -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DateiTo(SimpleHoster): __name__ = "DateiTo" __type__ = "hoster" - __version__ = "0.08" + __version__ = "0.09" __pattern__ = r'http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/DepositfilesCom.py b/module/plugins/hoster/DepositfilesCom.py index 8559bbc36..18f23f552 100644 --- a/module/plugins/hoster/DepositfilesCom.py +++ b/module/plugins/hoster/DepositfilesCom.py @@ -3,14 +3,14 @@ import re import urllib -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DepositfilesCom(SimpleHoster): __name__ = "DepositfilesCom" __type__ = "hoster" - __version__ = "0.55" + __version__ = "0.56" __pattern__ = r'https?://(?:www\.)?(depositfiles\.com|dfiles\.(eu|ru))(/\w{1,3})?/files/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/DlFreeFr.py b/module/plugins/hoster/DlFreeFr.py index 72d15852c..ff5ee7b92 100644 --- a/module/plugins/hoster/DlFreeFr.py +++ b/module/plugins/hoster/DlFreeFr.py @@ -5,7 +5,6 @@ import re from module.network.Browser import Browser from module.network.CookieJar import CookieJar -from module.plugins.internal.CaptchaService import AdYouLike from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns @@ -36,7 +35,7 @@ class CustomBrowser(Browser): class DlFreeFr(SimpleHoster): __name__ = "DlFreeFr" __type__ = "hoster" - __version__ = "0.28" + __version__ = "0.30" __pattern__ = r'http://(?:www\.)?dl\.free\.fr/(\w+|getfile\.pl\?file=/\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -44,12 +43,12 @@ class DlFreeFr(SimpleHoster): __description__ = """Dl.free.fr hoster plugin""" __license__ = "GPLv3" __authors__ = [("the-razer", "daniel_ AT gmx DOT net"), - ("zoidberg", "zoidberg@mujmail.cz"), - ("Toilal", "toilal.dev@gmail.com")] + ("zoidberg" , "zoidberg@mujmail.cz" ), + ("Toilal" , "toilal.dev@gmail.com" )] - NAME_PATTERN = r'Fichier:</td>\s*<td.*?>(?P<N>[^>]*)</td>' - SIZE_PATTERN = r'Taille:</td>\s*<td.*?>(?P<S>[\d.,]+\w)o' + NAME_PATTERN = r'Fichier:</td>\s*<td.*?>(?P<N>[^>]*)</td>' + SIZE_PATTERN = r'Taille:</td>\s*<td.*?>(?P<S>[\d.,]+\w)o' OFFLINE_PATTERN = r'Erreur 404 - Document non trouv|Fichier inexistant|Le fichier demandé n\'a pas été trouvé' @@ -84,6 +83,8 @@ class DlFreeFr(SimpleHoster): # Direct access to requested file for users using free.fr as Internet Service Provider. self.link = valid_url + self.download(self.link, disposition=True) + elif headers.get('code') == 404: self.offline() @@ -93,15 +94,10 @@ class DlFreeFr(SimpleHoster): def handleFree(self, pyfile): action, inputs = self.parseHtmlForm('action="getfile.pl"') - - adyoulike = AdYouLike(self) - response, challenge = adyoulike.challenge() - inputs.update(response) - self.load("http://dl.free.fr/getfile.pl", post=inputs) headers = self.getLastHeaders() if headers.get("code") == 302 and "set-cookie" in headers and "location" in headers: - m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", headers.get("set-cookie")) + m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*)", headers.get("set-cookie")) cj = CookieJar(__name__) if m: cj.setCookie(m.group(4), m.group(1), m.group(2), m.group(3)) @@ -109,7 +105,6 @@ class DlFreeFr(SimpleHoster): self.fail(_("Cookie error")) self.link = headers.get("location") - self.req.setCookieJar(cj) else: self.fail(_("Invalid response")) diff --git a/module/plugins/hoster/ExtabitCom.py b/module/plugins/hoster/ExtabitCom.py index f3b4d28be..ead2e1e53 100644 --- a/module/plugins/hoster/ExtabitCom.py +++ b/module/plugins/hoster/ExtabitCom.py @@ -4,14 +4,14 @@ import re from module.common.json_layer import json_loads -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, secondsToMidnight class ExtabitCom(SimpleHoster): __name__ = "ExtabitCom" __type__ = "hoster" - __version__ = "0.65" + __version__ = "0.66" __pattern__ = r'http://(?:www\.)?extabit\.com/(file|go|fid)/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/FileboomMe.py b/module/plugins/hoster/FileboomMe.py new file mode 100644 index 000000000..9cdeebe3d --- /dev/null +++ b/module/plugins/hoster/FileboomMe.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +import re + +from urlparse import urljoin + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class FileboomMe(SimpleHoster): + __name__ = "FileboomMe" + __type__ = "hoster" + __version__ = "0.02" + + __pattern__ = r'https?://f(?:ile)?boom\.me/file/(?P<ID>\w+)' + + __description__ = """Fileboom.me hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("GammaC0de", None)] + + + NAME_PATTERN = r'<i class="icon-download"></i>\s*(?P<N>.+?)\s*<' + SIZE_PATTERN = r'File size: (?P<S>[\d.,]+) (?P<U>[\w^_]+)' + OFFLINE_PATTERN = r'>This file is no longer available' + + WAIT_PATTERN = r'<div class="tik-tak">([\d:]+)' + LINK_PATTERN = r'/file/url\.html\?file=\w+' + + CAPTCHA_PATTERN = r'<img .* src="(/file/captcha.html\?v=\w+)"' + + + def setup(self): + self.resumeDownload = True + self.multiDL = False + self.chunkLimit = 1 + + + def handleFree(self, pyfile): + post_url = urljoin(pyfile.url, "/file/" + self.info['pattern']['ID']) + + m = re.search(r'data-slow-id="(\w+)"', self.html) + if m: + self.html = self.load(post_url, + post={'slow_id': m.group(1)}) + + m = re.search(self.LINK_PATTERN, self.html) + if m: + self.link = urljoin(pyfile.url, m.group(0)) + + else: + for _i in xrange(5): + m = re.search(r'<input type="hidden" name="uniqueId" value="(\w+)">', self.html) + if m: + uniqueId = m.group(1) + + m = re.search(self.CAPTCHA_PATTERN, self.html) + if m: + captcha = self.decryptCaptcha(urljoin(pyfile.url, m.group(1))) + + self.html = self.load(post_url, + post={'CaptchaForm[code]' : captcha, + 'free' : 1, + 'freeDownloadRequest': 1, + 'uniqueId' : uniqueId}) + + if 'The verification code is incorrect' in self.html: + self.invalidCaptcha() + + else: + self.checkErrors() + + self.html = self.load(post_url, + post={'free' : 1, + 'uniqueId': uniqueId}) + + m = re.search(self.LINK_PATTERN, self.html) + if m: + self.link = urljoin(pyfile.url, m.group(0)) + + else: + self.invalidCaptcha() + + break + + else: + self.fail(_("Captcha not found")) + + else: + m = re.search(r'>\s*Please wait ([\d:]+)', self.html) + if m: + wait_time = 0 + for v in re.findall(r'(\d+)', m.group(1), re.I): + wait_time = 60 * wait_time + int(v) + self.wait(wait_time) + self.retry() + break + + else: + self.fail(_("Invalid captcha")) + + +getInfo = create_getInfo(FileboomMe) diff --git a/module/plugins/hoster/FilecloudIo.py b/module/plugins/hoster/FilecloudIo.py index 38d2972a1..346e9c444 100644 --- a/module/plugins/hoster/FilecloudIo.py +++ b/module/plugins/hoster/FilecloudIo.py @@ -3,14 +3,14 @@ import re from module.common.json_layer import json_loads -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilecloudIo(SimpleHoster): __name__ = "FilecloudIo" __type__ = "hoster" - __version__ = "0.08" + __version__ = "0.09" __pattern__ = r'http://(?:www\.)?(?:filecloud\.io|ifile\.it|mihd\.net)/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/FilepostCom.py b/module/plugins/hoster/FilepostCom.py index 2a9e3dc26..1f3de6717 100644 --- a/module/plugins/hoster/FilepostCom.py +++ b/module/plugins/hoster/FilepostCom.py @@ -4,14 +4,14 @@ import re import time from module.common.json_layer import json_loads -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilepostCom(SimpleHoster): __name__ = "FilepostCom" __type__ = "hoster" - __version__ = "0.33" + __version__ = "0.34" __pattern__ = r'https?://(?:www\.)?(?:filepost\.com/files|fp\.io)/(?P<ID>[^/]+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/FilerNet.py b/module/plugins/hoster/FilerNet.py index 156392c79..3b876ed48 100644 --- a/module/plugins/hoster/FilerNet.py +++ b/module/plugins/hoster/FilerNet.py @@ -8,14 +8,14 @@ import pycurl import re import urlparse -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilerNet(SimpleHoster): __name__ = "FilerNet" __type__ = "hoster" - __version__ = "0.19" + __version__ = "0.20" __pattern__ = r'https?://(?:www\.)?filer\.net/get/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/FileserveCom.py b/module/plugins/hoster/FileserveCom.py index 4bca2eb59..f8cf652b9 100644 --- a/module/plugins/hoster/FileserveCom.py +++ b/module/plugins/hoster/FileserveCom.py @@ -6,7 +6,7 @@ from module.common.json_layer import json_loads from module.network.RequestFactory import getURL from module.plugins.Hoster import Hoster from module.plugins.Plugin import chunks -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import secondsToMidnight from module.utils import parseFileSize @@ -33,7 +33,7 @@ def checkFile(plugin, urls): class FileserveCom(Hoster): __name__ = "FileserveCom" __type__ = "hoster" - __version__ = "0.54" + __version__ = "0.55" __pattern__ = r'http://(?:www\.)?fileserve\.com/file/(?P<ID>[^/]+)' diff --git a/module/plugins/hoster/FreakshareCom.py b/module/plugins/hoster/FreakshareCom.py index 6a595e75b..d005443d9 100644 --- a/module/plugins/hoster/FreakshareCom.py +++ b/module/plugins/hoster/FreakshareCom.py @@ -3,14 +3,14 @@ import re from module.plugins.Hoster import Hoster -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import secondsToMidnight class FreakshareCom(Hoster): __name__ = "FreakshareCom" __type__ = "hoster" - __version__ = "0.40" + __version__ = "0.41" __pattern__ = r'http://(?:www\.)?freakshare\.(net|com)/files/\S*?/' diff --git a/module/plugins/hoster/Keep2ShareCc.py b/module/plugins/hoster/Keep2ShareCc.py index fdae65096..fb94d12c4 100644 --- a/module/plugins/hoster/Keep2ShareCc.py +++ b/module/plugins/hoster/Keep2ShareCc.py @@ -3,14 +3,14 @@ import re import urlparse -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class Keep2ShareCc(SimpleHoster): __name__ = "Keep2ShareCc" __type__ = "hoster" - __version__ = "0.21" + __version__ = "0.22" __pattern__ = r'https?://(?:www\.)?(keep2share|k2s|keep2s)\.cc/file/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/KingfilesNet.py b/module/plugins/hoster/KingfilesNet.py index 99f309d00..42547d658 100644 --- a/module/plugins/hoster/KingfilesNet.py +++ b/module/plugins/hoster/KingfilesNet.py @@ -2,14 +2,14 @@ import re -from module.plugins.internal.CaptchaService import SolveMedia +from module.plugins.internal.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class KingfilesNet(SimpleHoster): __name__ = "KingfilesNet" __type__ = "hoster" - __version__ = "0.07" + __version__ = "0.08" __pattern__ = r'http://(?:www\.)?kingfiles\.net/(?P<ID>\w{12})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/LetitbitNet.py b/module/plugins/hoster/LetitbitNet.py index 40d792e11..62afb6c7c 100644 --- a/module/plugins/hoster/LetitbitNet.py +++ b/module/plugins/hoster/LetitbitNet.py @@ -11,7 +11,7 @@ import urlparse from module.common.json_layer import json_loads, json_dumps from module.network.RequestFactory import getURL -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, secondsToMidnight @@ -35,7 +35,7 @@ def getInfo(urls): class LetitbitNet(SimpleHoster): __name__ = "LetitbitNet" __type__ = "hoster" - __version__ = "0.30" + __version__ = "0.31" __pattern__ = r'https?://(?:www\.)?(letitbit|shareflare)\.net/download/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/LoadTo.py b/module/plugins/hoster/LoadTo.py index 2b4202051..d2b25f0db 100644 --- a/module/plugins/hoster/LoadTo.py +++ b/module/plugins/hoster/LoadTo.py @@ -6,14 +6,14 @@ import re -from module.plugins.internal.CaptchaService import SolveMedia +from module.plugins.internal.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class LoadTo(SimpleHoster): __name__ = "LoadTo" __type__ = "hoster" - __version__ = "0.22" + __version__ = "0.23" __pattern__ = r'http://(?:www\.)?load\.to/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/LuckyShareNet.py b/module/plugins/hoster/LuckyShareNet.py index 26af8153f..f4932d93d 100644 --- a/module/plugins/hoster/LuckyShareNet.py +++ b/module/plugins/hoster/LuckyShareNet.py @@ -4,14 +4,14 @@ import re from bottle import json_loads -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class LuckyShareNet(SimpleHoster): __name__ = "LuckyShareNet" __type__ = "hoster" - __version__ = "0.06" + __version__ = "0.07" __pattern__ = r'https?://(?:www\.)?luckyshare\.net/(?P<ID>\d{10,})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/MediafireCom.py b/module/plugins/hoster/MediafireCom.py index 1ba38fdf7..09eb4705d 100644 --- a/module/plugins/hoster/MediafireCom.py +++ b/module/plugins/hoster/MediafireCom.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.CaptchaService import SolveMedia, ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.internal.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class MediafireCom(SimpleHoster): __name__ = "MediafireCom" __type__ = "hoster" - __version__ = "0.88" + __version__ = "0.89" __pattern__ = r'https?://(?:www\.)?mediafire\.com/(file/|view/\??|download(\.php\?|/)|\?)(?P<ID>\w{15})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/MegaCoNz.py b/module/plugins/hoster/MegaCoNz.py index aa7755af4..5280b42ec 100644 --- a/module/plugins/hoster/MegaCoNz.py +++ b/module/plugins/hoster/MegaCoNz.py @@ -48,9 +48,9 @@ from module.utils import decode, fs_decode, fs_encode class MegaCoNz(Hoster): __name__ = "MegaCoNz" __type__ = "hoster" - __version__ = "0.26" + __version__ = "0.29" - __pattern__ = r'(?:https?://(?:www\.)?mega\.co\.nz/|mega:|chrome:.+?)#(?P<TYPE>N|)!(?P<ID>[\w^_]+)!(?P<KEY>[\w,-]+)' + __pattern__ = r'(?:https?://(?:www\.)?mega(?:\.co)?\.nz/|mega:|chrome:.+?)#(?P<TYPE>N|)!(?P<ID>[\w^_]+)!(?P<KEY>[\w,-]+)' __description__ = """Mega.co.nz hoster plugin""" __license__ = "GPLv3" @@ -82,7 +82,7 @@ class MegaCoNz(Hoster): """ Dispatch a call to the api, see https://mega.co.nz/#developers """ # generate a session id, no idea where to obtain elsewhere - uid = random.random.randint(10 << 9, 10 ** 10) + uid = random.randint(10 << 9, 10 ** 10) res = self.load(self.API_URL, get={'id': uid}, post=json_dumps([kwargs])) self.logDebug("Api Response: " + res) diff --git a/module/plugins/hoster/NitroflareCom.py b/module/plugins/hoster/NitroflareCom.py index 6696d15d3..a0734d9b1 100644 --- a/module/plugins/hoster/NitroflareCom.py +++ b/module/plugins/hoster/NitroflareCom.py @@ -2,30 +2,28 @@ import re -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster class NitroflareCom(SimpleHoster): __name__ = "NitroflareCom" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.14" __pattern__ = r'https?://(?:www\.)?nitroflare\.com/view/(?P<ID>[\w^_]+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] __description__ = """Nitroflare.com hoster plugin""" __license__ = "GPLv3" - __authors__ = [("sahil", "sahilshekhawat01@gmail.com"), - ("Walter Purcaro", "vuolter@gmail.com"), - ("Stickell", "l.stickell@yahoo.it")] - - # URL_REPLACEMENTS = [("http://", "https://")] + __authors__ = [("sahil" , "sahilshekhawat01@gmail.com"), + ("Walter Purcaro", "vuolter@gmail.com" ), + ("Stickell" , "l.stickell@yahoo.it" )] INFO_PATTERN = r'title="(?P<N>.+?)".+>(?P<S>[\d.,]+) (?P<U>[\w^_]+)' OFFLINE_PATTERN = r'>File doesn\'t exist' - LINK_FREE_PATTERN = r'(https?://[\w\-]+\.nitroflare\.com/.+?)"' + LINK_PREMIUM_PATTERN = LINK_FREE_PATTERN = r'(https?://[\w\-]+\.nitroflare\.com/.+?)"' RECAPTCHA_KEY = "6Lenx_USAAAAAF5L1pmTWvWcH73dipAEzNnmNLgy" PREMIUM_ONLY_PATTERN = r'This file is available with Premium only' @@ -61,12 +59,4 @@ class NitroflareCom(SimpleHoster): 'recaptcha_challenge_field': challenge, 'recaptcha_response_field' : response}) - if "The captcha wasn't entered correctly" in self.html: - self.logWarning("The captcha wasn't entered correctly") - return - - if "You have to fill the captcha" in self.html: - self.logWarning("Captcha unfilled") - return - return super(NitroflareCom, self).handleFree(pyfile) diff --git a/module/plugins/hoster/OboomCom.py b/module/plugins/hoster/OboomCom.py index cfc448ff0..b50e2fb42 100644 --- a/module/plugins/hoster/OboomCom.py +++ b/module/plugins/hoster/OboomCom.py @@ -7,13 +7,13 @@ import re from module.common.json_layer import json_loads from module.plugins.Hoster import Hoster -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha class OboomCom(Hoster): __name__ = "OboomCom" __type__ = "hoster" - __version__ = "0.32" + __version__ = "0.33" __pattern__ = r'https?://(?:www\.)?oboom\.com/(?:#(?:id=|/)?)?(?P<ID>\w{8})' diff --git a/module/plugins/hoster/OpenloadIo.py b/module/plugins/hoster/OpenloadIo.py index c31b5b997..5a60b6787 100644 --- a/module/plugins/hoster/OpenloadIo.py +++ b/module/plugins/hoster/OpenloadIo.py @@ -6,14 +6,14 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class OpenloadIo(SimpleHoster): __name__ = "OpenloadIo" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.02" __pattern__ = r'https?://(?:www\.)?openload\.io/f/\w{11}' __description__ = """Openload.io hoster plugin""" __license__ = "GPLv3" - NAME_PATTERN = r'<span id="filename">(?P<N>.+)</' + NAME_PATTERN = r'<span id="filename">(?P<N>.+?)</' SIZE_PATTERN = r'<span class="count">(?P<S>[\d.,]+) (?P<U>[\w^_]+)<' OFFLINE_PATTERN = r">(We can't find the file you are looking for)" diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py index ae74e8a63..bd6bb8582 100644 --- a/module/plugins/hoster/RapidgatorNet.py +++ b/module/plugins/hoster/RapidgatorNet.py @@ -5,14 +5,16 @@ import re from module.common.json_layer import json_loads from module.network.HTTPRequest import BadHeader -from module.plugins.internal.CaptchaService import AdsCaptcha, ReCaptcha, SolveMedia +from module.plugins.internal.AdsCaptcha import AdsCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.internal.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class RapidgatorNet(SimpleHoster): __name__ = "RapidgatorNet" __type__ = "hoster" - __version__ = "0.33" + __version__ = "0.34" __pattern__ = r'http://(?:www\.)?(rapidgator\.net|rg\.to)/file/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/RapiduNet.py b/module/plugins/hoster/RapiduNet.py index fcccbbebc..da353ec70 100644 --- a/module/plugins/hoster/RapiduNet.py +++ b/module/plugins/hoster/RapiduNet.py @@ -5,14 +5,14 @@ import re import time from module.common.json_layer import json_loads -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class RapiduNet(SimpleHoster): __name__ = "RapiduNet" __type__ = "hoster" - __version__ = "0.08" + __version__ = "0.09" __pattern__ = r'https?://(?:www\.)?rapidu\.net/(?P<ID>\d{10})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py index a260f39f7..64a490993 100644 --- a/module/plugins/hoster/ShareonlineBiz.py +++ b/module/plugins/hoster/ShareonlineBiz.py @@ -6,14 +6,14 @@ import urllib import urlparse from module.network.RequestFactory import getURL -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class ShareonlineBiz(SimpleHoster): __name__ = "ShareonlineBiz" __type__ = "hoster" - __version__ = "0.50" + __version__ = "0.51" __pattern__ = r'https?://(?:www\.)?(share-online\.biz|egoshare\.com)/(download\.php\?id=|dl/)(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -39,25 +39,24 @@ class ShareonlineBiz(SimpleHoster): def apiInfo(cls, url): info = super(ShareonlineBiz, cls).apiInfo(url) - if url: - field = getURL("http://api.share-online.biz/linkcheck.php", - get={'md5' : "1", - 'links': re.match(cls.__pattern__, url).group("ID")}, - decode=True).split(";") - - try: - if field[1] == "OK": - info['fileid'] = field[0] - info['status'] = 2 - info['name'] = field[2] - info['size'] = field[3] #: in bytes - info['md5'] = field[4].strip().lower().replace("\n\n", "") #: md5 - - elif field[1] in ("DELETED", "NOT FOUND"): - info['status'] = 1 - - except IndexError: - pass + field = getURL("http://api.share-online.biz/linkcheck.php", + get={'md5' : "1", + 'links': re.match(cls.__pattern__, url).group("ID")}, + decode=True).split(";") + + try: + if field[1] == "OK": + info['fileid'] = field[0] + info['status'] = 2 + info['name'] = field[2] + info['size'] = field[3] #: in bytes + info['md5'] = field[4].strip().lower().replace("\n\n", "") #: md5 + + elif field[1] in ("DELETED", "NOT FOUND"): + info['status'] = 1 + + except IndexError: + pass return info diff --git a/module/plugins/hoster/TurbobitNet.py b/module/plugins/hoster/TurbobitNet.py index 7995bd0c0..254e06c2a 100644 --- a/module/plugins/hoster/TurbobitNet.py +++ b/module/plugins/hoster/TurbobitNet.py @@ -10,14 +10,14 @@ import urllib from Crypto.Cipher import ARC4 from module.network.RequestFactory import getURL -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp class TurbobitNet(SimpleHoster): __name__ = "TurbobitNet" __type__ = "hoster" - __version__ = "0.19" + __version__ = "0.20" __pattern__ = r'http://(?:www\.)?turbobit\.net/(?:download/free/)?(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/TusfilesNet.py b/module/plugins/hoster/TusfilesNet.py index 6021a4c30..a79d8c869 100644 --- a/module/plugins/hoster/TusfilesNet.py +++ b/module/plugins/hoster/TusfilesNet.py @@ -18,7 +18,6 @@ class TusfilesNet(XFSHoster): INFO_PATTERN = r'\](?P<N>.+) - (?P<S>[\d.,]+) (?P<U>[\w^_]+)\[' - OFFLINE_PATTERN = r'>File Not Found|<Title>TusFiles - Fast Sharing Files!|The file you are trying to download is no longer available' def setup(self): diff --git a/module/plugins/hoster/UploadableCh.py b/module/plugins/hoster/UploadableCh.py index 2907bd825..f323a3538 100644 --- a/module/plugins/hoster/UploadableCh.py +++ b/module/plugins/hoster/UploadableCh.py @@ -2,14 +2,14 @@ import re -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UploadableCh(SimpleHoster): __name__ = "UploadableCh" __type__ = "hoster" - __version__ = "0.09" + __version__ = "0.10" __pattern__ = r'http://(?:www\.)?uploadable\.ch/file/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/UploadedTo.py b/module/plugins/hoster/UploadedTo.py index 669694b22..16966a23d 100644 --- a/module/plugins/hoster/UploadedTo.py +++ b/module/plugins/hoster/UploadedTo.py @@ -4,14 +4,14 @@ import re import time from module.network.RequestFactory import getURL -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UploadedTo(SimpleHoster): __name__ = "UploadedTo" __type__ = "hoster" - __version__ = "0.88" + __version__ = "0.89" __pattern__ = r'https?://(?:www\.)?(uploaded\.(to|net)|ul\.to)(/file/|/?\?id=|.*?&id=|/)(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/UpstoreNet.py b/module/plugins/hoster/UpstoreNet.py index ec0c88c82..6410a2dce 100644 --- a/module/plugins/hoster/UpstoreNet.py +++ b/module/plugins/hoster/UpstoreNet.py @@ -2,14 +2,14 @@ import re -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UpstoreNet(SimpleHoster): __name__ = "UpstoreNet" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" __pattern__ = r'https?://(?:www\.)?upstore\.net/' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/WebshareCz.py b/module/plugins/hoster/WebshareCz.py index ae670c8d4..c898d23ab 100644 --- a/module/plugins/hoster/WebshareCz.py +++ b/module/plugins/hoster/WebshareCz.py @@ -9,42 +9,41 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class WebshareCz(SimpleHoster): __name__ = "WebshareCz" __type__ = "hoster" - __version__ = "0.16" + __version__ = "0.18" - __pattern__ = r'https?://(?:www\.)?webshare\.cz/(?:#/)?file/(?P<ID>\w+)' + __pattern__ = r'https?://(?:www\.)?(en\.)?webshare\.cz/(?:#/)?file/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] __description__ = """WebShare.cz hoster plugin""" __license__ = "GPLv3" - __authors__ = [("stickell", "l.stickell@yahoo.it"), - ("rush", "radek.senfeld@gmail.com")] + __authors__ = [("stickell", "l.stickell@yahoo.it "), + ("rush" , "radek.senfeld@gmail.com")] @classmethod - def getInfo(cls, url="", html=""): - info = super(WebshareCz, cls).getInfo(url, html) + def apiInfo(cls, url): + info = super(WebshareCz, cls).apiInfo(url) - if url: - info['pattern'] = re.match(cls.__pattern__, url).groupdict() + info['pattern'] = re.match(cls.__pattern__, url).groupdict() - api_data = getURL("https://webshare.cz/api/file_info/", - post={'ident': info['pattern']['ID']}, - decode=True) + api_data = getURL("https://webshare.cz/api/file_info/", + post={'ident': info['pattern']['ID'], 'wst': ""}, + decode=True) - if 'File not found' in api_data: - info['status'] = 1 - else: - info["status"] = 2 - info['name'] = re.search('<name>(.+)</name>', api_data).group(1) or info['name'] - info['size'] = re.search('<size>(.+)</size>', api_data).group(1) or info['size'] + if not re.search(r'<status>OK', api_data): + info['status'] = 1 + else: + info['status'] = 2 + info['name'] = re.search(r'<name>(.+?)<', api_data).group(1) + info['size'] = re.search(r'<size>(.+?)<', api_data).group(1) return info def handleFree(self, pyfile): - wst = self.account.infos['wst'] if self.account and 'wst' in self.account.infos else "" + wst = self.account.getAccountData(self.user).get('wst', None) if self.account else None - api_data = getURL('https://webshare.cz/api/file_link/', + api_data = getURL("https://webshare.cz/api/file_link/", post={'ident': self.info['pattern']['ID'], 'wst': wst}, decode=True) diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py index 1bfb504b7..169fbc8d3 100644 --- a/module/plugins/hoster/XFileSharingPro.py +++ b/module/plugins/hoster/XFileSharingPro.py @@ -8,9 +8,9 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class XFileSharingPro(XFSHoster): __name__ = "XFileSharingPro" __type__ = "hoster" - __version__ = "0.45" + __version__ = "0.46" - __pattern__ = r'^unmatchable$' + __pattern__ = r'https?://(?:www\.)?(?:\w+\.)*?(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,}(?:\.[a-zA-Z]{2,}){1,2})(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)' __description__ = """XFileSharingPro dummy hoster plugin for hook""" __license__ = "GPLv3" diff --git a/module/plugins/hoster/ZahikiNet.py b/module/plugins/hoster/ZahikiNet.py new file mode 100644 index 000000000..b2705662b --- /dev/null +++ b/module/plugins/hoster/ZahikiNet.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class ZahikiNet(SimpleHoster): + __name__ = "ZahikiNet" + __type__ = "hoster" + __version__ = "0.01" + + __pattern__ = r'https?://(?:www\.)?zahiki\.net/\w+/.+' + + __description__ = """Zahiki.net hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + DIRECT_LINK = True + + NAME_PATTERN = r'/(?P<N>.+?) </title>' + OFFLINE_PATTERN = r'>(Not Found|Il file selezionato non esiste)' + + LINK_FREE_PATTERN = r'file: "(.+?)"' + + + def setup(self): + self.resumeDownload = True + self.multiDL = True + self.limitDL = 6 + + +getInfo = create_getInfo(ZahikiNet) diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index c47ac4fe1..d776e5928 100644 --- a/module/plugins/hoster/ZippyshareCom.py +++ b/module/plugins/hoster/ZippyshareCom.py @@ -5,14 +5,14 @@ import urllib from BeautifulSoup import BeautifulSoup -from module.plugins.internal.CaptchaService import ReCaptcha +from module.plugins.internal.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class ZippyshareCom(SimpleHoster): __name__ = "ZippyshareCom" __type__ = "hoster" - __version__ = "0.78" + __version__ = "0.79" __pattern__ = r'http://www\d{0,2}\.zippyshare\.com/v(/|iew\.jsp.*key=)(?P<KEY>[\w^_]+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/internal/AdYouLike.py b/module/plugins/internal/AdYouLike.py new file mode 100644 index 000000000..a9c194dda --- /dev/null +++ b/module/plugins/internal/AdYouLike.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- + +import re + +from module.common.json_layer import json_loads +from module.plugins.internal.Captcha import Captcha + + +class AdYouLike(Captcha): + __name__ = "AdYouLike" + __type__ = "captcha" + __version__ = "0.06" + + __description__ = """AdYouLike captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)' + CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' + + + def detect_key(self, html=None): + html = html or self.retrieve_html() + + m = re.search(self.AYL_PATTERN, html) + n = re.search(self.CALLBACK_PATTERN, html) + if m and n: + self.key = (m.group(1).strip(), n.group(1).strip()) + self.logDebug("Ayl: %s | Callback: %s" % self.key) + return self.key #: key is the tuple(ayl, callback) + else: + self.logWarning("Ayl or callback pattern not found") + return None + + + def challenge(self, key=None, html=None): + ayl, callback = key or self.retrieve_key(html) + + # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, + # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} + ayl = json_loads(ayl) + + html = self.plugin.req.load("http://api-ayl.appspot.com/challenge", + get={'key' : ayl['adyoulike']['key'], + 'env' : ayl['all']['env'], + 'callback': callback}) + try: + challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) + + except AttributeError: + self.fail(_("AdYouLike challenge pattern not found")) + + self.logDebug("Challenge: %s" % challenge) + + return self.result(ayl, challenge), challenge + + + def result(self, server, challenge): + # Adyoulike.g._jsonp_5579316662423138 + # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}}, + # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[], + # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike", + # "iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\" + # height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256, + # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60}, + # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}}, + # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"}) + + if isinstance(server, basestring): + server = json_loads(server) + + if isinstance(challenge, basestring): + challenge = json_loads(challenge) + + try: + instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual'] + result = re.search(u'«(.+?)»', instructions_visual).group(1).strip() + + except AttributeError: + self.fail(_("AdYouLike result not found")) + + result = {'_ayl_captcha_engine' : "adyoulike", + '_ayl_env' : server['all']['env'], + '_ayl_tid' : challenge['tid'], + '_ayl_token_challenge': challenge['token'], + '_ayl_response' : response} + + self.logDebug("Result: %s" % result) + + return result diff --git a/module/plugins/internal/AdsCaptcha.py b/module/plugins/internal/AdsCaptcha.py new file mode 100644 index 000000000..9cab99151 --- /dev/null +++ b/module/plugins/internal/AdsCaptcha.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- + +import random +import re + +from module.plugins.internal.Captcha import Captcha + + +class AdsCaptcha(Captcha): + __name__ = "AdsCaptcha" + __type__ = "captcha" + __version__ = "0.09" + + __description__ = """AdsCaptcha captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("pyLoad Team", "admin@pyload.org")] + + + CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?CaptchaId=(\d+)' + PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?PublicKey=([\w-]+)' + + + def detect_key(self, html=None): + html = html or self.retrieve_html() + + m = re.search(self.PUBLICKEY_PATTERN, html) + n = re.search(self.CAPTCHAID_PATTERN, html) + if m and n: + self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId) + self.logDebug("Key: %s | ID: %s" % self.key) + return self.key + else: + self.logWarning("Key or id pattern not found") + return None + + + def challenge(self, key=None, html=None): + PublicKey, CaptchaId = key or self.retrieve_key(html) + + html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", + get={'CaptchaId': CaptchaId, + 'PublicKey': PublicKey}) + try: + challenge = re.search("challenge: '(.+?)',", html).group(1) + server = re.search("server: '(.+?)',", html).group(1) + + except AttributeError: + self.fail(_("AdsCaptcha challenge pattern not found")) + + self.logDebug("Challenge: %s" % challenge) + + return self.result(server, challenge), challenge + + + def result(self, server, challenge): + result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server, + get={'cid': challenge, 'dummy': random.random()}, + cookies=True, + imgtype="jpg") + + self.logDebug("Result: %s" % result) + + return result diff --git a/module/plugins/internal/Captcha.py b/module/plugins/internal/Captcha.py new file mode 100644 index 000000000..b4af46493 --- /dev/null +++ b/module/plugins/internal/Captcha.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +from module.plugins.Plugin import Base + + +#@TODO: Extend (new) Plugin class; remove all `html` args +class Captcha(Base): + __name__ = "Captcha" + __type__ = "captcha" + __version__ = "0.29" + + __description__ = """Base captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("pyLoad Team", "admin@pyload.org")] + + + key = None #: last key detected + + + def __init__(self, plugin): + self.plugin = plugin + super(Captcha, self).__init__(plugin.core) + + + #@TODO: Recheck in 0.4.10 + def fail(self, reason): + self.plugin.fail(reason) + raise AttributeError(reason) + + + #@TODO: Recheck in 0.4.10 + def retrieve_key(self, html): + if self.detect_key(html): + return self.key + else: + self.fail(_("%s key not found") % self.__name__) + + + #@TODO: Recheck in 0.4.10 + def retrieve_html(self): + if hasattr(self.plugin, "html") and self.plugin.html: + return self.plugin.html + else: + self.fail(_("%s html not found") % self.__name__) + + + def detect_key(self, html=None): + raise NotImplementedError + + + def challenge(self, key=None, html=None): + raise NotImplementedError + + + def result(self, server, challenge): + raise NotImplementedError diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py deleted file mode 100644 index e51844965..000000000 --- a/module/plugins/internal/CaptchaService.py +++ /dev/null @@ -1,489 +0,0 @@ -# -*- coding: utf-8 -*- - -import random -import re -import time -import urlparse - -from base64 import b64encode - -from module.common.json_layer import json_loads -from module.plugins.Plugin import Base, Fail - - -#@TODO: Extend (new) Plugin class; remove all `html` args -class CaptchaService(Base): - __name__ = "CaptchaService" - __type__ = "captcha" - __version__ = "0.29" - - __description__ = """Base captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - key = None #: last key detected - - - def __init__(self, plugin): - self.plugin = plugin - super(CaptchaService, self).__init__(plugin.core) - - - #@TODO: Recheck in 0.4.10 - def fail(self, reason): - self.plugin.fail(reason) - raise AttributeError(reason) - - - #@TODO: Recheck in 0.4.10 - def retrieve_key(self, html): - if self.detect_key(html): - return self.key - else: - self.fail(_("%s key not found") % self.__name__) - - - #@TODO: Recheck in 0.4.10 - def retrieve_html(self): - if hasattr(self.plugin, "html") and self.plugin.html: - return self.plugin.html - else: - self.fail(_("%s html not found") % self.__name__) - - - def detect_key(self, html=None): - raise NotImplementedError - - - def challenge(self, key=None, html=None): - raise NotImplementedError - - - def result(self, server, challenge): - raise NotImplementedError - - -class AdYouLike(CaptchaService): - __name__ = "AdYouLike" - __type__ = "captcha" - __version__ = "0.06" - - __description__ = """AdYouLike captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)' - CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' - - - def detect_key(self, html=None): - html = html or self.retrieve_html() - - m = re.search(self.AYL_PATTERN, html) - n = re.search(self.CALLBACK_PATTERN, html) - if m and n: - self.key = (m.group(1).strip(), n.group(1).strip()) - self.logDebug("Ayl: %s | Callback: %s" % self.key) - return self.key #: key is the tuple(ayl, callback) - else: - self.logWarning("Ayl or callback pattern not found") - return None - - - def challenge(self, key=None, html=None): - ayl, callback = key or self.retrieve_key(html) - - # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, - # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} - ayl = json_loads(ayl) - - html = self.plugin.req.load("http://api-ayl.appspot.com/challenge", - get={'key' : ayl['adyoulike']['key'], - 'env' : ayl['all']['env'], - 'callback': callback}) - try: - challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) - - except AttributeError: - self.fail(_("AdYouLike challenge pattern not found")) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(ayl, challenge), challenge - - - def result(self, server, challenge): - # Adyoulike.g._jsonp_5579316662423138 - # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}}, - # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[], - # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike", - # "iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\" - # height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256, - # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60}, - # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}}, - # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"}) - - if isinstance(server, basestring): - server = json_loads(server) - - if isinstance(challenge, basestring): - challenge = json_loads(challenge) - - try: - instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual'] - result = re.search(u'«(.+?)»', instructions_visual).group(1).strip() - - except AttributeError: - self.fail(_("AdYouLike result not found")) - - result = {'_ayl_captcha_engine' : "adyoulike", - '_ayl_env' : server['all']['env'], - '_ayl_tid' : challenge['tid'], - '_ayl_token_challenge': challenge['token'], - '_ayl_response' : response} - - self.logDebug("Result: %s" % result) - - return result - - -class AdsCaptcha(CaptchaService): - __name__ = "AdsCaptcha" - __type__ = "captcha" - __version__ = "0.09" - - __description__ = """AdsCaptcha captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?CaptchaId=(\d+)' - PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?PublicKey=([\w-]+)' - - - def detect_key(self, html=None): - html = html or self.retrieve_html() - - m = re.search(self.PUBLICKEY_PATTERN, html) - n = re.search(self.CAPTCHAID_PATTERN, html) - if m and n: - self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId) - self.logDebug("Key: %s | ID: %s" % self.key) - return self.key - else: - self.logWarning("Key or id pattern not found") - return None - - - def challenge(self, key=None, html=None): - PublicKey, CaptchaId = key or self.retrieve_key(html) - - html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", - get={'CaptchaId': CaptchaId, - 'PublicKey': PublicKey}) - try: - challenge = re.search("challenge: '(.+?)',", html).group(1) - server = re.search("server: '(.+?)',", html).group(1) - - except AttributeError: - self.fail(_("AdsCaptcha challenge pattern not found")) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(server, challenge), challenge - - - def result(self, server, challenge): - result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server, - get={'cid': challenge, 'dummy': random.random()}, - cookies=True, - imgtype="jpg") - - self.logDebug("Result: %s" % result) - - return result - - -class ReCaptcha(CaptchaService): - __name__ = "ReCaptcha" - __type__ = "captcha" - __version__ = "0.17" - - __description__ = """ReCaptcha captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com"), - ("zapp-brannigan", "fuerst.reinje@web.de")] - - - KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)' - KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)' - - - def detect_key(self, html=None): - html = html or self.retrieve_html() - - m = re.search(self.KEY_V2_PATTERN, html) or re.search(self.KEY_V1_PATTERN, html) - if m: - self.key = m.group(1).strip() - self.logDebug("Key: %s" % self.key) - return self.key - else: - self.logWarning("Key pattern not found") - return None - - - def challenge(self, key=None, html=None, version=None): - key = key or self.retrieve_key(html) - - if version in (1, 2): - return getattr(self, "_challenge_v%s" % version)(key) - - else: - return self.challenge(key, - version=2 if re.search(self.KEY_V2_PATTERN, html or self.retrieve_html()) else 1) - - - def _challenge_v1(self, key): - html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", - get={'k': key}) - try: - challenge = re.search("challenge : '(.+?)',", html).group(1) - server = re.search("server : '(.+?)',", html).group(1) - - except AttributeError: - self.fail(_("ReCaptcha challenge pattern not found")) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(server, challenge, key) - - - def result(self, server, challenge, key): - self.plugin.req.load("http://www.google.com/recaptcha/api/js/recaptcha.js") - html = self.plugin.req.load("http://www.google.com/recaptcha/api/reload", - get={'c' : challenge, - 'k' : key, - 'reason': "i", - 'type' : "image"}) - - try: - challenge = re.search('\(\'(.+?)\',',html).group(1) - - except AttributeError: - self.fail(_("ReCaptcha second challenge pattern not found")) - - self.logDebug("Second challenge: %s" % challenge) - result = self.plugin.decryptCaptcha("%simage" % server, - get={'c': challenge}, - cookies=True, - forceUser=True, - imgtype="jpg") - - self.logDebug("Result: %s" % result) - - return result, challenge - - - def _collectApiInfo(self): - html = self.plugin.req.load("http://www.google.com/recaptcha/api.js") - a = re.search(r'po.src = \'(.*?)\';', html).group(1) - vers = a.split("/")[5] - - self.logDebug("API version: %s" % vers) - - language = a.split("__")[1].split(".")[0] - - self.logDebug("API language: %s" % language) - - html = self.plugin.req.load("https://apis.google.com/js/api.js") - b = re.search(r'"h":"(.*?)","', html).group(1) - jsh = b.decode('unicode-escape') - - self.logDebug("API jsh-string: %s" % jsh) - - return vers, language, jsh - - - def _prepareTimeAndRpc(self): - self.plugin.req.load("http://www.google.com/recaptcha/api2/demo") - - millis = int(round(time.time() * 1000)) - - self.logDebug("Time: %s" % millis) - - rand = random.randint(1, 99999999) - a = "0.%s" % str(rand * 2147483647) - rpc = int(100000000 * float(a)) - - self.logDebug("Rpc-token: %s" % rpc) - - return millis, rpc - - - def _challenge_v2(self, key, parent=None): - if parent is None: - try: - parent = urlparse.urljoin("http://", urlparse.urlparse(self.plugin.pyfile.url).netloc) - - except Exception: - parent = "" - - botguardstring = "!A" - vers, language, jsh = self._collectApiInfo() - millis, rpc = self._prepareTimeAndRpc() - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/anchor", - get={'k' : key, - 'hl' : language, - 'v' : vers, - 'usegapi' : "1", - 'jsh' : "%s#id=IO_%s" % (jsh, millis), - 'parent' : parent, - 'pfname' : "", - 'rpctoken': rpc}) - - token1 = re.search(r'id="recaptcha-token" value="(.*?)">', html) - self.logDebug("Token #1: %s" % token1.group(1)) - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/frame", - get={'c' : token1.group(1), - 'hl' : language, - 'v' : vers, - 'bg' : botguardstring, - 'k' : key, - 'usegapi': "1", - 'jsh' : jsh}).decode('unicode-escape') - - token2 = re.search(r'"finput","(.*?)",', html) - self.logDebug("Token #2: %s" % token2.group(1)) - - token3 = re.search(r'"rresp","(.*?)",', html) - self.logDebug("Token #3: %s" % token3.group(1)) - - millis_captcha_loading = int(round(time.time() * 1000)) - captcha_response = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload", - get={'c':token3.group(1), 'k':key}, - cookies=True, - forceUser=True) - response = b64encode('{"response":"%s"}' % captcha_response) - - self.logDebug("Result: %s" % response) - - timeToSolve = int(round(time.time() * 1000)) - millis_captcha_loading - timeToSolveMore = timeToSolve + int(float("0." + str(random.randint(1, 99999999))) * 500) - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", - post={'k' : key, - 'c' : token3.group(1), - 'response': response, - 't' : timeToSolve, - 'ct' : timeToSolveMore, - 'bg' : botguardstring}) - - token4 = re.search(r'"uvresp","(.*?)",', html) - self.logDebug("Token #4: %s" % token4.group(1)) - - result = token4.group(1) - - return result, None - - -class SolveMedia(CaptchaService): - __name__ = "SolveMedia" - __type__ = "captcha" - __version__ = "0.13" - - __description__ = """SolveMedia captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' - - - def detect_key(self, html=None): - html = html or self.retrieve_html() - - m = re.search(self.KEY_PATTERN, html) - if m: - self.key = m.group(1).strip() - self.logDebug("Key: %s" % self.key) - return self.key - else: - self.logWarning("Key pattern not found") - return None - - - def challenge(self, key=None, html=None): - key = key or self.retrieve_key(html) - - html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript", - get={'k': key}) - - for i in xrange(1, 11): - try: - magic = re.search(r'name="magic" value="(.+?)"', html).group(1) - - except AttributeError: - self.logWarning("Magic pattern not found") - magic = None - - try: - challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="(.+?)">', - html).group(1) - - except AttributeError: - self.fail(_("SolveMedia challenge pattern not found")) - - else: - self.logDebug("Challenge: %s" % challenge) - - try: - result = self.result("http://api.solvemedia.com/papi/media", challenge) - - except Fail, e: - self.logWarning(e) - self.plugin.invalidCaptcha() - result = None - - html = self.plugin.req.load("http://api.solvemedia.com/papi/verify.noscript", - post={'adcopy_response' : result, - 'k' : key, - 'l' : "en", - 't' : "img", - 's' : "standard", - 'magic' : magic, - 'adcopy_challenge': challenge, - 'ref' : self.plugin.pyfile.url}) - try: - redirect = re.search(r'URL=(.+?)">', html).group(1) - - except AttributeError: - self.fail(_("SolveMedia verify pattern not found")) - - else: - if "error" in html: - self.logWarning("Captcha code was invalid") - self.logDebug("Retry #%d" % i) - html = self.plugin.req.load(redirect) - else: - break - - else: - self.fail(_("SolveMedia max retries exceeded")) - - return result, challenge - - - def result(self, server, challenge): - result = self.plugin.decryptCaptcha(server, - get={'c': challenge}, - cookies=True, - imgtype="gif") - - self.logDebug("Result: %s" % result) - - return result diff --git a/module/plugins/internal/DeadCrypter.py b/module/plugins/internal/DeadCrypter.py index c93447164..a12399501 100644 --- a/module/plugins/internal/DeadCrypter.py +++ b/module/plugins/internal/DeadCrypter.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- from module.plugins.internal.SimpleCrypter import create_getInfo -from module.plugins.Crypter import Crypter as _Crypter +from module.plugins.Crypter import Crypter -class DeadCrypter(_Crypter): +class DeadCrypter(Crypter): __name__ = "DeadCrypter" __type__ = "crypter" __version__ = "0.05" @@ -17,8 +17,8 @@ class DeadCrypter(_Crypter): @classmethod - def apiInfo(cls, url): - api = super(DeadCrypter, cls).apiInfo(url) + def apiInfo(cls, *args, **kwargs): + api = super(DeadCrypter, cls).apiInfo(*args, **kwargs) api['status'] = 1 return api diff --git a/module/plugins/internal/DeadHoster.py b/module/plugins/internal/DeadHoster.py index f159ae5fa..22825e87b 100644 --- a/module/plugins/internal/DeadHoster.py +++ b/module/plugins/internal/DeadHoster.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- from module.plugins.internal.SimpleHoster import create_getInfo -from module.plugins.Hoster import Hoster as _Hoster +from module.plugins.Hoster import Hoster -class DeadHoster(_Hoster): +class DeadHoster(Hoster): __name__ = "DeadHoster" __type__ = "hoster" __version__ = "0.15" @@ -17,8 +17,8 @@ class DeadHoster(_Hoster): @classmethod - def apiInfo(cls, url): - api = super(DeadHoster, cls).apiInfo(url) + def apiInfo(cls, *args, **kwargs): + api = super(DeadHoster, cls).apiInfo(*args, **kwargs) api['status'] = 1 return api diff --git a/module/plugins/internal/Extractor.py b/module/plugins/internal/Extractor.py index 159b65ffe..1a98060d9 100644 --- a/module/plugins/internal/Extractor.py +++ b/module/plugins/internal/Extractor.py @@ -29,8 +29,8 @@ class Extractor: EXTENSIONS = [] - VERSION = "" REPAIR = False + VERSION = "" @classmethod diff --git a/module/plugins/internal/ReCaptcha.py b/module/plugins/internal/ReCaptcha.py new file mode 100644 index 000000000..a9d0f3752 --- /dev/null +++ b/module/plugins/internal/ReCaptcha.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- + +import random +import re +import time +import urlparse + +from base64 import b64encode + +from module.plugins.internal.Captcha import Captcha + + +class ReCaptcha(Captcha): + __name__ = "ReCaptcha" + __type__ = "captcha" + __version__ = "0.17" + + __description__ = """ReCaptcha captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("pyLoad Team", "admin@pyload.org"), + ("Walter Purcaro", "vuolter@gmail.com"), + ("zapp-brannigan", "fuerst.reinje@web.de")] + + + KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)' + KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)' + + + def detect_key(self, html=None): + html = html or self.retrieve_html() + + m = re.search(self.KEY_V2_PATTERN, html) or re.search(self.KEY_V1_PATTERN, html) + if m: + self.key = m.group(1).strip() + self.logDebug("Key: %s" % self.key) + return self.key + else: + self.logWarning("Key pattern not found") + return None + + + def challenge(self, key=None, html=None, version=None): + key = key or self.retrieve_key(html) + + if version in (1, 2): + return getattr(self, "_challenge_v%s" % version)(key) + + else: + return self.challenge(key, + version=2 if re.search(self.KEY_V2_PATTERN, html or self.retrieve_html()) else 1) + + + def _challenge_v1(self, key): + html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", + get={'k': key}) + try: + challenge = re.search("challenge : '(.+?)',", html).group(1) + server = re.search("server : '(.+?)',", html).group(1) + + except AttributeError: + self.fail(_("ReCaptcha challenge pattern not found")) + + self.logDebug("Challenge: %s" % challenge) + + return self.result(server, challenge, key) + + + def result(self, server, challenge, key): + self.plugin.req.load("http://www.google.com/recaptcha/api/js/recaptcha.js") + html = self.plugin.req.load("http://www.google.com/recaptcha/api/reload", + get={'c' : challenge, + 'k' : key, + 'reason': "i", + 'type' : "image"}) + + try: + challenge = re.search('\(\'(.+?)\',',html).group(1) + + except AttributeError: + self.fail(_("ReCaptcha second challenge pattern not found")) + + self.logDebug("Second challenge: %s" % challenge) + result = self.plugin.decryptCaptcha("%simage" % server, + get={'c': challenge}, + cookies=True, + forceUser=True, + imgtype="jpg") + + self.logDebug("Result: %s" % result) + + return result, challenge + + + def _collectApiInfo(self): + html = self.plugin.req.load("http://www.google.com/recaptcha/api.js") + a = re.search(r'po.src = \'(.*?)\';', html).group(1) + vers = a.split("/")[5] + + self.logDebug("API version: %s" % vers) + + language = a.split("__")[1].split(".")[0] + + self.logDebug("API language: %s" % language) + + html = self.plugin.req.load("https://apis.google.com/js/api.js") + b = re.search(r'"h":"(.*?)","', html).group(1) + jsh = b.decode('unicode-escape') + + self.logDebug("API jsh-string: %s" % jsh) + + return vers, language, jsh + + + def _prepareTimeAndRpc(self): + self.plugin.req.load("http://www.google.com/recaptcha/api2/demo") + + millis = int(round(time.time() * 1000)) + + self.logDebug("Time: %s" % millis) + + rand = random.randint(1, 99999999) + a = "0.%s" % str(rand * 2147483647) + rpc = int(100000000 * float(a)) + + self.logDebug("Rpc-token: %s" % rpc) + + return millis, rpc + + + def _challenge_v2(self, key, parent=None): + if parent is None: + try: + parent = urlparse.urljoin("http://", urlparse.urlparse(self.plugin.pyfile.url).netloc) + + except Exception: + parent = "" + + botguardstring = "!A" + vers, language, jsh = self._collectApiInfo() + millis, rpc = self._prepareTimeAndRpc() + + html = self.plugin.req.load("https://www.google.com/recaptcha/api2/anchor", + get={'k' : key, + 'hl' : language, + 'v' : vers, + 'usegapi' : "1", + 'jsh' : "%s#id=IO_%s" % (jsh, millis), + 'parent' : parent, + 'pfname' : "", + 'rpctoken': rpc}) + + token1 = re.search(r'id="recaptcha-token" value="(.*?)">', html) + self.logDebug("Token #1: %s" % token1.group(1)) + + html = self.plugin.req.load("https://www.google.com/recaptcha/api2/frame", + get={'c' : token1.group(1), + 'hl' : language, + 'v' : vers, + 'bg' : botguardstring, + 'k' : key, + 'usegapi': "1", + 'jsh' : jsh}).decode('unicode-escape') + + token2 = re.search(r'"finput","(.*?)",', html) + self.logDebug("Token #2: %s" % token2.group(1)) + + token3 = re.search(r'"rresp","(.*?)",', html) + self.logDebug("Token #3: %s" % token3.group(1)) + + millis_captcha_loading = int(round(time.time() * 1000)) + captcha_response = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload", + get={'c':token3.group(1), 'k':key}, + cookies=True, + forceUser=True) + response = b64encode('{"response":"%s"}' % captcha_response) + + self.logDebug("Result: %s" % response) + + timeToSolve = int(round(time.time() * 1000)) - millis_captcha_loading + timeToSolveMore = timeToSolve + int(float("0." + str(random.randint(1, 99999999))) * 500) + + html = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", + post={'k' : key, + 'c' : token3.group(1), + 'response': response, + 't' : timeToSolve, + 'ct' : timeToSolveMore, + 'bg' : botguardstring}) + + token4 = re.search(r'"uvresp","(.*?)",', html) + self.logDebug("Token #4: %s" % token4.group(1)) + + result = token4.group(1) + + return result, None diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py index b843a28f0..81f977e57 100644 --- a/module/plugins/internal/SimpleCrypter.py +++ b/module/plugins/internal/SimpleCrypter.py @@ -11,7 +11,7 @@ from module.utils import fixup, html_unescape class SimpleCrypter(Crypter, SimpleHoster): __name__ = "SimpleCrypter" __type__ = "crypter" - __version__ = "0.46" + __version__ = "0.49" __pattern__ = r'^unmatchable$' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides core.config['general']['folder_per_package'] @@ -55,15 +55,6 @@ class SimpleCrypter(Crypter, SimpleHoster): LINK_PATTERN = None - NAME_REPLACEMENTS = [("&#?\w+;", fixup)] - URL_REPLACEMENTS = [] - - TEXT_ENCODING = False #: Set to True or encoding name if encoding in http header is not correct - COOKIES = True #: or False or list of tuples [(domain, name, value)] - - LOGIN_ACCOUNT = False - LOGIN_PREMIUM = False - #@TODO: Remove in 0.4.10 def init(self): @@ -83,6 +74,7 @@ class SimpleCrypter(Crypter, SimpleHoster): self.info = {} self.html = "" + self.link = "" #@TODO: Move to hoster class in 0.4.10 self.links = [] #@TODO: Move to hoster class in 0.4.10 if self.LOGIN_PREMIUM and not self.premium: @@ -99,18 +91,34 @@ class SimpleCrypter(Crypter, SimpleHoster): self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS) + def handleDirect(self, pyfile): + while True: + header = self.load(self.link or pyfile.url, just_header=True, decode=True) + if 'location' in header and header['location']: + self.link = header['location'] + else: + break + + def decrypt(self, pyfile): self.prepare() - self.preload() - self.checkInfo() + self.logDebug("Looking for link redirect...") + self.handleDirect(pyfile) + + if self.link: + self.urls = [self.link] + + else: + self.preload() + self.checkInfo() - self.links = self.getLinks() + self.links = self.getLinks() - if hasattr(self, 'PAGES_PATTERN') and hasattr(self, 'loadPage'): - self.handlePages(pyfile) + if hasattr(self, 'PAGES_PATTERN') and hasattr(self, 'loadPage'): + self.handlePages(pyfile) - self.logDebug("Package has %d links" % len(self.links)) + self.logDebug("Package has %d links" % len(self.links)) if self.links: self.packages = [(self.info['name'], self.links, self.info['folder'])] @@ -155,7 +163,7 @@ class SimpleCrypter(Crypter, SimpleHoster): links = [urlparse.urljoin(baseurl, link) if not urlparse.urlparse(link).scheme else link \ for link in re.findall(self.LINK_PATTERN, self.html)] - return [html_unescape(l.strip().decode('unicode-escape')) for l in links] + return [html_unescape(l.decode('unicode-escape').strip()) for l in links] def handlePages(self, pyfile): diff --git a/module/plugins/internal/SimpleDereferer.py b/module/plugins/internal/SimpleDereferer.py deleted file mode 100644 index 1f04ab1c6..000000000 --- a/module/plugins/internal/SimpleDereferer.py +++ /dev/null @@ -1,101 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -import urllib - -from module.plugins.Crypter import Crypter -from module.plugins.internal.SimpleHoster import create_getInfo, set_cookies -from module.utils import html_unescape - - -class SimpleDereferer(Crypter): - __name__ = "SimpleDereferer" - __type__ = "crypter" - __version__ = "0.13" - - __pattern__ = r'^unmatchable$' - __config__ = [] #@TODO: Remove in 0.4.10 - - __description__ = """Simple dereferer plugin""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - """ - Following patterns should be defined by each crypter: - - LINK_PATTERN: Regex to catch the redirect url in group(1) - example: LINK_PATTERN = r'<div class="link"><a href="(.+?)"' - - OFFLINE_PATTERN: (optional) Checks if the page is unreachable - example: OFFLINE_PATTERN = r'File (deleted|not found)' - - TEMP_OFFLINE_PATTERN: (optional) Checks if the page is temporarily unreachable - example: TEMP_OFFLINE_PATTERN = r'Server maintainance' - - - You can override the getLinks method if you need a more sophisticated way to extract the redirect url. - """ - - LINK_PATTERN = None - - TEXT_ENCODING = False - COOKIES = True - - - def handleDirect(self, pyfile): - header = self.load(pyfile.url, just_header=True, decode=True) - if 'location' in header and header['location']: - self.link = header['location'] - - - def decrypt(self, pyfile): - self.handleDirect(pyfile) - - if not self.link: - try: - self.link = urllib.unquote(re.match(self.__pattern__, pyfile.url).group('LINK')) - - except AttributeError: - self.prepare() - self.preload() - self.checkStatus() - - self.link = self.getLink() - - if self.link: - self.urls = [self.link] - - elif not self.urls and not self.packages: #@TODO: Remove in 0.4.10 - self.fail(_("No link grabbed")) - - - def prepare(self): - self.info = {} - self.html = "" - self.link = "" #@TODO: Move to hoster class in 0.4.10 - - self.req.setOption("timeout", 120) - - if isinstance(self.COOKIES, list): - set_cookies(self.req.cj, self.COOKIES) - - - def preload(self): - self.html = self.load(self.pyfile.url, cookies=bool(self.COOKIES), decode=not self.TEXT_ENCODING) - - if isinstance(self.TEXT_ENCODING, basestring): - self.html = unicode(self.html, self.TEXT_ENCODING) - - - def checkStatus(self): - if hasattr(self, "OFFLINE_PATTERN") and re.search(self.OFFLINE_PATTERN, self.html): - self.offline() - - elif hasattr(self, "TEMP_OFFLINE_PATTERN") and re.search(self.TEMP_OFFLINE_PATTERN, self.html): - self.tempOffline() - - - def getLink(self): - link = re.search(self.LINK_PATTERN, self.html).group(1) - return html_unescape(link.strip().decode('unicode-escape')) #@TODO: Move this check to plugin `load` method in 0.4.10 diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py index 1d44a6642..33e7d3674 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -239,7 +239,7 @@ def secondsToMidnight(gmt=0): class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "1.50" + __version__ = "1.53" __pattern__ = r'^unmatchable$' __config__ = [("use_premium", "bool", "Use premium account if available" , True), @@ -308,13 +308,15 @@ class SimpleHoster(Hoster): SIZE_REPLACEMENTS = [] URL_REPLACEMENTS = [] - TEXT_ENCODING = False #: Set to True or encoding name if encoding value in http header is not correct - COOKIES = True #: or False or list of tuples [(domain, name, value)] CHECK_TRAFFIC = False #: Set to True to force checking traffic left for premium account + COOKIES = True #: or False or list of tuples [(domain, name, value)] DIRECT_LINK = None #: Set to True to looking for direct link (as defined in handleDirect method), set to None to do it if self.account is True else False - MULTI_HOSTER = False #: Set to True to leech other hoster link (as defined in handleMulti method) - LOGIN_ACCOUNT = False #: Set to True to require account login DISPOSITION = True #: Set to True to use any content-disposition value in http header as file name + LOGIN_ACCOUNT = False #: Set to True to require account login + LOGIN_PREMIUM = False #: Set to True to require premium account login + MULTI_HOSTER = False #: Set to True to leech other hoster link (as defined in handleMulti method) + TEXT_ENCODING = False #: Set to True or encoding name if encoding value in http header is not correct + directLink = getFileURL #@TODO: Remove in 0.4.10 @@ -430,6 +432,9 @@ class SimpleHoster(Hoster): if not self.getConfig('use_premium', True): self.retryFree() + if self.LOGIN_PREMIUM and not self.premium: + self.fail(_("Required premium account not found")) + if self.LOGIN_ACCOUNT and not self.account: self.fail(_("Required account not found")) @@ -474,7 +479,7 @@ class SimpleHoster(Hoster): if not self.link and not self.lastDownload: self.MULTI_HOSTER = False - self.retry(1, reason="Multi hoster fails") + self.retry(1, reason=_("Multi hoster fails")) if not self.link and not self.lastDownload: self.preload() @@ -511,7 +516,7 @@ class SimpleHoster(Hoster): self.correctCaptcha() - link = html_unescape(link.strip().decode('unicode-escape')) #@TODO: Move this check to plugin `load` method in 0.4.10 + link = html_unescape(link.decode('unicode-escape').strip()) #@TODO: Move this check to plugin `load` method in 0.4.10 if not urlparse.urlparse(link).scheme: url_p = urlparse.urlparse(self.pyfile.url) @@ -625,6 +630,7 @@ class SimpleHoster(Hoster): elif re.search('captcha|code', errmsg, re.I): self.invalidCaptcha() + self.retry(10, reason=_("Wrong captcha")) elif re.search('countdown|expired', errmsg, re.I): self.retry(wait_time=60, reason=_("Link expired")) @@ -635,9 +641,14 @@ class SimpleHoster(Hoster): elif re.search('up to', errmsg, re.I): self.fail(_("File too large for free download")) - elif re.search('offline|delet|remov|not (found|available)', errmsg, re.I): + elif re.search('offline|delet|remov|not? (found|(longer)? available)', errmsg, re.I): self.offline() + elif re.search('filename', errmsg, re.I): + url_p = urlparse.urlparse(self.pyfile.url) + self.pyfile.url = "%s://%s/%s" % (url_p.scheme, url_p.netloc, url_p.path.strip('/').split('/')[0]) + self.retry(1, reason=_("Wrong url")) + elif re.search('premium', errmsg, re.I): self.fail(_("File can be downloaded by premium users only")) diff --git a/module/plugins/internal/SolveMedia.py b/module/plugins/internal/SolveMedia.py new file mode 100644 index 000000000..7f5de51e1 --- /dev/null +++ b/module/plugins/internal/SolveMedia.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.Plugin import Fail +from module.plugins.internal.Captcha import Captcha + + +class SolveMedia(Captcha): + __name__ = "SolveMedia" + __type__ = "captcha" + __version__ = "0.13" + + __description__ = """SolveMedia captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("pyLoad Team", "admin@pyload.org")] + + + KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' + + + def detect_key(self, html=None): + html = html or self.retrieve_html() + + m = re.search(self.KEY_PATTERN, html) + if m: + self.key = m.group(1).strip() + self.logDebug("Key: %s" % self.key) + return self.key + else: + self.logWarning("Key pattern not found") + return None + + + def challenge(self, key=None, html=None): + key = key or self.retrieve_key(html) + + html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript", + get={'k': key}) + + for i in xrange(1, 11): + try: + magic = re.search(r'name="magic" value="(.+?)"', html).group(1) + + except AttributeError: + self.logWarning("Magic pattern not found") + magic = None + + try: + challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="(.+?)">', + html).group(1) + + except AttributeError: + self.fail(_("SolveMedia challenge pattern not found")) + + else: + self.logDebug("Challenge: %s" % challenge) + + try: + result = self.result("http://api.solvemedia.com/papi/media", challenge) + + except Fail, e: + self.logWarning(e) + self.plugin.invalidCaptcha() + result = None + + html = self.plugin.req.load("http://api.solvemedia.com/papi/verify.noscript", + post={'adcopy_response' : result, + 'k' : key, + 'l' : "en", + 't' : "img", + 's' : "standard", + 'magic' : magic, + 'adcopy_challenge': challenge, + 'ref' : self.plugin.pyfile.url}) + try: + redirect = re.search(r'URL=(.+?)">', html).group(1) + + except AttributeError: + self.fail(_("SolveMedia verify pattern not found")) + + else: + if "error" in html: + self.logWarning("Captcha code was invalid") + self.logDebug("Retry #%d" % i) + html = self.plugin.req.load(redirect) + else: + break + + else: + self.fail(_("SolveMedia max retries exceeded")) + + return result, challenge + + + def result(self, server, challenge): + result = self.plugin.decryptCaptcha(server, + get={'c': challenge}, + cookies=True, + imgtype="gif") + + self.logDebug("Result: %s" % result) + + return result diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index 8d3fec370..4c18a0e35 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -19,8 +19,8 @@ class UnZip(Extractor): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - EXTENSIONS = [".zip", ".zip64"] VERSION ="(python %s.%s.%s)" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]) + EXTENSIONS = [".zip", ".zip64"] @classmethod diff --git a/module/plugins/internal/XFSCrypter.py b/module/plugins/internal/XFSCrypter.py index 80eff53ea..8b333b45c 100644 --- a/module/plugins/internal/XFSCrypter.py +++ b/module/plugins/internal/XFSCrypter.py @@ -19,8 +19,8 @@ class XFSCrypter(SimpleCrypter): URL_REPLACEMENTS = [(r'&?per_page=\d+', ""), (r'[?/&]+$', ""), (r'(.+/[^?]+)$', r'\1?'), (r'$', r'&per_page=10000')] - LINK_PATTERN = r'<(?:td|TD).*?>\s*(?:<.+>\s*)?<a href="(.+?)".*?>.+?(?:</a>)?\s*(?:<.+>\s*)?</(?:td|TD)>' NAME_PATTERN = r'<[Tt]itle>.*?\: (?P<N>.+) folder</[Tt]itle>' + LINK_PATTERN = r'<(?:td|TD).*?>\s*(?:<.+>\s*)?<a href="(.+?)".*?>.+?(?:</a>)?\s*(?:<.+>\s*)?</(?:td|TD)>' OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)' TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)' diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index e2818886c..e0fd8fa8d 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -5,7 +5,8 @@ import random import re import urlparse -from module.plugins.internal.CaptchaService import ReCaptcha, SolveMedia +from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.internal.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, secondsToMidnight from module.utils import html_unescape @@ -13,7 +14,7 @@ from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.51" + __version__ = "0.53" __pattern__ = r'^unmatchable$' @@ -26,14 +27,12 @@ class XFSHoster(SimpleHoster): HOSTER_DOMAIN = None - TEXT_ENCODING = False - DIRECT_LINK = None - MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy... + MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy... NAME_PATTERN = r'(Filename[ ]*:[ ]*</b>(</td><td nowrap>)?|name="fname"[ ]+value="|<[\w^_]+ class="(file)?name">)\s*(?P<N>.+?)(\s*<|")' SIZE_PATTERN = r'(Size[ ]*:[ ]*</b>(</td><td>)?|File:.*>|</font>\s*\(|<[\w^_]+ class="size">)\s*(?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)' - OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)' + OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed|no longer available)' TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)' WAIT_PATTERN = r'<span id="countdown_str".*>(\d+)</span>|id="countdown" value=".*?(\d+).*?"' |