diff options
author | lazlev <lazlev@yopmail.com> | 2015-08-09 00:50:54 +0200 |
---|---|---|
committer | lazlev <lazlev@yopmail.com> | 2015-08-09 00:50:54 +0200 |
commit | b0ef3f1673e1930916604bb1264ca3a38414bc8d (patch) | |
tree | c97936e4d2a4cd6eb1072c65c8a08a7d18816b18 /module | |
parent | [XFileSharingPro][XFileSharingProFolder] Added default __pattern__ (diff) | |
parent | Fix https://github.com/pyload/pyload/issues/1707 (diff) | |
download | pyload-b0ef3f1673e1930916604bb1264ca3a38414bc8d.tar.xz |
Merge pull request #1 from pyload/stable
sync with stable
Diffstat (limited to 'module')
496 files changed, 9622 insertions, 7506 deletions
diff --git a/module/plugins/Account.py b/module/plugins/Account.py deleted file mode 100644 index c147404e0..000000000 --- a/module/plugins/Account.py +++ /dev/null @@ -1,292 +0,0 @@ -# -*- coding: utf-8 -*- - -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from random import choice -from time import time -from traceback import print_exc -from threading import RLock - -from Plugin import Base -from module.utils import compare_time, parseFileSize, lock - -class WrongPassword(Exception): - pass - - -class Account(Base): - """ - Base class for every Account plugin. - Just overwrite `login` and cookies will be stored and account becomes accessible in\ - associated hoster plugin. Plugin should also provide `loadAccountInfo` - """ - __name__ = "Account" - __version__ = "0.2" - __type__ = "account" - __description__ = """Account Plugin""" - __author_name__ = ("mkaay") - __author_mail__ = ("mkaay@mkaay.de") - - #: after that time [in minutes] pyload will relogin the account - login_timeout = 600 - #: account data will be reloaded after this time - info_threshold = 600 - - - def __init__(self, manager, accounts): - Base.__init__(self, manager.core) - - self.manager = manager - self.accounts = {} - self.infos = {} # cache for account information - self.lock = RLock() - - self.timestamps = {} - self.setAccounts(accounts) - self.init() - - def init(self): - pass - - def login(self, user, data, req): - """login into account, the cookies will be saved so user can be recognized - - :param user: loginname - :param data: data dictionary - :param req: `Request` instance - """ - pass - - @lock - def _login(self, user, data): - # set timestamp for login - self.timestamps[user] = time() - - req = self.getAccountRequest(user) - try: - self.login(user, data, req) - except WrongPassword: - self.logWarning( - _("Could not login with account %(user)s | %(msg)s") % {"user": user - , "msg": _("Wrong Password")}) - data["valid"] = False - - except Exception, e: - self.logWarning( - _("Could not login with account %(user)s | %(msg)s") % {"user": user - , "msg": e}) - data["valid"] = False - if self.core.debug: - print_exc() - finally: - if req: req.close() - - def relogin(self, user): - req = self.getAccountRequest(user) - if req: - req.cj.clear() - req.close() - if user in self.infos: - del self.infos[user] #delete old information - - self._login(user, self.accounts[user]) - - def setAccounts(self, accounts): - self.accounts = accounts - for user, data in self.accounts.iteritems(): - self._login(user, data) - self.infos[user] = {} - - def updateAccounts(self, user, password=None, options={}): - """ updates account and return true if anything changed """ - - if user in self.accounts: - self.accounts[user]["valid"] = True #do not remove or accounts will not login - if password: - self.accounts[user]["password"] = password - self.relogin(user) - return True - if options: - before = self.accounts[user]["options"] - self.accounts[user]["options"].update(options) - return self.accounts[user]["options"] != before - else: - self.accounts[user] = {"password": password, "options": options, "valid": True} - self._login(user, self.accounts[user]) - return True - - def removeAccount(self, user): - if user in self.accounts: - del self.accounts[user] - if user in self.infos: - del self.infos[user] - if user in self.timestamps: - del self.timestamps[user] - - @lock - def getAccountInfo(self, name, force=False): - """retrieve account infos for an user, do **not** overwrite this method!\\ - just use it to retrieve infos in hoster plugins. see `loadAccountInfo` - - :param name: username - :param force: reloads cached account information - :return: dictionary with information - """ - data = Account.loadAccountInfo(self, name) - - if force or name not in self.infos: - self.logDebug("Get Account Info for %s" % name) - req = self.getAccountRequest(name) - - try: - infos = self.loadAccountInfo(name, req) - if not type(infos) == dict: - raise Exception("Wrong return format") - except Exception, e: - infos = {"error": str(e)} - - if req: req.close() - - self.logDebug("Account Info: %s" % str(infos)) - - infos["timestamp"] = time() - self.infos[name] = infos - elif "timestamp" in self.infos[name] and self.infos[name][ - "timestamp"] + self.info_threshold * 60 < time(): - self.logDebug("Reached timeout for account data") - self.scheduleRefresh(name) - - data.update(self.infos[name]) - return data - - def isPremium(self, user): - info = self.getAccountInfo(user) - return info["premium"] - - def loadAccountInfo(self, name, req=None): - """this should be overwritten in account plugin,\ - and retrieving account information for user - - :param name: - :param req: `Request` instance - :return: - """ - return { - "validuntil": None, # -1 for unlimited - "login": name, - #"password": self.accounts[name]["password"], #@XXX: security - "options": self.accounts[name]["options"], - "valid": self.accounts[name]["valid"], - "trafficleft": None, # in kb, -1 for unlimited - "maxtraffic": None, - "premium": True, #useful for free accounts - "timestamp": 0, #time this info was retrieved - "type": self.__name__, - } - - def getAllAccounts(self, force=False): - return [self.getAccountInfo(user, force) for user, data in self.accounts.iteritems()] - - def getAccountRequest(self, user=None): - if not user: - user, data = self.selectAccount() - if not user: - return None - - req = self.core.requestFactory.getRequest(self.__name__, user) - return req - - def getAccountCookies(self, user=None): - if not user: - user, data = self.selectAccount() - if not user: - return None - - cj = self.core.requestFactory.getCookieJar(self.__name__, user) - return cj - - def getAccountData(self, user): - return self.accounts[user] - - def selectAccount(self): - """ returns an valid account name and data""" - usable = [] - for user, data in self.accounts.iteritems(): - if not data["valid"]: continue - - if "time" in data["options"] and data["options"]["time"]: - time_data = "" - try: - time_data = data["options"]["time"][0] - start, end = time_data.split("-") - if not compare_time(start.split(":"), end.split(":")): - continue - except: - self.logWarning(_("Your Time %s has wrong format, use: 1:22-3:44") % time_data) - - if user in self.infos: - if "validuntil" in self.infos[user]: - if self.infos[user]["validuntil"] > 0 and time() > self.infos[user]["validuntil"]: - continue - if "trafficleft" in self.infos[user]: - if self.infos[user]["trafficleft"] == 0: - continue - - usable.append((user, data)) - - if not usable: return None, None - return choice(usable) - - def canUse(self): - return False if self.selectAccount() == (None, None) else True - - def parseTraffic(self, string): #returns kbyte - return parseFileSize(string) / 1024 - - def wrongPassword(self): - raise WrongPassword - - def empty(self, user): - if user in self.infos: - self.logWarning(_("Account %s has not enough traffic, checking again in 30min") % user) - - self.infos[user].update({"trafficleft": 0}) - self.scheduleRefresh(user, 30 * 60) - - def expired(self, user): - if user in self.infos: - self.logWarning(_("Account %s is expired, checking again in 1h") % user) - - self.infos[user].update({"validuntil": time() - 1}) - self.scheduleRefresh(user, 60 * 60) - - def scheduleRefresh(self, user, time=0, force=True): - """ add task to refresh account info to sheduler """ - self.logDebug("Scheduled Account refresh for %s in %s seconds." % (user, time)) - self.core.scheduler.addJob(time, self.getAccountInfo, [user, force]) - - @lock - def checkLogin(self, user): - """ checks if user is still logged in """ - if user in self.timestamps: - if self.timestamps[user] + self.login_timeout * 60 < time(): - self.logDebug("Reached login timeout for %s" % user) - self.relogin(user) - return False - - return True diff --git a/module/plugins/AccountManager.py b/module/plugins/AccountManager.py index fc521d36c..094641c76 100644 --- a/module/plugins/AccountManager.py +++ b/module/plugins/AccountManager.py @@ -125,10 +125,10 @@ class AccountManager(): f.write("\n") f.write(plugin+":\n") - for name,data in accounts.iteritems(): - f.write("\n\t%s:%s\n" % (name,data["password"]) ) - if data["options"]: - for option, values in data["options"].iteritems(): + for name, data in accounts.iteritems(): + f.write("\n\t%s:%s\n" % (name, data['password']) ) + if data['options']: + for option, values in data['options'].iteritems(): f.write("\t@%s %s\n" % (option, " ".join(values))) f.close() diff --git a/module/plugins/Container.py b/module/plugins/Container.py deleted file mode 100644 index c233d3710..000000000 --- a/module/plugins/Container.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- - -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from module.plugins.Crypter import Crypter - -from os.path import join, exists, basename -from os import remove -import re - -class Container(Crypter): - __name__ = "Container" - __version__ = "0.1" - __pattern__ = None - __type__ = "container" - __description__ = """Base container plugin""" - __author_name__ = ("mkaay") - __author_mail__ = ("mkaay@mkaay.de") - - - def preprocessing(self, thread): - """prepare""" - - self.setup() - self.thread = thread - - self.loadToDisk() - - self.decrypt(self.pyfile) - self.deleteTmp() - - self.createPackages() - - - def loadToDisk(self): - """loads container to disk if its stored remotely and overwrite url, - or check existent on several places at disk""" - - if self.pyfile.url.startswith("http"): - self.pyfile.name = re.findall("([^\/=]+)", self.pyfile.url)[-1] - content = self.load(self.pyfile.url) - self.pyfile.url = join(self.config["general"]["download_folder"], self.pyfile.name) - f = open(self.pyfile.url, "wb" ) - f.write(content) - f.close() - - else: - self.pyfile.name = basename(self.pyfile.url) - if not exists(self.pyfile.url): - if exists(join(pypath, self.pyfile.url)): - self.pyfile.url = join(pypath, self.pyfile.url) - else: - self.fail(_("File not exists.")) - - - def deleteTmp(self): - if self.pyfile.name.startswith("tmp_"): - remove(self.pyfile.url) - - diff --git a/module/plugins/Crypter.py b/module/plugins/Crypter.py deleted file mode 100644 index d1549fe80..000000000 --- a/module/plugins/Crypter.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- - -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from module.plugins.Plugin import Plugin - -class Crypter(Plugin): - __name__ = "Crypter" - __version__ = "0.1" - __pattern__ = None - __type__ = "container" - __description__ = """Base crypter plugin""" - __author_name__ = ("mkaay") - __author_mail__ = ("mkaay@mkaay.de") - - def __init__(self, pyfile): - Plugin.__init__(self, pyfile) - - #: Put all packages here. It's a list of tuples like: ( name, [list of links], folder ) - self.packages = [] - - #: List of urls, pyLoad will generate packagenames - self.urls = [] - - self.multiDL = True - self.limitDL = 0 - - - def preprocessing(self, thread): - """prepare""" - self.setup() - self.thread = thread - - self.decrypt(self.pyfile) - - self.createPackages() - - - def decrypt(self, pyfile): - raise NotImplementedError - - def createPackages(self): - """ create new packages from self.packages """ - for pack in self.packages: - - self.log.debug("Parsed package %(name)s with %(len)d links" % { "name" : pack[0], "len" : len(pack[1]) } ) - - links = [x.decode("utf-8") for x in pack[1]] - - pid = self.core.api.addPackage(pack[0], links, self.pyfile.package().queue) - - if self.pyfile.package().password: - self.core.api.setPackageData(pid, {"password": self.pyfile.package().password}) - - if self.urls: - self.core.api.generateAndAddPackages(self.urls) - diff --git a/module/plugins/Hook.py b/module/plugins/Hook.py deleted file mode 100644 index 5efd08bae..000000000 --- a/module/plugins/Hook.py +++ /dev/null @@ -1,161 +0,0 @@ -# -*- coding: utf-8 -*- - -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay - @interface-version: 0.2 -""" - -from traceback import print_exc - -from Plugin import Base - -class Expose(object): - """ used for decoration to declare rpc services """ - - def __new__(cls, f, *args, **kwargs): - hookManager.addRPC(f.__module__, f.func_name, f.func_doc) - return f - -def threaded(f): - def run(*args,**kwargs): - hookManager.startThread(f, *args, **kwargs) - return run - -class Hook(Base): - """ - Base class for hook plugins. - """ - __name__ = "Hook" - __version__ = "0.2" - __type__ = "hook" - __threaded__ = [] - __config__ = [ ("name", "type", "desc" , "default") ] - __description__ = """interface for hook""" - __author_name__ = ("mkaay", "RaNaN") - __author_mail__ = ("mkaay@mkaay.de", "RaNaN@pyload.org") - - #: automatically register event listeners for functions, attribute will be deleted dont use it yourself - event_map = None - - # Alternative to event_map - #: List of events the plugin can handle, name the functions exactly like eventname. - event_list = None # dont make duplicate entries in event_map - - - #: periodic call interval in secondc - interval = 60 - - def __init__(self, core, manager): - Base.__init__(self, core) - - #: Provide information in dict here, usable by API `getInfo` - self.info = None - - #: Callback of periodical job task, used by hookmanager - self.cb = None - - #: `HookManager` - self.manager = manager - - #register events - if self.event_map: - for event, funcs in self.event_map.iteritems(): - if type(funcs) in (list, tuple): - for f in funcs: - self.manager.addEvent(event, getattr(self,f)) - else: - self.manager.addEvent(event, getattr(self,funcs)) - - #delete for various reasons - self.event_map = None - - if self.event_list: - for f in self.event_list: - self.manager.addEvent(f, getattr(self,f)) - - self.event_list = None - - self.initPeriodical() - self.setup() - - def initPeriodical(self): - if self.interval >=1: - self.cb = self.core.scheduler.addJob(0, self._periodical, threaded=False) - - def _periodical(self): - try: - if self.isActivated(): self.periodical() - except Exception, e: - self.core.log.error(_("Error executing hooks: %s") % str(e)) - if self.core.debug: - print_exc() - - self.cb = self.core.scheduler.addJob(self.interval, self._periodical, threaded=False) - - - def __repr__(self): - return "<Hook %s>" % self.__name__ - - def setup(self): - """ more init stuff if needed """ - pass - - def unload(self): - """ called when hook was deactivated """ - pass - - def isActivated(self): - """ checks if hook is activated""" - return self.config.getPlugin(self.__name__, "activated") - - - #event methods - overwrite these if needed - def coreReady(self): - pass - - def coreExiting(self): - pass - - def downloadPreparing(self, pyfile): - pass - - def downloadFinished(self, pyfile): - pass - - def downloadFailed(self, pyfile): - pass - - def packageFinished(self, pypack): - pass - - def beforeReconnecting(self, ip): - pass - - def afterReconnecting(self, ip): - pass - - def periodical(self): - pass - - def newCaptchaTask(self, task): - """ new captcha task for the plugin, it MUST set the handler and timeout or will be ignored """ - pass - - def captchaCorrect(self, task): - pass - - def captchaInvalid(self, task): - pass
\ No newline at end of file diff --git a/module/plugins/Hoster.py b/module/plugins/Hoster.py deleted file mode 100644 index 814a70949..000000000 --- a/module/plugins/Hoster.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- - -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from module.plugins.Plugin import Plugin - -def getInfo(self): - #result = [ .. (name, size, status, url) .. ] - return - -class Hoster(Plugin): - __name__ = "Hoster" - __version__ = "0.1" - __pattern__ = None - __type__ = "hoster" - __description__ = """Base hoster plugin""" - __author_name__ = ("mkaay") - __author_mail__ = ("mkaay@mkaay.de") diff --git a/module/plugins/accounts/AlldebridCom.py b/module/plugins/accounts/AlldebridCom.py index f9c1f2ca6..6a2f09c9c 100644 --- a/module/plugins/accounts/AlldebridCom.py +++ b/module/plugins/accounts/AlldebridCom.py @@ -4,60 +4,63 @@ import re import time import xml.dom.minidom as dom -from BeautifulSoup import BeautifulSoup +import BeautifulSoup -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class AlldebridCom(Account): __name__ = "AlldebridCom" __type__ = "account" - __version__ = "0.23" + __version__ = "0.26" + __status__ = "testing" __description__ = """AllDebrid.com account plugin""" __license__ = "GPLv3" __authors__ = [("Andy Voigt", "spamsales@online.de")] - def loadAccountInfo(self, user, req): - data = self.getAccountData(user) - html = req.load("http://www.alldebrid.com/account/") - soup = BeautifulSoup(html) + def parse_info(self, user, password, data, req): + data = self.get_data(user) + html = self.load("http://www.alldebrid.com/account/") + soup = BeautifulSoup.BeautifulSoup(html) - #Try to parse expiration date directly from the control panel page (better accuracy) + #: Try to parse expiration date directly from the control panel page (better accuracy) try: time_text = soup.find('div', attrs={'class': 'remaining_time_text'}).strong.string - self.logDebug("Account expires in: %s" % time_text) + self.log_debug("Account expires in: %s" % time_text) p = re.compile('\d+') exp_data = p.findall(time_text) exp_time = time.time() + int(exp_data[0]) * 24 * 60 * 60 + int( exp_data[1]) * 60 * 60 + (int(exp_data[2]) - 1) * 60 - #Get expiration date from API + #: Get expiration date from API except Exception: - data = self.getAccountData(user) - html = req.load("http://www.alldebrid.com/api.php", - get={'action': "info_user", 'login': user, 'pw': data['password']}) + data = self.get_data(user) + html = self.load("https://www.alldebrid.com/api.php", + get={'action': "info_user", + 'login' : user, + 'pw' : password}) - self.logDebug(html) + self.log_debug(html) xml = dom.parseString(html) exp_time = time.time() + int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue) * 24 * 60 * 60 - account_info = {"validuntil": exp_time, "trafficleft": -1} - return account_info + return {'validuntil' : exp_time, + 'trafficleft': -1 , + 'premium' : True } - def login(self, user, data, req): - html = req.load("http://www.alldebrid.com/register/", - get={'action' : "login", - 'login_login' : user, - 'login_password': data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://www.alldebrid.com/register/", + get={'action' : "login", + 'login_login' : user, + 'login_password': password}) if "This login doesn't exist" in html \ or "The password is not valid" in html \ or "Invalid captcha" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/AniStreamCom.py b/module/plugins/accounts/AniStreamCom.py new file mode 100644 index 000000000..53ca1d5b8 --- /dev/null +++ b/module/plugins/accounts/AniStreamCom.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSAccount import XFSAccount + + +class AniStreamCom(XFSAccount): + __name__ = "AniStreamCom" + __type__ = "account" + __version__ = "0.01" + __status__ = "testing" + + __description__ = """Ani-Stream.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + HOSTER_DOMAIN = "ani-stream.com" diff --git a/module/plugins/accounts/BackinNet.py b/module/plugins/accounts/BackinNet.py index 46c8d7ac5..58939c13a 100644 --- a/module/plugins/accounts/BackinNet.py +++ b/module/plugins/accounts/BackinNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class BackinNet(XFSAccount): __name__ = "BackinNet" __type__ = "account" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __description__ = """Backin.net account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/BitshareCom.py b/module/plugins/accounts/BitshareCom.py index 00e546f6d..280f008b2 100644 --- a/module/plugins/accounts/BitshareCom.py +++ b/module/plugins/accounts/BitshareCom.py @@ -1,34 +1,36 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class BitshareCom(Account): __name__ = "BitshareCom" __type__ = "account" - __version__ = "0.13" + __version__ = "0.15" + __status__ = "testing" __description__ = """Bitshare account plugin""" __license__ = "GPLv3" __authors__ = [("Paul King", None)] - def loadAccountInfo(self, user, req): - html = req.load("http://bitshare.com/mysettings.html") + def parse_info(self, user, password, data, req): + html = self.load("http://bitshare.com/mysettings.html") if "\"http://bitshare.com/myupgrade.html\">Free" in html: - return {"validuntil": -1, "trafficleft": -1, "premium": False} + return {'validuntil': -1, 'trafficleft': -1, 'premium': False} if not '<input type="checkbox" name="directdownload" checked="checked" />' in html: - self.logWarning(_("Activate direct Download in your Bitshare Account")) + self.log_warning(_("Activate direct Download in your Bitshare Account")) - return {"validuntil": -1, "trafficleft": -1, "premium": True} + return {'validuntil': -1, 'trafficleft': -1, 'premium': True} - def login(self, user, data, req): - html = req.load("http://bitshare.com/login.html", - post={"user": user, "password": data['password'], "submit": "Login"}, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://bitshare.com/login.html", + post={'user' : user, + 'password': password, + 'submit' : "Login"}) if "login" in req.lastEffectiveURL: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/CatShareNet.py b/module/plugins/accounts/CatShareNet.py index bb42f443f..92f1cb27e 100644 --- a/module/plugins/accounts/CatShareNet.py +++ b/module/plugins/accounts/CatShareNet.py @@ -3,15 +3,16 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class CatShareNet(Account): __name__ = "CatShareNet" __type__ = "account" - __version__ = "0.05" + __version__ = "0.08" + __status__ = "testing" - __description__ = """CatShareNet account plugin""" + __description__ = """Catshare.net account plugin""" __license__ = "GPLv3" __authors__ = [("prOq", None)] @@ -21,19 +22,19 @@ class CatShareNet(Account): TRAFFIC_LEFT_PATTERN = r'<a href="/premium">([0-9.]+ [kMG]B)' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): premium = False validuntil = -1 trafficleft = -1 - html = req.load("http://catshare.net/", decode=True) + html = self.load("http://catshare.net/") if re.search(self.PREMIUM_PATTERN, html): premium = True try: expiredate = re.search(self.VALID_UNTIL_PATTERN, html).group(1) - self.logDebug("Expire date: " + expiredate) + self.log_debug("Expire date: " + expiredate) validuntil = time.mktime(time.strptime(expiredate, "%Y-%m-%d %H:%M:%S")) @@ -41,7 +42,7 @@ class CatShareNet(Account): pass try: - trafficleft = self.parseTraffic(re.search(self.TRAFFIC_LEFT_PATTERN, html).group(1)) + trafficleft = self.parse_traffic(re.search(self.TRAFFIC_LEFT_PATTERN, html).group(1)) except Exception: pass @@ -49,13 +50,12 @@ class CatShareNet(Account): return {'premium': premium, 'trafficleft': trafficleft, 'validuntil': validuntil} - def login(self, user, data, req): - html = req.load("http://catshare.net/login", - post={'user_email': user, - 'user_password': data['password'], - 'remindPassword': 0, - 'user[submit]': "Login"}, - decode=True) + def login(self, user, password, data, req): + html = self.load("http://catshare.net/login", #@TODO: Revert to `https` in 0.4.10 + post={'user_email' : user, + 'user_password' : password, + 'remindPassword': 0, + 'user[submit]' : "Login"}) if not '<a href="/logout">Wyloguj</a>' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/CloudsixMe.py b/module/plugins/accounts/CloudsixMe.py new file mode 100644 index 000000000..973e37044 --- /dev/null +++ b/module/plugins/accounts/CloudsixMe.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSAccount import XFSAccount + + +class CloudsixMe(XFSAccount): + __name__ = "CloudsixMe" + __type__ = "account" + __version__ = "0.01" + __status__ = "testing" + + __description__ = """Cloudsix.me account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + HOSTER_DOMAIN = "cloudsix.me" diff --git a/module/plugins/accounts/CloudzillaTo.py b/module/plugins/accounts/CloudzillaTo.py index d22d5e4b3..0d473eb7d 100644 --- a/module/plugins/accounts/CloudzillaTo.py +++ b/module/plugins/accounts/CloudzillaTo.py @@ -2,13 +2,14 @@ import re -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class CloudzillaTo(Account): __name__ = "CloudzillaTo" __type__ = "account" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __description__ = """Cloudzilla.to account plugin""" __license__ = "GPLv3" @@ -18,20 +19,19 @@ class CloudzillaTo(Account): PREMIUM_PATTERN = r'<h2>account type</h2>\s*Premium Account' - def loadAccountInfo(self, user, req): - html = req.load("http://www.cloudzilla.to/") + def parse_info(self, user, password, data, req): + html = self.load("http://www.cloudzilla.to/") premium = True if re.search(self.PREMIUM_PATTERN, html) else False return {'validuntil': -1, 'trafficleft': -1, 'premium': premium} - def login(self, user, data, req): - html = req.load("http://www.cloudzilla.to/", - post={'lusername': user, - 'lpassword': data['password'], - 'w' : "dologin"}, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://www.cloudzilla.to/", + post={'lusername': user, + 'lpassword': password, + 'w' : "dologin"}) if "ERROR" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/CramitIn.py b/module/plugins/accounts/CramitIn.py index a9e2274a2..d3f2e0d77 100644 --- a/module/plugins/accounts/CramitIn.py +++ b/module/plugins/accounts/CramitIn.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class CramitIn(XFSAccount): __name__ = "CramitIn" __type__ = "account" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __description__ = """Cramit.in account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/CzshareCom.py b/module/plugins/accounts/CzshareCom.py index 300943828..e9a34cb83 100644 --- a/module/plugins/accounts/CzshareCom.py +++ b/module/plugins/accounts/CzshareCom.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class CzshareCom(Account): __name__ = "CzshareCom" __type__ = "account" - __version__ = "0.18" + __version__ = "0.20" + __status__ = "testing" __description__ = """Czshare.com account plugin, now Sdilej.cz""" __license__ = "GPLv3" @@ -20,20 +21,20 @@ class CzshareCom(Account): CREDIT_LEFT_PATTERN = r'<tr class="active">\s*<td>([\d ,]+) (KiB|MiB|GiB)</td>\s*<td>([^<]*)</td>\s*</tr>' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): premium = False validuntil = None trafficleft = None - html = req.load("http://sdilej.cz/prehled_kreditu/") + html = self.load("http://sdilej.cz/prehled_kreditu/") try: m = re.search(self.CREDIT_LEFT_PATTERN, html) - trafficleft = self.parseTraffic(m.group(1).replace(' ', '').replace(',', '.')) + m.group(2) + trafficleft = self.parse_traffic(m.group(1).replace(' ', '').replace(',', '.')) + m.group(2) validuntil = time.mktime(time.strptime(m.group(3), '%d.%m.%y %H:%M')) except Exception, e: - self.logError(e) + self.log_error(e) else: premium = True @@ -43,12 +44,11 @@ class CzshareCom(Account): 'trafficleft': trafficleft} - def login(self, user, data, req): - html = req.load('https://sdilej.cz/index.php', - post={"Prihlasit": "Prihlasit", - "login-password": data['password'], - "login-name": user}, - decode=True) + def login(self, user, password, data, req): + html = self.load('https://sdilej.cz/index.php', + post={'Prihlasit' : "Prihlasit", + "login-password": password, + "login-name" : user}) if '<div class="login' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/DebridItaliaCom.py b/module/plugins/accounts/DebridItaliaCom.py index 3df99101a..9c0956668 100644 --- a/module/plugins/accounts/DebridItaliaCom.py +++ b/module/plugins/accounts/DebridItaliaCom.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class DebridItaliaCom(Account): __name__ = "DebridItaliaCom" __type__ = "account" - __version__ = "0.13" + __version__ = "0.15" + __status__ = "testing" __description__ = """Debriditalia.com account plugin""" __license__ = "GPLv3" @@ -20,25 +21,25 @@ class DebridItaliaCom(Account): WALID_UNTIL_PATTERN = r'Premium valid till: (.+?) \|' - def loadAccountInfo(self, user, req): - info = {"premium": False, "validuntil": None, "trafficleft": None} - html = req.load("http://debriditalia.com/") + def parse_info(self, user, password, data, req): + info = {'premium': False, 'validuntil': None, 'trafficleft': None} + html = self.load("http://debriditalia.com/") if 'Account premium not activated' not in html: m = re.search(self.WALID_UNTIL_PATTERN, html) if m: validuntil = time.mktime(time.strptime(m.group(1), "%d/%m/%Y %H:%M")) - info = {"premium": True, "validuntil": validuntil, "trafficleft": -1} + info = {'premium': True, 'validuntil': validuntil, 'trafficleft': -1} else: - self.logError(_("Unable to retrieve account information")) + self.log_error(_("Unable to retrieve account information")) return info - def login(self, user, data, req): - html = req.load("http://debriditalia.com/login.php", - get={'u': user, 'p': data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://debriditalia.com/login.php", + get={'u': user, + 'p': password}) if 'NO' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/DepositfilesCom.py b/module/plugins/accounts/DepositfilesCom.py index a0bd6a37c..848529bc3 100644 --- a/module/plugins/accounts/DepositfilesCom.py +++ b/module/plugins/accounts/DepositfilesCom.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class DepositfilesCom(Account): __name__ = "DepositfilesCom" __type__ = "account" - __version__ = "0.32" + __version__ = "0.34" + __status__ = "testing" __description__ = """Depositfiles.com account plugin""" __license__ = "GPLv3" @@ -18,19 +19,20 @@ class DepositfilesCom(Account): ("Walter Purcaro", "vuolter@gmail.com")] - def loadAccountInfo(self, user, req): - html = req.load("https://dfiles.eu/de/gold/") + def parse_info(self, user, password, data, req): + html = self.load("https://dfiles.eu/de/gold/") validuntil = re.search(r"Sie haben Gold Zugang bis: <b>(.*?)</b></div>", html).group(1) validuntil = time.mktime(time.strptime(validuntil, "%Y-%m-%d %H:%M:%S")) - return {"validuntil": validuntil, "trafficleft": -1} + return {'validuntil': validuntil, 'trafficleft': -1} - def login(self, user, data, req): - html = req.load("https://dfiles.eu/de/login.php", get={"return": "/de/gold/payment.php"}, - post={"login": user, "password": data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://dfiles.eu/de/login.php", + get={'return': "/de/gold/payment.php"}, + post={'login' : user, + 'password': password}) if r'<div class="error_message">Sie haben eine falsche Benutzername-Passwort-Kombination verwendet.</div>' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/EasybytezCom.py b/module/plugins/accounts/EasybytezCom.py index 93d3e2c19..5e1a4f962 100644 --- a/module/plugins/accounts/EasybytezCom.py +++ b/module/plugins/accounts/EasybytezCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class EasybytezCom(XFSAccount): __name__ = "EasybytezCom" __type__ = "account" - __version__ = "0.12" + __version__ = "0.13" + __status__ = "testing" __description__ = """EasyBytez.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/EuroshareEu.py b/module/plugins/accounts/EuroshareEu.py index db4539e2e..bc8618250 100644 --- a/module/plugins/accounts/EuroshareEu.py +++ b/module/plugins/accounts/EuroshareEu.py @@ -3,39 +3,40 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class EuroshareEu(Account): __name__ = "EuroshareEu" __type__ = "account" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __description__ = """Euroshare.eu account plugin""" __license__ = "GPLv3" __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): self.relogin(user) - html = req.load("http://euroshare.eu/customer-zone/settings/") + html = self.load("http://euroshare.eu/customer-zone/settings/") m = re.search('id="input_expire_date" value="(\d+\.\d+\.\d+ \d+:\d+)"', html) if m is None: - premium, validuntil = False, -1 + premium = False + validuntil = -1 else: premium = True validuntil = time.mktime(time.strptime(m.group(1), "%d.%m.%Y %H:%M")) - return {"validuntil": validuntil, "trafficleft": -1, "premium": premium} + return {'validuntil': validuntil, 'trafficleft': -1, 'premium': premium} - def login(self, user, data, req): - html = req.load('http://euroshare.eu/customer-zone/login/', - post={"trvale": "1", - "login": user, - "password": data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load('http://euroshare.eu/customer-zone/login/', + post={'trvale' : "1", + 'login' : user, + 'password': password}) if u">Nesprávne prihlasovacie meno alebo heslo" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/ExashareCom.py b/module/plugins/accounts/ExashareCom.py index 431798522..26594c702 100644 --- a/module/plugins/accounts/ExashareCom.py +++ b/module/plugins/accounts/ExashareCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class ExashareCom(XFSAccount): __name__ = "ExashareCom" __type__ = "account" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __description__ = """Exashare.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/FastixRu.py b/module/plugins/accounts/FastixRu.py index 51be3880f..13edbbb44 100644 --- a/module/plugins/accounts/FastixRu.py +++ b/module/plugins/accounts/FastixRu.py @@ -1,36 +1,41 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class FastixRu(Account): __name__ = "FastixRu" __type__ = "account" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" __description__ = """Fastix account plugin""" __license__ = "GPLv3" __authors__ = [("Massimo Rosamilia", "max@spiritix.eu")] - def loadAccountInfo(self, user, req): - data = self.getAccountData(user) - html = json_loads(req.load("http://fastix.ru/api_v2/", get={'apikey': data['api'], 'sub': "getaccountdetails"})) + def parse_info(self, user, password, data, req): + data = self.get_data(user) + html = json_loads(self.load("http://fastix.ru/api_v2/", + get={'apikey': data['api'], + 'sub' : "getaccountdetails"})) points = html['points'] kb = float(points) * 1024 ** 2 / 1000 if points > 0: - account_info = {"validuntil": -1, "trafficleft": kb} + account_info = {'validuntil': -1, 'trafficleft': kb} else: - account_info = {"validuntil": None, "trafficleft": None, "premium": False} + account_info = {'validuntil': None, 'trafficleft': None, 'premium': False} return account_info - def login(self, user, data, req): - html = req.load("http://fastix.ru/api_v2/", - get={'sub': "get_apikey", 'email': user, 'password': data['password']}) + def login(self, user, password, data, req): + html = self.load("https://fastix.ru/api_v2/", + get={'sub' : "get_apikey", + 'email' : user, + 'password': password}) api = json_loads(html) api = api['apikey'] @@ -38,4 +43,4 @@ class FastixRu(Account): data['api'] = api if "error_code" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/FastshareCz.py b/module/plugins/accounts/FastshareCz.py index b946e29ba..3a3769a1c 100644 --- a/module/plugins/accounts/FastshareCz.py +++ b/module/plugins/accounts/FastshareCz.py @@ -2,13 +2,15 @@ import re -from module.plugins.Account import Account +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import set_cookie class FastshareCz(Account): __name__ = "FastshareCz" __type__ = "account" - __version__ = "0.06" + __version__ = "0.09" + __status__ = "testing" __description__ = """Fastshare.cz account plugin""" __license__ = "GPLv3" @@ -19,16 +21,16 @@ class FastshareCz(Account): CREDIT_PATTERN = r'Credit\s*:\s*</td>\s*<td>(.+?)\s*<' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = -1 trafficleft = None premium = False - html = req.load("http://www.fastshare.cz/user", decode=True) + html = self.load("http://www.fastshare.cz/user") m = re.search(self.CREDIT_PATTERN, html) if m: - trafficleft = self.parseTraffic(m.group(1)) + trafficleft = self.parse_traffic(m.group(1)) premium = bool(trafficleft) @@ -37,14 +39,14 @@ class FastshareCz(Account): 'premium' : premium} - def login(self, user, data, req): - req.cj.setCookie("fastshare.cz", "lang", "en") + def login(self, user, password, data, req): + set_cookie(req.cj, "fastshare.cz", "lang", "en") - req.load('http://www.fastshare.cz/login') # Do not remove or it will not login + self.load('http://www.fastshare.cz/login') #@NOTE: Do not remove or it will not login - html = req.load("http://www.fastshare.cz/sql.php", - post={'login': user, 'heslo': data['password']}, - decode=True) + html = self.load("https://www.fastshare.cz/sql.php", + post={'login': user, + 'heslo': password}) if ">Wrong username or password" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/File4SafeCom.py b/module/plugins/accounts/File4SafeCom.py index 50fe1aac8..54c3a2359 100644 --- a/module/plugins/accounts/File4SafeCom.py +++ b/module/plugins/accounts/File4SafeCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class File4SafeCom(XFSAccount): __name__ = "File4SafeCom" __type__ = "account" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __description__ = """File4Safe.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/FileParadoxIn.py b/module/plugins/accounts/FileParadoxIn.py index c12d99d6a..21f43be6e 100644 --- a/module/plugins/accounts/FileParadoxIn.py +++ b/module/plugins/accounts/FileParadoxIn.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class FileParadoxIn(XFSAccount): __name__ = "FileParadoxIn" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """FileParadox.in account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/FilecloudIo.py b/module/plugins/accounts/FilecloudIo.py index 8ca55b1bc..bdb13bd3d 100644 --- a/module/plugins/accounts/FilecloudIo.py +++ b/module/plugins/accounts/FilecloudIo.py @@ -1,13 +1,15 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account from module.common.json_layer import json_loads +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import set_cookie class FilecloudIo(Account): __name__ = "FilecloudIo" __type__ = "account" - __version__ = "0.04" + __version__ = "0.07" + __status__ = "testing" __description__ = """FilecloudIo account plugin""" __license__ = "GPLv3" @@ -15,45 +17,44 @@ class FilecloudIo(Account): ("stickell", "l.stickell@yahoo.it")] - def loadAccountInfo(self, user, req): - # It looks like the first API request always fails, so we retry 5 times, it should work on the second try + def parse_info(self, user, password, data, req): + #: It looks like the first API request always fails, so we retry 5 times, it should work on the second try for _i in xrange(5): - rep = req.load("https://secure.filecloud.io/api-fetch_apikey.api", - post={"username": user, "password": self.getAccountData(user)['password']}) + rep = self.load("https://secure.filecloud.io/api-fetch_apikey.api", + post={'username': user, 'password': password}) rep = json_loads(rep) - if rep['status'] == 'ok': + if rep['status'] == "ok": break - elif rep['status'] == 'error' and rep['message'] == 'no such user or wrong password': - self.logError(_("Wrong username or password")) - return {"valid": False, "premium": False} + elif rep['status'] == "error" and rep['message'] == "no such user or wrong password": + self.log_error(_("Wrong username or password")) + return {'valid': False, 'premium': False} else: - return {"premium": False} + return {'premium': False} akey = rep['akey'] - self.accounts[user]['akey'] = akey # Saved for hoster plugin - rep = req.load("http://api.filecloud.io/api-fetch_account_details.api", - post={"akey": akey}) + self.accounts[user]['akey'] = akey #: Saved for hoster plugin + rep = self.load("http://api.filecloud.io/api-fetch_account_details.api", + post={'akey': akey}) rep = json_loads(rep) if rep['is_premium'] == 1: - return {"validuntil": float(rep['premium_until']), "trafficleft": -1} + return {'validuntil': float(rep['premium_until']), 'trafficleft': -1} else: - return {"premium": False} + return {'premium': False} - def login(self, user, data, req): - req.cj.setCookie("secure.filecloud.io", "lang", "en") - html = req.load('https://secure.filecloud.io/user-login.html') + def login(self, user, password, data, req): + set_cookie(req.cj, "secure.filecloud.io", "lang", "en") + html = self.load('https://secure.filecloud.io/user-login.html') if not hasattr(self, "form_data"): self.form_data = {} self.form_data['username'] = user - self.form_data['password'] = data['password'] + self.form_password = password - html = req.load('https://secure.filecloud.io/user-login_p.html', - post=self.form_data, - multipart=True) + html = self.load('https://secure.filecloud.io/user-login_p.html', + post=self.form_data) if "you have successfully logged in" not in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/FilefactoryCom.py b/module/plugins/accounts/FilefactoryCom.py index 37b6f97a8..e3d0c8491 100644 --- a/module/plugins/accounts/FilefactoryCom.py +++ b/module/plugins/accounts/FilefactoryCom.py @@ -4,13 +4,14 @@ import pycurl import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class FilefactoryCom(Account): __name__ = "FilefactoryCom" __type__ = "account" - __version__ = "0.15" + __version__ = "0.17" + __status__ = "testing" __description__ = """Filefactory.com account plugin""" __license__ = "GPLv3" @@ -21,8 +22,8 @@ class FilefactoryCom(Account): VALID_UNTIL_PATTERN = r'Premium valid until: <strong>(?P<D>\d{1,2})\w{1,2} (?P<M>\w{3}), (?P<Y>\d{4})</strong>' - def loadAccountInfo(self, user, req): - html = req.load("http://www.filefactory.com/account/") + def parse_info(self, user, password, data, req): + html = self.load("http://www.filefactory.com/account/") m = re.search(self.VALID_UNTIL_PATTERN, html) if m: @@ -33,16 +34,16 @@ class FilefactoryCom(Account): premium = False validuntil = -1 - return {"premium": premium, "trafficleft": -1, "validuntil": validuntil} + return {'premium': premium, 'trafficleft': -1, 'validuntil': validuntil} - def login(self, user, data, req): + def login(self, user, password, data, req): req.http.c.setopt(pycurl.REFERER, "http://www.filefactory.com/member/login.php") - html = req.load("http://www.filefactory.com/member/signin.php", - post={"loginEmail" : user, - "loginPassword": data['password'], - "Submit" : "Sign In"}) + html = self.load("https://www.filefactory.com/member/signin.php", + post={'loginEmail' : user, + 'loginPassword': password, + 'Submit' : "Sign In"}) if req.lastEffectiveURL != "http://www.filefactory.com/account/": - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/FilejungleCom.py b/module/plugins/accounts/FilejungleCom.py index b92a371a5..fb251ac5f 100644 --- a/module/plugins/accounts/FilejungleCom.py +++ b/module/plugins/accounts/FilejungleCom.py @@ -2,14 +2,16 @@ import re import time +import urlparse -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class FilejungleCom(Account): __name__ = "FilejungleCom" __type__ = "account" - __version__ = "0.12" + __version__ = "0.14" + __status__ = "testing" __description__ = """Filejungle.com account plugin""" __license__ = "GPLv3" @@ -23,8 +25,8 @@ class FilejungleCom(Account): LOGIN_FAILED_PATTERN = r'<span htmlfor="loginUser(Name|Password)" generated="true" class="fail_info">' - def loadAccountInfo(self, user, req): - html = req.load(self.URL + "dashboard.php") + def parse_info(self, user, password, data, req): + html = self.load(self.URL + "dashboard.php") m = re.search(self.TRAFFIC_LEFT_PATTERN, html) if m: premium = True @@ -33,18 +35,17 @@ class FilejungleCom(Account): premium = False validuntil = -1 - return {"premium": premium, "trafficleft": -1, "validuntil": validuntil} + return {'premium': premium, 'trafficleft': -1, 'validuntil': validuntil} - def login(self, user, data, req): - html = req.load(self.URL + "login.php", - post={"loginUserName": user, - "loginUserPassword": data['password'], - "loginFormSubmit": "Login", - "recaptcha_challenge_field": "", - "recaptcha_response_field": "", - "recaptcha_shortencode_field": ""}, - decode=True) + def login(self, user, password, data, req): + html = self.load(urlparse.urljoin(self.URL, "login.php"), + post={'loginUserName' : user, + 'loginUserPassword' : password, + 'loginFormSubmit' : "Login", + 'recaptcha_challenge_field' : "", + 'recaptcha_response_field' : "", + 'recaptcha_shortencode_field': ""}) if re.search(self.LOGIN_FAILED_PATTERN, html): - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/FileomCom.py b/module/plugins/accounts/FileomCom.py index 7c743f56a..957f4ef05 100644 --- a/module/plugins/accounts/FileomCom.py +++ b/module/plugins/accounts/FileomCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class FileomCom(XFSAccount): __name__ = "FileomCom" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Fileom.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/FilerNet.py b/module/plugins/accounts/FilerNet.py index ac5fd11da..674c7a5dd 100644 --- a/module/plugins/accounts/FilerNet.py +++ b/module/plugins/accounts/FilerNet.py @@ -3,57 +3,57 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class FilerNet(Account): __name__ = "FilerNet" __type__ = "account" - __version__ = "0.04" + __version__ = "0.07" + __status__ = "testing" __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' - def loadAccountInfo(self, user, req): - html = req.load("https://filer.net/profile") + def parse_info(self, user, password, data, req): + html = self.load("https://filer.net/profile") - # Free user + #: Free user if re.search(self.FREE_PATTERN, html): - return {"premium": False, "validuntil": None, "trafficleft": None} + return {'premium': False, 'validuntil': None, 'trafficleft': None} until = re.search(self.WALID_UNTIL_PATTERN, html) traffic = re.search(self.TRAFFIC_PATTERN, html) if until and traffic: validuntil = time.mktime(time.strptime(until.group(1), "%d.%m.%Y %H:%M:%S")) - trafficleft = self.parseTraffic(traffic.group(1)) - return {"premium": True, "validuntil": validuntil, "trafficleft": trafficleft} + trafficleft = self.parse_traffic(traffic.group(1)) + return {'premium': True, 'validuntil': validuntil, 'trafficleft': trafficleft} else: - self.logError(_("Unable to retrieve account information")) - return {"premium": False, "validuntil": None, "trafficleft": None} + self.log_error(_("Unable to retrieve account information")) + return {'premium': False, 'validuntil': None, 'trafficleft': None} - def login(self, user, data, req): - html = req.load("https://filer.net/login") + def login(self, user, password, data, req): + html = self.load("https://filer.net/login") token = re.search(self.TOKEN_PATTERN, html).group(1) - html = req.load("https://filer.net/login_check", - post={"_username": user, - "_password": data['password'], - "_remember_me": "on", - "_csrf_token": token, - "_target_path": "https://filer.net/"}, - decode=True) + html = self.load("https://filer.net/login_check", + post={'_username' : user, + '_password' : password, + '_remember_me': "on", + '_csrf_token' : token, + '_target_path': "https://filer.net/"}) if 'Logout' not in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/FilerioCom.py b/module/plugins/accounts/FilerioCom.py index 4c6755293..8a4750036 100644 --- a/module/plugins/accounts/FilerioCom.py +++ b/module/plugins/accounts/FilerioCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class FilerioCom(XFSAccount): __name__ = "FilerioCom" __type__ = "account" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __description__ = """FileRio.in account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/FilesMailRu.py b/module/plugins/accounts/FilesMailRu.py index ee309c425..7ed09e731 100644 --- a/module/plugins/accounts/FilesMailRu.py +++ b/module/plugins/accounts/FilesMailRu.py @@ -1,31 +1,31 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class FilesMailRu(Account): __name__ = "FilesMailRu" __type__ = "account" - __version__ = "0.11" + __version__ = "0.13" + __status__ = "testing" __description__ = """Filesmail.ru account plugin""" __license__ = "GPLv3" __authors__ = [("RaNaN", "RaNaN@pyload.org")] - def loadAccountInfo(self, user, req): - return {"validuntil": None, "trafficleft": None} + def parse_info(self, user, password, data, req): + return {'validuntil': None, 'trafficleft': None} - def login(self, user, data, req): + def login(self, user, password, data, req): user, domain = user.split("@") - html = req.load("http://swa.mail.ru/cgi-bin/auth", - post={"Domain": domain, - "Login": user, - "Password": data['password'], - "Page": "http://files.mail.ru/"}, - decode=True) + html = self.load("https://swa.mail.ru/cgi-bin/auth", + post={'Domain' : domain, + 'Login' : user, + 'Password': password, + 'Page' : "http://files.mail.ru/"}) if "ÐевеÑМПе ÐžÐŒÑ Ð¿ÐŸÐ»ÑзПваÑÐµÐ»Ñ ÐžÐ»Ðž паÑПлÑ" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/FileserveCom.py b/module/plugins/accounts/FileserveCom.py index 5eb6b844c..dabfc1932 100644 --- a/module/plugins/accounts/FileserveCom.py +++ b/module/plugins/accounts/FileserveCom.py @@ -2,43 +2,50 @@ import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class FileserveCom(Account): __name__ = "FileserveCom" __type__ = "account" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" __description__ = """Fileserve.com account plugin""" __license__ = "GPLv3" __authors__ = [("mkaay", "mkaay@mkaay.de")] - def loadAccountInfo(self, user, req): - data = self.getAccountData(user) + def parse_info(self, user, password, data, req): + data = self.get_data(user) - html = req.load("http://app.fileserve.com/api/login/", post={"username": user, "password": data['password'], - "submit": "Submit+Query"}) + html = self.load("http://app.fileserve.com/api/login/", + post={'username': user, + 'password': password, + 'submit': "Submit+Query"}) res = json_loads(html) if res['type'] == "premium": validuntil = time.mktime(time.strptime(res['expireTime'], "%Y-%m-%d %H:%M:%S")) - return {"trafficleft": res['traffic'], "validuntil": validuntil} + return {'trafficleft': res['traffic'], 'validuntil': validuntil} else: - return {"premium": False, "trafficleft": None, "validuntil": None} + return {'premium': False, 'trafficleft': None, 'validuntil': None} - def login(self, user, data, req): - html = req.load("http://app.fileserve.com/api/login/", post={"username": user, "password": data['password'], - "submit": "Submit+Query"}) + def login(self, user, password, data, req): + html = self.load("http://app.fileserve.com/api/login/", + post={'username': user, + 'password': password, + 'submit' : "Submit+Query"}) res = json_loads(html) if not res['type']: - self.wrongPassword() - - #login at fileserv html - req.load("http://www.fileserve.com/login.php", - post={"loginUserName": user, "loginUserPassword": data['password'], "autoLogin": "checked", - "loginFormSubmit": "Login"}) + self.login_fail() + + #: Login at fileserv html + self.load("http://www.fileserve.com/login.php", + post={'loginUserName' : user, + 'loginUserPassword': password, + 'autoLogin' : "checked", + 'loginFormSubmit' : "Login"}) diff --git a/module/plugins/accounts/FourSharedCom.py b/module/plugins/accounts/FourSharedCom.py index 2777a142a..a7ec8e2c5 100644 --- a/module/plugins/accounts/FourSharedCom.py +++ b/module/plugins/accounts/FourSharedCom.py @@ -1,12 +1,14 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import set_cookie class FourSharedCom(Account): __name__ = "FourSharedCom" __type__ = "account" - __version__ = "0.04" + __version__ = "0.07" + __status__ = "testing" __description__ = """FourShared.com account plugin""" __license__ = "GPLv3" @@ -14,21 +16,20 @@ class FourSharedCom(Account): ("stickell", "l.stickell@yahoo.it")] - def loadAccountInfo(self, user, req): - # Free mode only for now - return {"premium": False} + def parse_info(self, user, password, data, req): + #: Free mode only for now + return {'premium': False} - def login(self, user, data, req): - req.cj.setCookie("4shared.com", "4langcookie", "en") + def login(self, user, password, data, req): + set_cookie(req.cj, "4shared.com", "4langcookie", "en") - res = req.load("http://www.4shared.com/web/login", - post={'login' : user, - 'password' : data['password'], - 'remember' : "on", - '_remember': "on", - 'returnTo' : "http://www.4shared.com/account/home.jsp"}, - decode=True) + res = self.load("https://www.4shared.com/web/login", + post={'login' : user, + 'password' : password, + 'remember' : "on", + '_remember': "on", + 'returnTo' : "http://www.4shared.com/account/home.jsp"}) if 'Please log in to access your 4shared account' in res: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/FreakshareCom.py b/module/plugins/accounts/FreakshareCom.py index ca3602a2c..a2f66f3b3 100644 --- a/module/plugins/accounts/FreakshareCom.py +++ b/module/plugins/accounts/FreakshareCom.py @@ -3,25 +3,26 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class FreakshareCom(Account): __name__ = "FreakshareCom" __type__ = "account" - __version__ = "0.13" + __version__ = "0.15" + __status__ = "testing" __description__ = """Freakshare.com account plugin""" __license__ = "GPLv3" __authors__ = [("RaNaN", "RaNaN@pyload.org")] - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): premium = False validuntil = None trafficleft = None - html = req.load("http://freakshare.com/") + html = self.load("http://freakshare.com/") try: m = re.search(r'ltig bis:</td>\s*<td><b>([\d.:-]+)</b></td>', html, re.M) @@ -32,20 +33,21 @@ class FreakshareCom(Account): try: m = re.search(r'Traffic verbleibend:</td>\s*<td>([^<]+)', html, re.M) - trafficleft = self.parseTraffic(m.group(1)) + trafficleft = self.parse_traffic(m.group(1)) except Exception: pass - return {"premium": premium, "validuntil": validuntil, "trafficleft": trafficleft} + return {'premium': premium, 'validuntil': validuntil, 'trafficleft': trafficleft} - def login(self, user, data, req): - req.load("http://freakshare.com/index.php?language=EN") + def login(self, user, password, data, req): + self.load("http://freakshare.com/index.php?language=EN") - html = req.load("http://freakshare.com/login.html", - post={"submit": "Login", "user": user, "pass": data['password']}, - decode=True) + html = self.load("https://freakshare.com/login.html", + post={'submit': "Login", + 'user' : user, + 'pass' : password}) if ">Wrong Username or Password" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/FreeWayMe.py b/module/plugins/accounts/FreeWayMe.py index 14b9f1e9a..0c315873f 100644 --- a/module/plugins/accounts/FreeWayMe.py +++ b/module/plugins/accounts/FreeWayMe.py @@ -1,52 +1,53 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class FreeWayMe(Account): __name__ = "FreeWayMe" __type__ = "account" - __version__ = "0.13" + __version__ = "0.16" + __status__ = "testing" __description__ = """FreeWayMe account plugin""" __license__ = "GPLv3" __authors__ = [("Nicolas Giese", "james@free-way.me")] - def loadAccountInfo(self, user, req): - status = self.getAccountStatus(user, req) + def parse_info(self, user, password, data, req): + status = self.get_account_status(user, password, req) - self.logDebug(status) + self.log_debug(status) - account_info = {"validuntil": -1, "premium": False} + account_info = {'validuntil': -1, 'premium': False} if status['premium'] == "Free": - account_info['trafficleft'] = self.parseTraffic(status['guthaben'] + "MB") + account_info['trafficleft'] = self.parse_traffic(status['guthaben'] + "MB") elif status['premium'] == "Spender": account_info['trafficleft'] = -1 elif status['premium'] == "Flatrate": - account_info = {"validuntil": float(status['Flatrate']), - "trafficleft": -1, - "premium": True} + account_info = {'validuntil' : float(status['Flatrate']), + 'trafficleft': -1, + 'premium' : True} return account_info - def login(self, user, data, req): - status = self.getAccountStatus(user, req) + def login(self, user, password, data, req): + status = self.get_account_status(user, password, req) - # Check if user and password are valid + #: Check if user and password are valid if not status: - self.wrongPassword() + self.login_fail() - def getAccountStatus(self, user, req): - answer = req.load("https://www.free-way.me/ajax/jd.php", - get={"id": 4, "user": user, "pass": self.getAccountData(user)['password']}) + def get_account_status(self, user, password, req): + answer = self.load("http://www.free-way.bz/ajax/jd.php", #@TODO: Revert to `https` in 0.4.10 + get={'id': 4, 'user': user, 'pass': password}) - self.logDebug("Login: %s" % answer) + self.log_debug("Login: %s" % answer) if answer == "Invalid login": - self.wrongPassword() + self.login_fail() return json_loads(answer) diff --git a/module/plugins/accounts/FshareVn.py b/module/plugins/accounts/FshareVn.py index 7fcf88f20..bc8ced5e2 100644 --- a/module/plugins/accounts/FshareVn.py +++ b/module/plugins/accounts/FshareVn.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class FshareVn(Account): __name__ = "FshareVn" __type__ = "account" - __version__ = "0.09" + __version__ = "0.11" + __status__ = "testing" __description__ = """Fshare.vn account plugin""" __license__ = "GPLv3" @@ -23,40 +24,38 @@ class FshareVn(Account): DIRECT_DOWNLOAD_PATTERN = ur'<input type="checkbox"\s*([^=>]*)[^>]*/>KÃch hoạt download trá»±c tiếp</dt>' - def loadAccountInfo(self, user, req): - html = req.load("http://www.fshare.vn/account_info.php", decode=True) + def parse_info(self, user, password, data, req): + html = self.load("http://www.fshare.vn/account_info.php") if re.search(self.LIFETIME_PATTERN, html): - self.logDebug("Lifetime membership detected") - trafficleft = self.getTrafficLeft() - return {"validuntil": -1, "trafficleft": trafficleft, "premium": True} + self.log_debug("Lifetime membership detected") + trafficleft = self.get_traffic_left() + return {'validuntil': -1, 'trafficleft': trafficleft, 'premium': True} m = re.search(self.VALID_UNTIL_PATTERN, html) if m: premium = True validuntil = time.mktime(time.strptime(m.group(1), '%I:%M:%S %p %d-%m-%Y')) - trafficleft = self.getTrafficLeft() + trafficleft = self.get_traffic_left() else: premium = False validuntil = None trafficleft = None - return {"validuntil": validuntil, "trafficleft": trafficleft, "premium": premium} + return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium} - def login(self, user, data, req): - html = req.load("https://www.fshare.vn/login.php", - post={'LoginForm[email]' : user, - 'LoginForm[password]' : data['password'], - 'LoginForm[rememberMe]': 1, - 'yt0' : "Login"}, - referer=True, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://www.fshare.vn/login.php", + post={'LoginForm[email]' : user, + 'LoginForm[password]' : password, + 'LoginForm[rememberMe]': 1, + 'yt0' : "Login"}) if not re.search(r'<img\s+alt="VIP"', html): - self.wrongPassword() + self.login_fail() - def getTrafficLeft(self): + def get_traffic_left(self): m = re.search(self.TRAFFIC_LEFT_PATTERN, html) - return self.parseTraffic(m.group(1) + m.group(2)) if m else 0 + return self.parse_traffic(m.group(1) + m.group(2)) if m else 0 diff --git a/module/plugins/accounts/Ftp.py b/module/plugins/accounts/Ftp.py index f978d2fa0..2d35ab7bb 100644 --- a/module/plugins/accounts/Ftp.py +++ b/module/plugins/accounts/Ftp.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class Ftp(Account): __name__ = "Ftp" __type__ = "account" - __version__ = "0.01" + __version__ = "0.03" + __status__ = "testing" __description__ = """Ftp dummy account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/HellshareCz.py b/module/plugins/accounts/HellshareCz.py index e559b28e1..55daa8c2d 100644 --- a/module/plugins/accounts/HellshareCz.py +++ b/module/plugins/accounts/HellshareCz.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class HellshareCz(Account): __name__ = "HellshareCz" __type__ = "account" - __version__ = "0.16" + __version__ = "0.18" + __status__ = "testing" __description__ = """Hellshare.cz account plugin""" __license__ = "GPLv3" @@ -19,9 +20,9 @@ class HellshareCz(Account): CREDIT_LEFT_PATTERN = r'<div class="credit-link">\s*<table>\s*<tr>\s*<th>(\d+|\d\d\.\d\d\.)</th>' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): self.relogin(user) - html = req.load("http://www.hellshare.com/") + html = self.load("http://www.hellshare.com/") m = re.search(self.CREDIT_LEFT_PATTERN, html) if m is None: @@ -33,47 +34,47 @@ class HellshareCz(Account): premium = True try: if "." in credit: - #Time-based account + #: Time-based account vt = [int(x) for x in credit.split('.')[:2]] lt = time.localtime() - year = lt.tm_year + int(vt[1] < lt.tm_mon or (vt[1] == lt.tm_mon and vt[0] < lt.tm_mday)) + year = lt.tm_year + int(vt[1] < lt.tm_mon or (vt[1] is lt.tm_mon and vt[0] < lt.tm_mday)) validuntil = time.mktime(time.strptime("%s%d 23:59:59" % (credit, year), "%d.%m.%Y %H:%M:%S")) trafficleft = -1 else: - #Traffic-based account - trafficleft = self.parseTraffic(credit + "MB") + #: Traffic-based account + trafficleft = self.parse_traffic(credit + "MB") validuntil = -1 except Exception, e: - self.logError(_("Unable to parse credit info"), e) + self.log_error(_("Unable to parse credit info"), e) validuntil = -1 trafficleft = -1 - return {"validuntil": validuntil, "trafficleft": trafficleft, "premium": premium} + return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium} - def login(self, user, data, req): - html = req.load('http://www.hellshare.com/', decode=True) + def login(self, user, password, data, req): + html = self.load('http://www.hellshare.com/') if req.lastEffectiveURL != 'http://www.hellshare.com/': - #Switch to English - self.logDebug("Switch lang - URL: %s" % req.lastEffectiveURL) + #: Switch to English + self.log_debug("Switch lang - URL: %s" % req.lastEffectiveURL) - json = req.load("%s?do=locRouter-show" % req.lastEffectiveURL) + json = self.load("%s?do=locRouter-show" % req.lastEffectiveURL) hash = re.search(r"(\-\-[0-9a-f]+\-)", json).group(1) - self.logDebug("Switch lang - HASH: %s" % hash) + self.log_debug("Switch lang - HASH: %s" % hash) - html = req.load('http://www.hellshare.com/%s/' % hash, decode=True) + html = self.load('http://www.hellshare.com/%s/' % hash) if re.search(self.CREDIT_LEFT_PATTERN, html): - self.logDebug("Already logged in") + self.log_debug("Already logged in") return - html = req.load('http://www.hellshare.com/login?do=loginForm-submit', - post={"login": "Log in", - "password": data['password'], - "username": user, - "perm_login": "on"}, - decode=True) + html = self.load("https://www.hellshare.com/login", + get={'do': "loginForm-submit"}, + post={'login' : "Log in", + 'password' : password, + 'username' : user, + 'perm_login': "on"}) if "<p>You input a wrong user name or wrong password</p>" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/HighWayMe.py b/module/plugins/accounts/HighWayMe.py new file mode 100644 index 000000000..ff90ec2d2 --- /dev/null +++ b/module/plugins/accounts/HighWayMe.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +from module.common.json_layer import json_loads +from module.plugins.internal.Account import Account + + +class HighWayMe(Account): + __name__ = "HighWayMe.py" + __type__ = "account" + __version__ = "0.04" + __status__ = "testing" + + __description__ = """High-Way.me account plugin""" + __license__ = "GPLv3" + __authors__ = [("EvolutionClip", "evolutionclip@live.de")] + + + def parse_info(self, user, password, data, req): + premium = False + validuntil = -1 + trafficleft = None + + json_data = self.load('https://high-way.me/api.php?user') + + self.log_debug("JSON data: %s" % json_data) + + json_data = json_loads(json_data) + + if 'premium' in json_data['user'] and json_data['user']['premium']: + premium = True + + if 'premium_bis' in json_data['user'] and json_data['user']['premium_bis']: + validuntil = float(json_data['user']['premium_bis']) + + if 'premium_traffic' in json_data['user'] and json_data['user']['premium_traffic']: + trafficleft = float(json_data['user']['premium_traffic']) / 1024 #@TODO: Remove `/ 1024` in 0.4.10 + + return {'premium' : premium, + 'validuntil' : validuntil, + 'trafficleft': trafficleft} + + + def login(self, user, password, data, req): + html = self.load("https://high-way.me/api.php?login", + post={'login': '1', + 'user': user, + 'pass': password}) + + if 'UserOrPassInvalid' in html: + self.login_fail() diff --git a/module/plugins/accounts/Http.py b/module/plugins/accounts/Http.py index 07e46eb07..dcab156ee 100644 --- a/module/plugins/accounts/Http.py +++ b/module/plugins/accounts/Http.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class Http(Account): __name__ = "Http" __type__ = "account" - __version__ = "0.01" + __version__ = "0.03" + __status__ = "testing" __description__ = """Http dummy account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/HugefilesNet.py b/module/plugins/accounts/HugefilesNet.py index 5da3bbc37..fa64945a3 100644 --- a/module/plugins/accounts/HugefilesNet.py +++ b/module/plugins/accounts/HugefilesNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class HugefilesNet(XFSAccount): __name__ = "HugefilesNet" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Hugefiles.net account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/HundredEightyUploadCom.py b/module/plugins/accounts/HundredEightyUploadCom.py index 319a3feee..a8527d62c 100644 --- a/module/plugins/accounts/HundredEightyUploadCom.py +++ b/module/plugins/accounts/HundredEightyUploadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class HundredEightyUploadCom(XFSAccount): __name__ = "HundredEightyUploadCom" __type__ = "account" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __description__ = """180upload.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/JunkyvideoCom.py b/module/plugins/accounts/JunkyvideoCom.py index 8275ff176..5fcefda36 100644 --- a/module/plugins/accounts/JunkyvideoCom.py +++ b/module/plugins/accounts/JunkyvideoCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class JunkyvideoCom(XFSAccount): __name__ = "JunkyvideoCom" __type__ = "account" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __description__ = """Junkyvideo.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/JunocloudMe.py b/module/plugins/accounts/JunocloudMe.py index b0fc160f3..791835dfe 100644 --- a/module/plugins/accounts/JunocloudMe.py +++ b/module/plugins/accounts/JunocloudMe.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class JunocloudMe(XFSAccount): __name__ = "JunocloudMe" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Junocloud.me account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/Keep2ShareCc.py b/module/plugins/accounts/Keep2ShareCc.py index d2ba1d237..014d43a69 100644 --- a/module/plugins/accounts/Keep2ShareCc.py +++ b/module/plugins/accounts/Keep2ShareCc.py @@ -3,13 +3,15 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import set_cookie class Keep2ShareCc(Account): __name__ = "Keep2ShareCc" __type__ = "account" - __version__ = "0.05" + __version__ = "0.08" + __status__ = "testing" __description__ = """Keep2Share.cc account plugin""" __license__ = "GPLv3" @@ -23,17 +25,17 @@ class Keep2ShareCc(Account): LOGIN_FAIL_PATTERN = r'Please fix the following input errors' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = -1 premium = False - html = req.load("http://keep2share.cc/site/profile.html", decode=True) + html = self.load("http://keep2share.cc/site/profile.html") m = re.search(self.VALID_UNTIL_PATTERN, html) if m: expiredate = m.group(1).strip() - self.logDebug("Expire date: " + expiredate) + self.log_debug("Expire date: " + expiredate) if expiredate == "LifeTime": premium = True @@ -43,7 +45,7 @@ class Keep2ShareCc(Account): validuntil = time.mktime(time.strptime(expiredate, "%Y.%m.%d")) except Exception, e: - self.logError(e) + self.log_error(e) else: premium = True if validuntil > time.mktime(time.gmtime()) else False @@ -51,23 +53,22 @@ class Keep2ShareCc(Account): m = re.search(self.TRAFFIC_LEFT_PATTERN, html) if m: try: - trafficleft = self.parseTraffic(m.group(1)) + trafficleft = self.parse_traffic(m.group(1)) except Exception, e: - self.logError(e) + self.log_error(e) return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium} - def login(self, user, data, req): - req.cj.setCookie("keep2share.cc", "lang", "en") + def login(self, user, password, data, req): + set_cookie(req.cj, "keep2share.cc", "lang", "en") - html = req.load("http://keep2share.cc/login.html", - post={'LoginForm[username]' : user, - 'LoginForm[password]' : data['password'], - 'LoginForm[rememberMe]': 1, - 'yt0' : ""}, - decode=True) + html = self.load("https://keep2share.cc/login.html", + post={'LoginForm[username]' : user, + 'LoginForm[password]' : password, + 'LoginForm[rememberMe]': 1, + 'yt0' : ""}) if re.search(self.LOGIN_FAIL_PATTERN, html): - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/LetitbitNet.py b/module/plugins/accounts/LetitbitNet.py index 7f973d2d3..1fc9b76ba 100644 --- a/module/plugins/accounts/LetitbitNet.py +++ b/module/plugins/accounts/LetitbitNet.py @@ -1,34 +1,35 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account # from module.common.json_layer import json_loads, json_dumps class LetitbitNet(Account): __name__ = "LetitbitNet" __type__ = "account" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __description__ = """Letitbit.net account plugin""" __license__ = "GPLv3" __authors__ = [("stickell", "l.stickell@yahoo.it")] - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): ## DISABLED BECAUSE IT GET 'key exausted' EVEN IF VALID ## - # api_key = self.getAccountData(user)['password'] - # json_data = [api_key, ['key/info']] - # api_rep = req.load('http://api.letitbit.net/json', post={'r': json_dumps(json_data)}) - # self.logDebug("API Key Info: " + api_rep) + # json_data = [password, ['key/info']] + # api_rep = self.load("http://api.letitbit.net/json", + # post={'r': json_dumps(json_data)}) + # self.log_debug("API Key Info: " + api_rep) # api_rep = json_loads(api_rep) # - # if api_rep['status'] == 'FAIL': - # self.logWarning(api_rep['data']) + # if api_rep['status'] == "FAIL": + # self.log_warning(api_rep['data']) # return {'valid': False, 'premium': False} - return {"premium": True} + return {'premium': True} - def login(self, user, data, req): - # API_KEY is the username and the PREMIUM_KEY is the password - self.logInfo(_("You must use your API KEY as username and the PREMIUM KEY as password")) + def login(self, user, password, data, req): + #: API_KEY is the username and the PREMIUM_KEY is the password + self.log_info(_("You must use your API KEY as username and the PREMIUM KEY as password")) diff --git a/module/plugins/accounts/LinestorageCom.py b/module/plugins/accounts/LinestorageCom.py index a48d5beb9..87dd2a1d3 100644 --- a/module/plugins/accounts/LinestorageCom.py +++ b/module/plugins/accounts/LinestorageCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class LinestorageCom(XFSAccount): __name__ = "LinestorageCom" __type__ = "account" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __description__ = """Linestorage.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/LinksnappyCom.py b/module/plugins/accounts/LinksnappyCom.py index 34571d374..00ae64b44 100644 --- a/module/plugins/accounts/LinksnappyCom.py +++ b/module/plugins/accounts/LinksnappyCom.py @@ -2,38 +2,42 @@ import hashlib -from module.plugins.Account import Account +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class LinksnappyCom(Account): __name__ = "LinksnappyCom" __type__ = "account" - __version__ = "0.05" + __version__ = "0.07" + __status__ = "testing" + __description__ = """Linksnappy.com account plugin""" __license__ = "GPLv3" __authors__ = [("stickell", "l.stickell@yahoo.it")] - def loadAccountInfo(self, user, req): - data = self.getAccountData(user) - r = req.load('http://gen.linksnappy.com/lseAPI.php', - get={'act': 'USERDETAILS', 'username': user, 'password': hashlib.md5(data['password']).hexdigest()}) + def parse_info(self, user, password, data, req): + data = self.get_data(user) + r = self.load('http://gen.linksnappy.com/lseAPI.php', + get={'act' : 'USERDETAILS', + 'username': user, + 'password': hashlib.md5(password).hexdigest()}) - self.logDebug("JSON data: " + r) + self.log_debug("JSON data: " + r) j = json_loads(r) if j['error']: - return {"premium": False} + return {'premium': False} validuntil = j['return']['expire'] - if validuntil == 'lifetime': + if validuntil == "lifetime": validuntil = -1 - elif validuntil == 'expired': - return {"premium": False} + elif validuntil == "expired": + return {'premium': False} else: validuntil = float(validuntil) @@ -41,17 +45,18 @@ class LinksnappyCom(Account): if 'trafficleft' not in j['return'] or isinstance(j['return']['trafficleft'], str): trafficleft = -1 else: - trafficleft = self.parseTraffic("%d MB" % j['return']['trafficleft']) + trafficleft = self.parse_traffic("%d MB" % j['return']['trafficleft']) - return {"premium": True, "validuntil": validuntil, "trafficleft": trafficleft} + return {'premium' : True , + 'validuntil' : validuntil , + 'trafficleft': trafficleft} - def login(self, user, data, req): - r = req.load("http://gen.linksnappy.com/lseAPI.php", - get={'act' : 'USERDETAILS', - 'username': user, - 'password': hashlib.md5(data['password']).hexdigest()}, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://gen.linksnappy.com/lseAPI.php", + get={'act' : 'USERDETAILS', + 'username': user, + 'password': hashlib.md5(password).hexdigest()}) - if 'Invalid Account Details' in r: - self.wrongPassword() + if "Invalid Account Details" in html: + self.login_fail() diff --git a/module/plugins/accounts/MegaDebridEu.py b/module/plugins/accounts/MegaDebridEu.py index a082b97af..d7a04491d 100644 --- a/module/plugins/accounts/MegaDebridEu.py +++ b/module/plugins/accounts/MegaDebridEu.py @@ -1,39 +1,44 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class MegaDebridEu(Account): __name__ = "MegaDebridEu" __type__ = "account" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" - __description__ = """mega-debrid.eu account plugin""" + __description__ = """Mega-debrid.eu account plugin""" __license__ = "GPLv3" __authors__ = [("D.Ducatel", "dducatel@je-geek.fr")] - # Define the base URL of MegaDebrid api + #: Define the base URL of MegaDebrid api API_URL = "https://www.mega-debrid.eu/api.php" - def loadAccountInfo(self, user, req): - data = self.getAccountData(user) - jsonResponse = req.load(self.API_URL, - get={'action': 'connectUser', 'login': user, 'password': data['password']}) + def parse_info(self, user, password, data, req): + data = self.get_data(user) + jsonResponse = self.load(self.API_URL, + get={'action' : 'connectUser', + 'login' : user, + 'password': password}) res = json_loads(jsonResponse) if res['response_code'] == "ok": - return {"premium": True, "validuntil": float(res['vip_end']), "status": True} + return {'premium': True, 'validuntil': float(res['vip_end']), 'status': True} else: - self.logError(res) - return {"status": False, "premium": False} + self.log_error(res) + return {'status': False, 'premium': False} - def login(self, user, data, req): - jsonResponse = req.load(self.API_URL, - get={'action': 'connectUser', 'login': user, 'password': data['password']}) + def login(self, user, password, data, req): + jsonResponse = self.load(self.API_URL, + get={'action' : 'connectUser', + 'login' : user, + 'password': password}) res = json_loads(jsonResponse) if res['response_code'] != "ok": - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/MegaRapidCz.py b/module/plugins/accounts/MegaRapidCz.py index 262d5a818..ce2d78994 100644 --- a/module/plugins/accounts/MegaRapidCz.py +++ b/module/plugins/accounts/MegaRapidCz.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class MegaRapidCz(Account): __name__ = "MegaRapidCz" __type__ = "account" - __version__ = "0.35" + __version__ = "0.37" + __status__ = "testing" __description__ = """MegaRapid.cz account plugin""" __license__ = "GPLv3" @@ -24,37 +25,37 @@ class MegaRapidCz(Account): TRAFFIC_LEFT_PATTERN = r'<tr><td>Kredit</td><td>(.*?) GiB' - def loadAccountInfo(self, user, req): - htmll = req.load("http://megarapid.cz/mujucet/", decode=True) + def parse_info(self, user, password, data, req): + htmll = self.load("http://megarapid.cz/mujucet/") m = re.search(self.LIMITDL_PATTERN, htmll) if m: - data = self.getAccountData(user) + data = self.get_data(user) data['options']['limitDL'] = [int(m.group(1))] m = re.search(self.VALID_UNTIL_PATTERN, htmll) if m: validuntil = time.mktime(time.strptime(m.group(1), "%d.%m.%Y - %H:%M")) - return {"premium": True, "trafficleft": -1, "validuntil": validuntil} + return {'premium': True, 'trafficleft': -1, 'validuntil': validuntil} m = re.search(self.TRAFFIC_LEFT_PATTERN, htmll) if m: trafficleft = float(m.group(1)) * (1 << 20) - return {"premium": True, "trafficleft": trafficleft, "validuntil": -1} + return {'premium': True, 'trafficleft': trafficleft, 'validuntil': -1} - return {"premium": False, "trafficleft": None, "validuntil": None} + return {'premium': False, 'trafficleft': None, 'validuntil': None} - def login(self, user, data, req): - html = req.load("http://megarapid.cz/prihlaseni/", decode=True) + def login(self, user, password, data, req): + html = self.load("http://megarapid.cz/prihlaseni/") if "Heslo:" in html: start = html.index('id="inp_hash" name="hash" value="') html = html[start + 33:] hashes = html[0:32] - html = req.load("http://megarapid.cz/prihlaseni/", - post={"hash": hashes, - "login": user, - "pass1": data['password'], - "remember": 0, - "sbmt": u"PÅihlásit"}) + html = self.load("https://megarapid.cz/prihlaseni/", + post={'hash' : hashes, + 'login' : user, + 'pass1' : password, + 'remember': 1, + 'sbmt' : u"PÅihlásit"}) diff --git a/module/plugins/accounts/MegaRapidoNet.py b/module/plugins/accounts/MegaRapidoNet.py index d061d02bc..08cf1f535 100644 --- a/module/plugins/accounts/MegaRapidoNet.py +++ b/module/plugins/accounts/MegaRapidoNet.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class MegaRapidoNet(Account): __name__ = "MegaRapidoNet" __type__ = "account" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __description__ = """MegaRapido.net account plugin""" __license__ = "GPLv3" @@ -20,16 +21,16 @@ class MegaRapidoNet(Account): USER_ID_PATTERN = r'<\s*?div[^>]*?class\s*?=\s*?["\']checkbox_compartilhar["\'].*?>.*?<\s*?input[^>]*?name\s*?=\s*?["\']usar["\'].*?>.*?<\s*?input[^>]*?name\s*?=\s*?["\']user["\'][^>]*?value\s*?=\s*?["\'](.*?)\s*?["\']' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = None premium = False - html = req.load("http://megarapido.net/gerador", decode=True) + html = self.load("http://megarapido.net/gerador") validuntil = re.search(self.VALID_UNTIL_PATTERN, html) if validuntil: - #hier weitermachen!!! (mÃŒssen umbedingt die zeit richtig machen damit! (sollte aber möglich)) + #: Hier weitermachen!!! (mÃŒssen umbedingt die zeit richtig machen damit! (sollte aber möglich)) validuntil = time.time() + int(validuntil.group(1)) * 24 * 3600 + int(validuntil.group(2)) * 3600 + int(validuntil.group(3)) * 60 + int(validuntil.group(4)) trafficleft = -1 premium = True @@ -39,19 +40,19 @@ class MegaRapidoNet(Account): 'premium' : premium} - def login(self, user, data, req): - req.load("http://megarapido.net/login") - req.load("http://megarapido.net/painel_user/ajax/logar.php", - post={'login': user, 'senha': data['password']}, - decode=True) + def login(self, user, password, data, req): + self.load("http://megarapido.net/login") + self.load("http://megarapido.net/painel_user/ajax/logar.php", + post={'login': user, + 'senha': password}) - html = req.load("http://megarapido.net/gerador") + html = self.load("http://megarapido.net/gerador") if "sair" not in html.lower(): - self.wrongPassword() + self.login_fail() else: m = re.search(self.USER_ID_PATTERN, html) if m: data['uid'] = m.group(1) else: - self.fail("Couldn't find the user ID") + self.login_fail("Couldn't find the user ID") diff --git a/module/plugins/accounts/MegasharesCom.py b/module/plugins/accounts/MegasharesCom.py index 3d7ddbe46..ec43b7fc0 100644 --- a/module/plugins/accounts/MegasharesCom.py +++ b/module/plugins/accounts/MegasharesCom.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class MegasharesCom(Account): __name__ = "MegasharesCom" __type__ = "account" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" __description__ = """Megashares.com account plugin""" __license__ = "GPLv3" @@ -19,30 +20,29 @@ class MegasharesCom(Account): VALID_UNTIL_PATTERN = r'<p class="premium_info_box">Period Ends: (\w{3} \d{1,2}, \d{4})</p>' - def loadAccountInfo(self, user, req): - #self.relogin(user) - html = req.load("http://d01.megashares.com/myms.php", decode=True) + def parse_info(self, user, password, data, req): + # self.relogin(user) + html = self.load("http://d01.megashares.com/myms.php") premium = False if '>Premium Upgrade<' in html else True validuntil = trafficleft = -1 try: timestr = re.search(self.VALID_UNTIL_PATTERN, html).group(1) - self.logDebug(timestr) + self.log_debug(timestr) validuntil = time.mktime(time.strptime(timestr, "%b %d, %Y")) except Exception, e: - self.logError(e) + self.log_error(e) - return {"validuntil": validuntil, "trafficleft": -1, "premium": premium} + return {'validuntil': validuntil, 'trafficleft': -1, 'premium': premium} - def login(self, user, data, req): - html = req.load('http://d01.megashares.com/myms_login.php', - post={"httpref" : "", - "myms_login" : "Login", - "mymslogin_name": user, - "mymspassword" : data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load('http://d01.megashares.com/myms_login.php', + post={'httpref' : "", + 'myms_login' : "Login", + 'mymslogin_name': user, + 'mymspassword' : password}) if not '<span class="b ml">%s</span>' % user in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/MovReelCom.py b/module/plugins/accounts/MovReelCom.py index 6128cddc8..090950bf2 100644 --- a/module/plugins/accounts/MovReelCom.py +++ b/module/plugins/accounts/MovReelCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class MovReelCom(XFSAccount): __name__ = "MovReelCom" __type__ = "account" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __description__ = """Movreel.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/MultihostersCom.py b/module/plugins/accounts/MultihostersCom.py index e98f17b2d..ed04ad3c2 100644 --- a/module/plugins/accounts/MultihostersCom.py +++ b/module/plugins/accounts/MultihostersCom.py @@ -6,7 +6,8 @@ from module.plugins.accounts.ZeveraCom import ZeveraCom class MultihostersCom(ZeveraCom): __name__ = "MultihostersCom" __type__ = "account" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __description__ = """Multihosters.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/MultishareCz.py b/module/plugins/accounts/MultishareCz.py index 3488e3288..c9e30a93f 100644 --- a/module/plugins/accounts/MultishareCz.py +++ b/module/plugins/accounts/MultishareCz.py @@ -2,13 +2,14 @@ import re -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class MultishareCz(Account): __name__ = "MultishareCz" __type__ = "account" - __version__ = "0.05" + __version__ = "0.07" + __status__ = "testing" __description__ = """Multishare.cz account plugin""" __license__ = "GPLv3" @@ -19,26 +20,25 @@ class MultishareCz(Account): ACCOUNT_INFO_PATTERN = r'<input type="hidden" id="(u_ID|u_hash)" name=".+?" value="(.+?)">' - def loadAccountInfo(self, user, req): - #self.relogin(user) - html = req.load("http://www.multishare.cz/profil/", decode=True) + def parse_info(self, user, password, data, req): + # self.relogin(user) + html = self.load("http://www.multishare.cz/profil/") m = re.search(self.TRAFFIC_LEFT_PATTERN, html) - trafficleft = self.parseTraffic(m.group('S') + m.group('U')) if m else 0 + trafficleft = self.parse_traffic(m.group('S') + m.group('U')) if m else 0 self.premium = True if trafficleft else False - html = req.load("http://www.multishare.cz/", decode=True) + html = self.load("http://www.multishare.cz/") mms_info = dict(re.findall(self.ACCOUNT_INFO_PATTERN, html)) - return dict(mms_info, **{"validuntil": -1, "trafficleft": trafficleft}) + return dict(mms_info, **{'validuntil': -1, 'trafficleft': trafficleft}) - def login(self, user, data, req): - html = req.load('http://www.multishare.cz/html/prihlaseni_process.php', - post={"akce" : "PÅihlásit", - "heslo": data['password'], - "jmeno": user}, - decode=True) + def login(self, user, password, data, req): + html = self.load('https://www.multishare.cz/html/prihlaseni_process.php', + post={'akce' : "PÅihlásit", + 'heslo': password, + 'jmeno': user}) if '<div class="akce-chyba akce">' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/MyfastfileCom.py b/module/plugins/accounts/MyfastfileCom.py index 9a13e2e42..008b62cc6 100644 --- a/module/plugins/accounts/MyfastfileCom.py +++ b/module/plugins/accounts/MyfastfileCom.py @@ -3,35 +3,37 @@ import time from module.common.json_layer import json_loads -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class MyfastfileCom(Account): __name__ = "MyfastfileCom" __type__ = "account" - __version__ = "0.04" + __version__ = "0.06" + __status__ = "testing" __description__ = """Myfastfile.com account plugin""" __license__ = "GPLv3" __authors__ = [("stickell", "l.stickell@yahoo.it")] - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): if 'days_left' in self.json_data: validuntil = time.time() + self.json_data['days_left'] * 24 * 60 * 60 - return {"premium": True, "validuntil": validuntil, "trafficleft": -1} + return {'premium': True, 'validuntil': validuntil, 'trafficleft': -1} else: - self.logError(_("Unable to get account information")) + self.log_error(_("Unable to get account information")) - def login(self, user, data, req): - # Password to use is the API-Password written in http://myfastfile.com/myaccount - html = req.load("http://myfastfile.com/api.php", - get={"user": user, "pass": data['password']}) + def login(self, user, password, data, req): + #: Password to use is the API-Password written in http://myfastfile.com/myaccount + html = self.load("https://myfastfile.com/api.php", + get={'user': user, + 'pass': password}) - self.logDebug("JSON data: " + html) + self.log_debug("JSON data: " + html) self.json_data = json_loads(html) if self.json_data['status'] != 'ok': - self.logError(_('Invalid login. The password to use is the API-Password you find in your "My Account" page')) - self.wrongPassword() + self.log_error(_('Invalid login. The password to use is the API-Password you find in your "My Account" page')) + self.login_fail() diff --git a/module/plugins/accounts/NitroflareCom.py b/module/plugins/accounts/NitroflareCom.py new file mode 100644 index 000000000..b7edcca32 --- /dev/null +++ b/module/plugins/accounts/NitroflareCom.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- + +import re +import time + +from module.plugins.internal.Account import Account + + +class NitroflareCom(Account): + __name__ = "NitroflareCom" + __type__ = "account" + __version__ = "0.06" + __status__ = "testing" + + __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 parse_info(self, user, password, data, req): + validuntil = -1 + trafficleft = None + premium = False + + html = self.load("https://nitroflare.com/member", + get={'s': "premium"}) + + m = re.search(self.VALID_UNTIL_PATTERN, html) + if m: + expiredate = m.group(1).strip() + self.log_debug("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.log_error(e) + + else: + self.log_debug("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.parse_traffic(str(max(0, 50 - float(m.group(1)))) + " GB") + + except Exception, e: + self.log_error(e) + else: + self.log_debug("TRAFFIC_LEFT_PATTERN not found") + + return {'validuntil' : validuntil, + 'trafficleft': trafficleft, + 'premium' : premium} + + + def login(self, user, password, data, req): + html = self.load("https://nitroflare.com/login") + + token = re.search(self.TOKEN_PATTERN, html).group(1) + + html = self.load("https://nitroflare.com/login", + post={'login' : "", + 'email' : user, + 'password': password, + 'token' : token}) + + if re.search(self.LOGIN_FAIL_PATTERN, html): + self.login_fail() diff --git a/module/plugins/accounts/NoPremiumPl.py b/module/plugins/accounts/NoPremiumPl.py index 7e3f757d3..e9dad7647 100644 --- a/module/plugins/accounts/NoPremiumPl.py +++ b/module/plugins/accounts/NoPremiumPl.py @@ -4,78 +4,80 @@ import datetime import hashlib import time -from module.plugins.Account import Account -from module.common.json_layer import json_loads as loads +from module.common.json_layer import json_loads +from module.plugins.internal.Account import Account class NoPremiumPl(Account): - __name__ = "NoPremiumPl" - __version__ = "0.01" - __type__ = "account" + __name__ = "NoPremiumPl" + __type__ = "account" + __version__ = "0.03" + __status__ = "testing" + __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): + + def parse_info(self, name, req): self._req = req try: - result = loads(self.runAuthQuery()) + result = json_loads(self.run_auth_query()) except Exception: - # todo: return or let it be thrown? + #@TODO: return or let it be thrown? return premium = False valid_untill = -1 - if "expire" in result.keys() and result["expire"]: + 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 + 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): + + def login(self, user, password, data, req): self._usr = user - self._pwd = hashlib.sha1(hashlib.md5(data["password"]).hexdigest()).hexdigest() + self._pwd = hashlib.sha1(hashlib.md5(password).hexdigest()).hexdigest() self._req = req try: - response = loads(self.runAuthQuery()) + response = json_loads(self.run_auth_query()) except Exception: - self.wrongPassword() + self.login_fail() if "errno" in response.keys(): - self.wrongPassword() + self.login_fail() + data['usr'] = self._usr data['pwd'] = self._pwd - def createAuthQuery(self): - query = self._api_query - query["username"] = self._usr - query["password"] = self._pwd + def create_auth_query(self): + 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 run_auth_query(self): + return self.load(self.API_URL, + post=self.create_auth_query()) diff --git a/module/plugins/accounts/NosuploadCom.py b/module/plugins/accounts/NosuploadCom.py index e523ee2f4..5febc8d66 100644 --- a/module/plugins/accounts/NosuploadCom.py +++ b/module/plugins/accounts/NosuploadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class NosuploadCom(XFSAccount): __name__ = "NosuploadCom" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Nosupload.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/NovafileCom.py b/module/plugins/accounts/NovafileCom.py index ab61bf0fc..524c01087 100644 --- a/module/plugins/accounts/NovafileCom.py +++ b/module/plugins/accounts/NovafileCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class NovafileCom(XFSAccount): __name__ = "NovafileCom" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Novafile.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/NowVideoSx.py b/module/plugins/accounts/NowVideoSx.py index 2f7b033bd..73bb383be 100644 --- a/module/plugins/accounts/NowVideoSx.py +++ b/module/plugins/accounts/NowVideoSx.py @@ -3,13 +3,14 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class NowVideoSx(Account): __name__ = "NowVideoSx" __type__ = "account" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" __description__ = """NowVideo.at account plugin""" __license__ = "GPLv3" @@ -19,23 +20,23 @@ class NowVideoSx(Account): VALID_UNTIL_PATTERN = r'>Your premium membership expires on: (.+?)<' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = -1 premium = None - html = req.load("http://www.nowvideo.sx/premium.php") + html = self.load("http://www.nowvideo.sx/premium.php") m = re.search(self.VALID_UNTIL_PATTERN, html) if m: expiredate = m.group(1).strip() - self.logDebug("Expire date: " + expiredate) + self.log_debug("Expire date: " + expiredate) try: validuntil = time.mktime(time.strptime(expiredate, "%Y-%b-%d")) except Exception, e: - self.logError(e) + self.log_error(e) else: if validuntil > time.mktime(time.gmtime()): @@ -44,13 +45,13 @@ class NowVideoSx(Account): premium = False validuntil = -1 - return {"validuntil": validuntil, "trafficleft": trafficleft, "premium": premium} + return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium} - def login(self, user, data, req): - html = req.load("http://www.nowvideo.sx/login.php", - post={'user': user, 'pass': data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load("http://www.nowvideo.sx/login.php", + post={'user': user, + 'pass': password}) if re.search(r'>Log In<', html): - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/OboomCom.py b/module/plugins/accounts/OboomCom.py index 020a45ba7..380368b70 100644 --- a/module/plugins/accounts/OboomCom.py +++ b/module/plugins/accounts/OboomCom.py @@ -17,37 +17,40 @@ except ImportError: return b2a_hex(pbkdf2(self.passphrase, self.salt, self.iterations, octets)) from module.common.json_layer import json_loads -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class OboomCom(Account): __name__ = "OboomCom" __type__ = "account" - __version__ = "0.24" + __version__ = "0.27" + __status__ = "testing" __description__ = """Oboom.com account plugin""" __license__ = "GPLv3" __authors__ = [("stanley", "stanley.foerster@gmail.com")] - def loadAccountData(self, user, req): - passwd = self.getAccountData(user)['password'] + def load_account_data(self, user, req): + passwd = self.get_info(user)['login']['password'] salt = passwd[::-1] pbkdf2 = PBKDF2(passwd, salt, 1000).hexread(16) - result = json_loads(req.load("https://www.oboom.com/1/login", get={"auth": user, "pass": pbkdf2})) + result = json_loads(self.load("http://www.oboom.com/1/login", #@TODO: Revert to `https` in 0.4.10 + get={'auth': user, + 'pass': pbkdf2})) if not result[0] == 200: - self.logWarning(_("Failed to log in: %s") % result[1]) - self.wrongPassword() + self.log_warning(_("Failed to log in: %s") % result[1]) + self.login_fail() return result[1] - def loadAccountInfo(self, name, req): - accountData = self.loadAccountData(name, req) + def parse_info(self, name, req): + account_data = self.load_account_data(name, req) - userData = accountData['user'] + userData = account_data['user'] if userData['premium'] == "null": premium = False @@ -64,7 +67,7 @@ class OboomCom(Account): trafficLeft = traffic['current'] / 1024 #@TODO: Remove `/ 1024` in 0.4.10 maxTraffic = traffic['max'] / 1024 #@TODO: Remove `/ 1024` in 0.4.10 - session = accountData['session'] + session = account_data['session'] return {'premium' : premium, 'validuntil' : validUntil, @@ -73,5 +76,5 @@ class OboomCom(Account): 'session' : session} - def login(self, user, data, req): - self.loadAccountData(user, req) + def login(self, user, password, data, req): + self.load_account_data(user, req) diff --git a/module/plugins/accounts/OneFichierCom.py b/module/plugins/accounts/OneFichierCom.py index b19e2bc69..3a0131a3f 100644 --- a/module/plugins/accounts/OneFichierCom.py +++ b/module/plugins/accounts/OneFichierCom.py @@ -4,13 +4,14 @@ import pycurl import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class OneFichierCom(Account): __name__ = "OneFichierCom" __type__ = "account" - __version__ = "0.12" + __version__ = "0.14" + __status__ = "testing" __description__ = """1fichier.com account plugin""" __license__ = "GPLv3" @@ -21,38 +22,37 @@ class OneFichierCom(Account): VALID_UNTIL_PATTERN = r'Your Premium Status will end the (\d+/\d+/\d+)' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = -1 premium = None - html = req.load("https://1fichier.com/console/abo.pl") + html = self.load("https://1fichier.com/console/abo.pl") m = re.search(self.VALID_UNTIL_PATTERN, html) if m: expiredate = m.group(1) - self.logDebug("Expire date: " + expiredate) + self.log_debug("Expire date: " + expiredate) try: validuntil = time.mktime(time.strptime(expiredate, "%d/%m/%Y")) except Exception, e: - self.logError(e) + self.log_error(e) else: premium = True return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium or False} - def login(self, user, data, req): + def login(self, user, password, data, req): req.http.c.setopt(pycurl.REFERER, "https://1fichier.com/login.pl?lg=en") - html = req.load("https://1fichier.com/login.pl?lg=en", - post={'mail' : user, - 'pass' : data['password'], - 'It' : "on", - 'purge' : "off", - 'valider': "Send"}, - decode=True) + html = self.load("https://1fichier.com/login.pl?lg=en", + post={'mail' : user, + 'pass' : password, + 'It' : "on", + 'purge' : "off", + 'valider': "Send"}) if '>Invalid email address' in html or '>Invalid password' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/OverLoadMe.py b/module/plugins/accounts/OverLoadMe.py index 64d04aded..6741b674f 100644 --- a/module/plugins/accounts/OverLoadMe.py +++ b/module/plugins/accounts/OverLoadMe.py @@ -1,43 +1,42 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class OverLoadMe(Account): __name__ = "OverLoadMe" __type__ = "account" - __version__ = "0.04" + __version__ = "0.06" + __status__ = "testing" __description__ = """Over-Load.me account plugin""" __license__ = "GPLv3" __authors__ = [("marley", "marley@over-load.me")] - def loadAccountInfo(self, user, req): - https = "https" if self.getConfig('ssl') else "http" - data = self.getAccountData(user) - html = req.load(https + "://api.over-load.me/account.php", - get={'user': user, - 'auth': data['password']}).strip() + def parse_info(self, user, password, data, req): + data = self.get_data(user) + html = self.load("https://api.over-load.me/account.php", + get={'user': user, + 'auth': password}).strip() data = json_loads(html) - self.logDebug(data) + self.log_debug(data) - # Check for premium + #: Check for premium if data['membership'] == "Free": return {'premium': False, 'validuntil': None, 'trafficleft': None} else: return {'premium': True, 'validuntil': data['expirationunix'], 'trafficleft': -1} - def login(self, user, data, req): - https = "https" if self.getConfig('ssl') else "http" - jsondata = req.load(https + "://api.over-load.me/account.php", - get={'user': user, - 'auth': data['password']}).strip() + def login(self, user, password, data, req): + jsondata = self.load("https://api.over-load.me/account.php", + get={'user': user, + 'auth': password}).strip() data = json_loads(jsondata) if data['err'] == 1: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/PremiumTo.py b/module/plugins/accounts/PremiumTo.py index c8ea2fa26..ba8f24c6d 100644 --- a/module/plugins/accounts/PremiumTo.py +++ b/module/plugins/accounts/PremiumTo.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class PremiumTo(Account): __name__ = "PremiumTo" __type__ = "account" - __version__ = "0.08" + __version__ = "0.11" + __status__ = "testing" __description__ = """Premium.to account plugin""" __license__ = "GPLv3" @@ -15,9 +16,10 @@ class PremiumTo(Account): ("stickell", "l.stickell@yahoo.it")] - def loadAccountInfo(self, user, req): - traffic = req.load("http://premium.to/api/straffic.php", - get={'username': self.username, 'password': self.password}) + def parse_info(self, user, password, data, req): + traffic = self.load("http://premium.to/api/straffic.php", #@TODO: Revert to `https` in 0.4.10 + get={'username': self.username, + 'password': self.password}) if "wrong username" not in traffic: trafficleft = sum(map(float, traffic.split(';'))) / 1024 #@TODO: Remove `/ 1024` in 0.4.10 @@ -26,12 +28,12 @@ class PremiumTo(Account): return {'premium': False, 'trafficleft': None, 'validuntil': None} - def login(self, user, data, req): + def login(self, user, password, data, req): self.username = user - self.password = data['password'] - authcode = req.load("http://premium.to/api/getauthcode.php", - get={'username': user, 'password': self.password}, - decode=True) + self.password = password + authcode = self.load("http://premium.to/api/getauthcode.php", #@TODO: Revert to `https` in 0.4.10 + get={'username': user, + 'password': self.password}) if "wrong username" in authcode: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/PremiumizeMe.py b/module/plugins/accounts/PremiumizeMe.py index 7d061ec2d..df3b5db51 100644 --- a/module/plugins/accounts/PremiumizeMe.py +++ b/module/plugins/accounts/PremiumizeMe.py @@ -1,49 +1,49 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account - from module.common.json_layer import json_loads +from module.plugins.internal.Account import Account class PremiumizeMe(Account): __name__ = "PremiumizeMe" __type__ = "account" - __version__ = "0.13" + __version__ = "0.19" + __status__ = "testing" __description__ = """Premiumize.me account plugin""" __license__ = "GPLv3" __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com")] - def loadAccountInfo(self, user, req): - # Get user data from premiumize.me - status = self.getAccountStatus(user, req) - self.logDebug(status) + def parse_info(self, user, password, data, req): + #: Get user data from premiumize.me + status = self.get_account_status(user, password) + self.log_debug(status) - # Parse account info - account_info = {"validuntil": float(status['result']['expires']), - "trafficleft": max(0, status['result']['trafficleft_bytes'] / 1024)} #@TODO: Remove `/ 1024` in 0.4.10 + #: Parse account info + account_info = {'validuntil': float(status['result']['expires']), + 'trafficleft': max(0, status['result']['trafficleft_bytes'] / 1024)} #@TODO: Remove `/ 1024` in 0.4.10 - if status['result']['type'] == 'free': - account_info['premium'] = False + if status['result']['type'] != 'free': + account_info['premium'] = True return account_info - def login(self, user, data, req): - # Get user data from premiumize.me - status = self.getAccountStatus(user, req) + def login(self, user, password, data, req): + #: Get user data from premiumize.me + status = self.get_account_status(user, password) - # Check if user and password are valid + #: Check if user and password are valid if status['status'] != 200: - self.wrongPassword() + self.login_fail() - 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", + def get_account_status(self, user, password): + #: Use premiumize.me API v1 (see https://secure.premiumize.me/?show=api) + #: To retrieve account info and return the parsed json answer + answer = self.load("http://api.premiumize.me/pm-api/v1.php", #@TODO: Revert to `https` in 0.4.10 get={'method' : "accountstatus", 'params[login]': user, - 'params[pass]' : self.getAccountData(user)['password']}) + 'params[pass]' : password}) return json_loads(answer) diff --git a/module/plugins/accounts/PutdriveCom.py b/module/plugins/accounts/PutdriveCom.py index 4f2fadbcc..5356c4d1a 100644 --- a/module/plugins/accounts/PutdriveCom.py +++ b/module/plugins/accounts/PutdriveCom.py @@ -6,7 +6,8 @@ from module.plugins.accounts.ZeveraCom import ZeveraCom class PutdriveCom(ZeveraCom): __name__ = "PutdriveCom" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Putdrive.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/QuickshareCz.py b/module/plugins/accounts/QuickshareCz.py index 16141d63e..42022ec82 100644 --- a/module/plugins/accounts/QuickshareCz.py +++ b/module/plugins/accounts/QuickshareCz.py @@ -2,13 +2,14 @@ import re -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class QuickshareCz(Account): __name__ = "QuickshareCz" __type__ = "account" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" __description__ = """Quickshare.cz account plugin""" __license__ = "GPLv3" @@ -18,26 +19,25 @@ class QuickshareCz(Account): TRAFFIC_LEFT_PATTERN = r'Stav kreditu: <strong>(.+?)</strong>' - def loadAccountInfo(self, user, req): - html = req.load("http://www.quickshare.cz/premium", decode=True) + def parse_info(self, user, password, data, req): + html = self.load("http://www.quickshare.cz/premium") m = re.search(self.TRAFFIC_LEFT_PATTERN, html) if m: - trafficleft = self.parseTraffic(m.group(1)) + trafficleft = self.parse_traffic(m.group(1)) premium = True if trafficleft else False else: trafficleft = None premium = False - return {"validuntil": -1, "trafficleft": trafficleft, "premium": premium} + return {'validuntil': -1, 'trafficleft': trafficleft, 'premium': premium} - def login(self, user, data, req): - html = req.load('http://www.quickshare.cz/html/prihlaseni_process.php', - post={"akce": u'PÅihlásit', - "heslo": data['password'], - "jmeno": user}, - decode=True) + def login(self, user, password, data, req): + html = self.load('http://www.quickshare.cz/html/prihlaseni_process.php', + post={'akce' : u'PÅihlásit', + 'heslo': password, + 'jmeno': user}) if u'>TakovÃœ uÅŸivatel neexistuje.<' in html or u'>Å patné heslo.<' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/RPNetBiz.py b/module/plugins/accounts/RPNetBiz.py index 829e54a46..d713cedca 100644 --- a/module/plugins/accounts/RPNetBiz.py +++ b/module/plugins/accounts/RPNetBiz.py @@ -1,51 +1,52 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class RPNetBiz(Account): __name__ = "RPNetBiz" __type__ = "account" - __version__ = "0.12" + __version__ = "0.15" + __status__ = "testing" __description__ = """RPNet.biz account plugin""" __license__ = "GPLv3" __authors__ = [("Dman", "dmanugm@gmail.com")] - def loadAccountInfo(self, user, req): - # Get account information from rpnet.biz - res = self.getAccountStatus(user, req) + def parse_info(self, user, password, data, req): + #: Get account information from rpnet.biz + res = self.get_account_status(user, password, req) try: if res['accountInfo']['isPremium']: - # Parse account info. Change the trafficleft later to support per host info. - account_info = {"validuntil": float(res['accountInfo']['premiumExpiry']), - "trafficleft": -1, "premium": True} + #: Parse account info. Change the trafficleft later to support per host info. + account_info = {'validuntil': float(res['accountInfo']['premiumExpiry']), + 'trafficleft': -1, 'premium': True} else: - account_info = {"validuntil": None, "trafficleft": None, "premium": False} + account_info = {'validuntil': None, 'trafficleft': None, 'premium': False} except KeyError: - #handle wrong password exception - account_info = {"validuntil": None, "trafficleft": None, "premium": False} + #: Handle wrong password exception + account_info = {'validuntil': None, 'trafficleft': None, 'premium': False} return account_info - def login(self, user, data, req): - # Get account information from rpnet.biz - res = self.getAccountStatus(user, req) + def login(self, user, password, data, req): + #: Get account information from rpnet.biz + res = self.get_account_status(user, password, req) - # If we have an error in the res, we have wrong login information + #: If we have an error in the res, we have wrong login information if 'error' in res: - self.wrongPassword() + self.login_fail() - def getAccountStatus(self, user, req): - # Using the rpnet API, check if valid premium account - res = req.load("https://premium.rpnet.biz/client_api.php", - get={"username": user, "password": self.getAccountData(user)['password'], - "action": "showAccountInformation"}) - self.logDebug("JSON data: %s" % res) + def get_account_status(self, user, password, req): + #: Using the rpnet API, check if valid premium account + res = self.load("https://premium.rpnet.biz/client_api.php", + get={'username': user, 'password': password, + 'action': "showAccountInformation"}) + self.log_debug("JSON data: %s" % res) return json_loads(res) diff --git a/module/plugins/accounts/RapideoPl.py b/module/plugins/accounts/RapideoPl.py index 3e9d52fe8..42d084bdb 100644 --- a/module/plugins/accounts/RapideoPl.py +++ b/module/plugins/accounts/RapideoPl.py @@ -4,77 +4,80 @@ import datetime import hashlib import time -from module.plugins.Account import Account -from module.common.json_layer import json_loads as loads +from module.common.json_layer import json_loads +from module.plugins.internal.Account import Account class RapideoPl(Account): - __name__ = "RapideoPl" - __version__ = "0.01" - __type__ = "account" + __name__ = "RapideoPl" + __type__ = "account" + __version__ = "0.03" + __status__ = "testing" + __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): + + def parse_info(self, name, req): self._req = req try: - result = loads(self.runAuthQuery()) + result = json_loads(self.run_auth_query()) except Exception: - # todo: return or let it be thrown? + #@TODO: return or let it be thrown? return premium = False valid_untill = -1 - if "expire" in result.keys() and result["expire"]: + + if "expire" in result.keys() and result['expire']: premium = True - valid_untill = time.mktime(datetime.datetime.fromtimestamp(int(result["expire"])).timetuple()) + valid_untill = time.mktime(datetime.datetime.fromtimestamp(int(result['expire'])).timetuple()) - traffic_left = result["balance"] + 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): + + def login(self, user, password, data, req): self._usr = user - self._pwd = hashlib.md5(data["password"]).hexdigest() + self._pwd = hashlib.md5(password).hexdigest() self._req = req + try: - response = loads(self.runAuthQuery()) + response = json_loads(self.run_auth_query()) except Exception: - self.wrongPassword() + self.login_fail() if "errno" in response.keys(): - self.wrongPassword() + self.login_fail() + data['usr'] = self._usr data['pwd'] = self._pwd - def createAuthQuery(self): - query = self._api_query - query["username"] = self._usr - query["password"] = self._pwd + def create_auth_query(self): + 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 run_auth_query(self): + return self.load(self.API_URL, + post=self.create_auth_query()) diff --git a/module/plugins/accounts/RapidfileshareNet.py b/module/plugins/accounts/RapidfileshareNet.py index c0dd7eaee..069b30900 100644 --- a/module/plugins/accounts/RapidfileshareNet.py +++ b/module/plugins/accounts/RapidfileshareNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class RapidfileshareNet(XFSAccount): __name__ = "RapidfileshareNet" __type__ = "account" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __description__ = """Rapidfileshare.net account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/RapidgatorNet.py b/module/plugins/accounts/RapidgatorNet.py index 23d7aff53..5ce51a1ec 100644 --- a/module/plugins/accounts/RapidgatorNet.py +++ b/module/plugins/accounts/RapidgatorNet.py @@ -1,13 +1,16 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +import urlparse + +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class RapidgatorNet(Account): __name__ = "RapidgatorNet" __type__ = "account" - __version__ = "0.09" + __version__ = "0.11" + __status__ = "testing" __description__ = """Rapidgator.net account plugin""" __license__ = "GPLv3" @@ -17,34 +20,35 @@ class RapidgatorNet(Account): API_URL = "http://rapidgator.net/api/user" - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = None premium = False sid = None try: - sid = self.getAccountData(user).get('sid') + sid = self.get_data(user).get('sid', None) assert sid - html = req.load("%s/info" % self.API_URL, get={'sid': sid}) + html = self.load(urlparse.urljoin(self.API_URL, "info"), + get={'sid': sid}) - self.logDebug("API:USERINFO", html) + self.log_debug("API:USERINFO", html) json = json_loads(html) if json['response_status'] == 200: if "reset_in" in json['response']: - self.scheduleRefresh(user, json['response']['reset_in']) + self.schedule_refresh(user, json['response']['reset_in']) validuntil = json['response']['expire_date'] trafficleft = float(json['response']['traffic_left']) / 1024 #@TODO: Remove `/ 1024` in 0.4.10 premium = True else: - self.logError(json['response_details']) + self.log_error(json['response_details']) except Exception, e: - self.logError(e) + self.log_error(e) return {'validuntil' : validuntil, 'trafficleft': trafficleft, @@ -52,11 +56,13 @@ class RapidgatorNet(Account): 'sid' : sid} - def login(self, user, data, req): + def login(self, user, password, data, req): try: - html = req.load('%s/login' % self.API_URL, post={"username": user, "password": data['password']}) + html = self.load(urlparse.urljoin(self.API_URL, "login"), + post={'username': user, + 'password': password}) - self.logDebug("API:LOGIN", html) + self.log_debug("API:LOGIN", html) json = json_loads(html) @@ -64,9 +70,9 @@ class RapidgatorNet(Account): data['sid'] = str(json['response']['session_id']) return else: - self.logError(json['response_details']) + self.log_error(json['response_details']) except Exception, e: - self.logError(e) + self.log_error(e) - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/RapiduNet.py b/module/plugins/accounts/RapiduNet.py index 70f47b673..1ec29bd77 100644 --- a/module/plugins/accounts/RapiduNet.py +++ b/module/plugins/accounts/RapiduNet.py @@ -3,14 +3,15 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account from module.common.json_layer import json_loads class RapiduNet(Account): __name__ = "RapiduNet" __type__ = "account" - __version__ = "0.05" + __version__ = "0.07" + __status__ = "testing" __description__ = """Rapidu.net account plugin""" __license__ = "GPLv3" @@ -25,12 +26,12 @@ class RapiduNet(Account): TRAFFIC_LEFT_PATTERN = r'class="tipsyS"><b>(.+?)<' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = -1 premium = False - html = req.load("https://rapidu.net/", decode=True) + html = self.load("https://rapidu.net/") if re.search(self.PREMIUM_PATTERN, html): premium = True @@ -41,25 +42,25 @@ class RapiduNet(Account): m = re.search(self.TRAFFIC_LEFT_PATTERN, html) if m: - trafficleft = self.parseTraffic(m.group(1)) + trafficleft = self.parse_traffic(m.group(1)) return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium} - def login(self, user, data, req): - req.load("https://rapidu.net/ajax.php", - get={'a': "getChangeLang"}, - post={'_go' : "", - 'lang': "en"}) + def login(self, user, password, data, req): + self.load("https://rapidu.net/ajax.php", + get={'a': "getChangeLang"}, + post={'_go' : "", + 'lang': "en"}) - json = json_loads(req.load("https://rapidu.net/ajax.php", - get={'a': "getUserLogin"}, - post={'_go' : "", - 'login' : user, - 'pass' : data['password'], - 'remember': "1"})) + json = json_loads(self.load("https://rapidu.net/ajax.php", + get={'a': "getUserLogin"}, + post={'_go' : "", + 'login' : user, + 'pass' : password, + 'remember': "1"})) - self.logDebug(json) + self.log_debug(json) if not json['message'] == "success": - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/RarefileNet.py b/module/plugins/accounts/RarefileNet.py index 577a6c8f6..5f52ba147 100644 --- a/module/plugins/accounts/RarefileNet.py +++ b/module/plugins/accounts/RarefileNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class RarefileNet(XFSAccount): __name__ = "RarefileNet" __type__ = "account" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" __description__ = """RareFile.net account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/RealdebridCom.py b/module/plugins/accounts/RealdebridCom.py index 41d8a0975..718850c1a 100644 --- a/module/plugins/accounts/RealdebridCom.py +++ b/module/plugins/accounts/RealdebridCom.py @@ -2,39 +2,44 @@ import xml.dom.minidom as dom -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class RealdebridCom(Account): __name__ = "RealdebridCom" __type__ = "account" - __version__ = "0.45" + __version__ = "0.48" + __status__ = "testing" __description__ = """Real-Debrid.com account plugin""" __license__ = "GPLv3" __authors__ = [("Devirex Hazzard", "naibaf_11@yahoo.de")] - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): if self.pin_code: - return {"premium": False} - html = req.load("https://real-debrid.com/api/account.php") - xml = dom.parseString(html) - account_info = {"validuntil": float(xml.getElementsByTagName("expiration")[0].childNodes[0].nodeValue), - "trafficleft": -1} + return - return account_info + html = self.load("https://real-debrid.com/api/account.php") + xml = dom.parseString(html) + validuntil = float(xml.getElementsByTagName("expiration")[0].childNodes[0].nodeValue) - def login(self, user, data, req): + return {'validuntil' : validuntil, + 'trafficleft': -1 , + 'premium' : True } + + + def login(self, user, password, data, req): self.pin_code = False - html = req.load("https://real-debrid.com/ajax/login.php", - get={"user": user, "pass": data['password']}, - decode=True) + + html = self.load("https://real-debrid.com/ajax/login.php", + get={'user': user, + 'pass': password}) if "Your login informations are incorrect" in html: - self.wrongPassword() + self.login_fail() elif "PIN Code required" in html: - self.logWarning(_("PIN code required. Please login to https://real-debrid.com using the PIN or disable the double authentication in your control panel on https://real-debrid.com")) + self.log_warning(_("PIN code required. Please login to https://real-debrid.com using the PIN or disable the double authentication in your control panel on https://real-debrid.com")) self.pin_code = True diff --git a/module/plugins/accounts/RehostTo.py b/module/plugins/accounts/RehostTo.py index 04e71c9ad..36e5e33eb 100644 --- a/module/plugins/accounts/RehostTo.py +++ b/module/plugins/accounts/RehostTo.py @@ -1,40 +1,43 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class RehostTo(Account): __name__ = "RehostTo" __type__ = "account" - __version__ = "0.16" + __version__ = "0.18" + __status__ = "testing" __description__ = """Rehost.to account plugin""" __license__ = "GPLv3" __authors__ = [("RaNaN", "RaNaN@pyload.org")] - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): premium = False trafficleft = None validuntil = -1 session = "" - html = req.load("http://rehost.to/api.php", - get={'cmd' : "login", 'user': user, - 'pass': self.getAccountData(user)['password']}) + html = self.load("https://rehost.to/api.php", + get={'cmd' : "login", + 'user': user, + 'pass': password}) try: session = html.split(",")[1].split("=")[1] - html = req.load("http://rehost.to/api.php", - get={'cmd': "get_premium_credits", 'long_ses': session}) + html = self.load("http://rehost.to/api.php", + get={'cmd' : "get_premium_credits", + 'long_ses': session}) if html.strip() == "0,0" or "ERROR" in html: - self.logDebug(html) + self.log_debug(html) else: traffic, valid = html.split(",") premium = True - trafficleft = self.parseTraffic(traffic + "MB") + trafficleft = self.parse_traffic(traffic + "MB") validuntil = float(valid) finally: @@ -44,11 +47,12 @@ class RehostTo(Account): 'session' : session} - def login(self, user, data, req): - html = req.load("http://rehost.to/api.php", - get={'cmd': "login", 'user': user, 'pass': data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://rehost.to/api.php", + get={'cmd': "login", + 'user': user, + 'pass': password}) if "ERROR" in html: - self.logDebug(html) - self.wrongPassword() + self.log_debug(html) + self.login_fail() diff --git a/module/plugins/accounts/RyushareCom.py b/module/plugins/accounts/RyushareCom.py index 8c56ff20f..3ab907a76 100644 --- a/module/plugins/accounts/RyushareCom.py +++ b/module/plugins/accounts/RyushareCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class RyushareCom(XFSAccount): __name__ = "RyushareCom" __type__ = "account" - __version__ = "0.06" + __version__ = "0.07" + __status__ = "testing" __description__ = """Ryushare.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/SafesharingEu.py b/module/plugins/accounts/SafesharingEu.py index 2e58d33b3..eb84d502f 100644 --- a/module/plugins/accounts/SafesharingEu.py +++ b/module/plugins/accounts/SafesharingEu.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class SafesharingEu(XFSAccount): __name__ = "SafesharingEu" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Safesharing.eu account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/SecureUploadEu.py b/module/plugins/accounts/SecureUploadEu.py index b335c94da..a81030b67 100644 --- a/module/plugins/accounts/SecureUploadEu.py +++ b/module/plugins/accounts/SecureUploadEu.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class SecureUploadEu(XFSAccount): __name__ = "SecureUploadEu" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """SecureUpload.eu account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/SendmywayCom.py b/module/plugins/accounts/SendmywayCom.py index 4fcbe0b7a..2875e0d46 100644 --- a/module/plugins/accounts/SendmywayCom.py +++ b/module/plugins/accounts/SendmywayCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class SendmywayCom(XFSAccount): __name__ = "SendmywayCom" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Sendmyway.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/SharebeastCom.py b/module/plugins/accounts/SharebeastCom.py new file mode 100644 index 000000000..a104a4a46 --- /dev/null +++ b/module/plugins/accounts/SharebeastCom.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSAccount import XFSAccount + + +class SharebeastCom(XFSAccount): + __name__ = "SharebeastCom" + __type__ = "account" + __version__ = "0.02" + __status__ = "testing" + + __description__ = """Sharebeast.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + HOSTER_DOMAIN = "sharebeast.com" diff --git a/module/plugins/accounts/ShareonlineBiz.py b/module/plugins/accounts/ShareonlineBiz.py index 4214b4401..87bbc4632 100644 --- a/module/plugins/accounts/ShareonlineBiz.py +++ b/module/plugins/accounts/ShareonlineBiz.py @@ -2,54 +2,58 @@ import re -from module.plugins.Account import Account +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import set_cookie class ShareonlineBiz(Account): __name__ = "ShareonlineBiz" __type__ = "account" - __version__ = "0.33" + __version__ = "0.39" + __status__ = "testing" __description__ = """Share-online.biz account plugin""" __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - def api_response(self, user, req): - return req.load("http://api.share-online.biz/cgi-bin", + def api_response(self, user, password, req): + res = self.load("https://api.share-online.biz/cgi-bin", get={'q' : "userdetails", 'aux' : "traffic", 'username': user, - 'password': self.getAccountData(user)['password']}) + 'password': password}, + decode=False) + self.log_debug(res) - def loadAccountInfo(self, user, req): - premium = False - validuntil = None - trafficleft = -1 - maxtraffic = 100 * 1024 * 1024 * 1024 #: 100 GB + api = dict(line.split("=") for line in res.splitlines() if "=" in line) + + if not 'a' in api: + self.login_fail(res.strip('*').strip()) - api = {} - for line in self.api_response(user, req).splitlines(): - if "=" in line: - key, value = line.split("=") - api[key] = value + if api['a'].lower() == "not_available": + self.login_fail(_("No info available")) - self.logDebug(api) + return api - if api['a'].lower() != "not_available": - req.cj.setCookie("share-online.biz", 'a', api['a']) - premium = api['group'] in ("PrePaid", "Premium", "Penalty-Premium") + def parse_info(self, user, password, data, req): + premium = False + validuntil = None + trafficleft = -1 + maxtraffic = 100 * 1024 * 1024 * 1024 #: 100 GB - validuntil = float(api['expire_date']) + api = self.api_response(user, password, req) - traffic = float(api['traffic_1d'].split(";")[0]) + premium = api['group'] in ("PrePaid", "Premium", "Penalty-Premium") + validuntil = float(api['expire_date']) + traffic = float(api['traffic_1d'].split(";")[0]) - if maxtraffic > traffic: - trafficleft = maxtraffic - traffic - else: - trafficleft = -1 + if maxtraffic > traffic: + trafficleft = maxtraffic - traffic + else: + trafficleft = -1 maxtraffic /= 1024 #@TODO: Remove `/ 1024` in 0.4.10 trafficleft /= 1024 #@TODO: Remove `/ 1024` in 0.4.10 @@ -60,9 +64,6 @@ class ShareonlineBiz(Account): 'maxtraffic' : maxtraffic} - def login(self, user, data, req): - html = self.api_response(user, req) - err = re.search(r'\*\*(.+?)\*\*', html) - if err: - self.logError(err.group(1)) - self.wrongPassword() + def login(self, user, password, data, req): + api = self.api_response(user, password, req) + set_cookie(req.cj, "share-online.biz", 'a', api['a']) diff --git a/module/plugins/accounts/SimplyPremiumCom.py b/module/plugins/accounts/SimplyPremiumCom.py index 8caf600f9..a5c69f51c 100644 --- a/module/plugins/accounts/SimplyPremiumCom.py +++ b/module/plugins/accounts/SimplyPremiumCom.py @@ -1,27 +1,29 @@ # -*- coding: utf-8 -*- from module.common.json_layer import json_loads -from module.plugins.Account import Account +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import set_cookie class SimplyPremiumCom(Account): __name__ = "SimplyPremiumCom" __type__ = "account" - __version__ = "0.05" + __version__ = "0.08" + __status__ = "testing" __description__ = """Simply-Premium.com account plugin""" __license__ = "GPLv3" __authors__ = [("EvolutionClip", "evolutionclip@live.de")] - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): premium = False validuntil = -1 trafficleft = None - json_data = req.load('http://www.simply-premium.com/api/user.php?format=json') + json_data = self.load('http://www.simply-premium.com/api/user.php?format=json') - self.logDebug("JSON data: %s" % json_data) + self.log_debug("JSON data: %s" % json_data) json_data = json_loads(json_data) @@ -34,15 +36,14 @@ class SimplyPremiumCom(Account): if 'remain_traffic' in json_data['result'] and json_data['result']['remain_traffic']: trafficleft = float(json_data['result']['remain_traffic']) / 1024 #@TODO: Remove `/ 1024` in 0.4.10 - return {"premium": premium, "validuntil": validuntil, "trafficleft": trafficleft} + return {'premium': premium, 'validuntil': validuntil, 'trafficleft': trafficleft} - def login(self, user, data, req): - req.cj.setCookie("simply-premium.com", "lang", "EN") + def login(self, user, password, data, req): + set_cookie(req.cj, "simply-premium.com", "lang", "EN") - html = req.load("http://www.simply-premium.com/login.php", - post={'key': user} if not data['password'] else {'login_name': user, 'login_pass': data['password']}, - decode=True) + html = self.load("https://www.simply-premium.com/login.php", + post={'key': user} if not password else {'login_name': user, 'login_pass': password}) if 'logout' not in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/SimplydebridCom.py b/module/plugins/accounts/SimplydebridCom.py index 24108eb0b..84c38227e 100644 --- a/module/plugins/accounts/SimplydebridCom.py +++ b/module/plugins/accounts/SimplydebridCom.py @@ -2,34 +2,36 @@ import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class SimplydebridCom(Account): __name__ = "SimplydebridCom" __type__ = "account" - __version__ = "0.11" + __version__ = "0.13" + __status__ = "testing" __description__ = """Simply-Debrid.com account plugin""" __license__ = "GPLv3" __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")] - def loadAccountInfo(self, user, req): - get_data = {'login': 2, 'u': self.loginname, 'p': self.password} - res = req.load("http://simply-debrid.com/api.php", get=get_data, decode=True) + def parse_info(self, user, password, data, req): + res = self.load("http://simply-debrid.com/api.php", + get={'login': 2, + 'u' : user, + 'p' : password}) data = [x.strip() for x in res.split(";")] if str(data[0]) != "1": - return {"premium": False} + return {'premium': False} else: - return {"trafficleft": -1, "validuntil": time.mktime(time.strptime(str(data[2]), "%d/%m/%Y"))} + return {'trafficleft': -1, 'validuntil': time.mktime(time.strptime(str(data[2]), "%d/%m/%Y"))} - def login(self, user, data, req): - self.loginname = user - self.password = data['password'] - get_data = {'login': 1, 'u': self.loginname, 'p': self.password} - - res = req.load("http://simply-debrid.com/api.php", get=get_data, decode=True) + def login(self, user, password, data, req): + res = self.load("https://simply-debrid.com/api.php", + get={'login': 1, + 'u' : user, + 'p' : password}) if res != "02: loggin success": - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/SmoozedCom.py b/module/plugins/accounts/SmoozedCom.py index 1c303331b..9c2451794 100644 --- a/module/plugins/accounts/SmoozedCom.py +++ b/module/plugins/accounts/SmoozedCom.py @@ -20,37 +20,38 @@ except ImportError: return b2a_hex(pbkdf2(self.passphrase, self.salt, self.iterations, octets)) from module.common.json_layer import json_loads -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class SmoozedCom(Account): __name__ = "SmoozedCom" __type__ = "account" - __version__ = "0.05" + __version__ = "0.07" + __status__ = "testing" __description__ = """Smoozed.com account plugin""" __license__ = "GPLv3" __authors__ = [("", "")] - def loadAccountInfo(self, user, req): - status = self.getAccountStatus(user, req) + def parse_info(self, user, password, data, req): + status = self.get_account_status(user, password, req) - self.logDebug(status) + self.log_debug(status) if status['state'] != 'ok': info = {'validuntil' : None, 'trafficleft': None, 'premium' : False} else: - # Parse account info - info = {'validuntil' : float(status["data"]["user"]["user_premium"]), - 'trafficleft': max(0, status["data"]["traffic"][1] - status["data"]["traffic"][0]), - 'session' : status["data"]["session_key"], - 'hosters' : [hoster["name"] for hoster in status["data"]["hoster"]]} + #: Parse account info + info = {'validuntil' : float(status['data']['user']['user_premium']), + 'trafficleft': max(0, status['data']['traffic'][1] - status['data']['traffic'][0]), + 'session' : status['data']['session_key'], + 'hosters' : [hoster['name'] for hoster in status['data']['hoster']]} if info['validuntil'] < time.time(): - if float(status["data"]["user"].get("user_trial", 0)) > time.time(): + if float(status['data']['user'].get("user_trial", 0)) > time.time(): info['premium'] = True else: info['premium'] = False @@ -60,19 +61,20 @@ class SmoozedCom(Account): return info - def login(self, user, data, req): - # Get user data from premiumize.me - status = self.getAccountStatus(user, req) + def login(self, user, password, data, req): + #: Get user data from premiumize.me + status = self.get_account_status(user, password, req) - # Check if user and password are valid + #: Check if user and password are valid if status['state'] != 'ok': - self.wrongPassword() + self.login_fail() - def getAccountStatus(self, user, req): - password = self.getAccountData(user)['password'] + def get_account_status(self, user, password, req): + password = password salt = hashlib.sha256(password).hexdigest() encrypted = PBKDF2(password, salt, iterations=1000).hexread(32) - return json_loads(req.load("http://www2.smoozed.com/api/login", - get={'auth': user, 'password': encrypted})) + return json_loads(self.load("http://www2.smoozed.com/api/login", + get={'auth': user, + 'password': encrypted})) diff --git a/module/plugins/accounts/StahnuTo.py b/module/plugins/accounts/StahnuTo.py deleted file mode 100644 index 882dbd2c3..000000000 --- a/module/plugins/accounts/StahnuTo.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -from module.plugins.Account import Account - - -class StahnuTo(Account): - __name__ = "StahnuTo" - __type__ = "account" - __version__ = "0.05" - - __description__ = """StahnuTo account plugin""" - __license__ = "GPLv3" - __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - - - def loadAccountInfo(self, user, req): - html = req.load("http://www.stahnu.to/") - - m = re.search(r'>VIP: (\d+.*)<', html) - trafficleft = self.parseTraffic(m.group(1)) if m else 0 - - return {"premium": trafficleft > 512, "trafficleft": trafficleft, "validuntil": -1} - - - def login(self, user, data, req): - html = req.load("http://www.stahnu.to/login.php", - post={"username": user, - "password": data['password'], - "submit": "Login"}, - decode=True) - - if not '<a href="logout.php">' in html: - self.wrongPassword() diff --git a/module/plugins/accounts/StreamcloudEu.py b/module/plugins/accounts/StreamcloudEu.py index aa1eafcbd..9549896cc 100644 --- a/module/plugins/accounts/StreamcloudEu.py +++ b/module/plugins/accounts/StreamcloudEu.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class StreamcloudEu(XFSAccount): __name__ = "StreamcloudEu" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Streamcloud.eu account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/TurbobitNet.py b/module/plugins/accounts/TurbobitNet.py index 010fbc270..206e7874f 100644 --- a/module/plugins/accounts/TurbobitNet.py +++ b/module/plugins/accounts/TurbobitNet.py @@ -3,21 +3,23 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import set_cookie class TurbobitNet(Account): __name__ = "TurbobitNet" __type__ = "account" - __version__ = "0.02" + __version__ = "0.05" + __status__ = "testing" __description__ = """TurbobitNet account plugin""" __license__ = "GPLv3" __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - def loadAccountInfo(self, user, req): - html = req.load("http://turbobit.net") + def parse_info(self, user, password, data, req): + html = self.load("http://turbobit.net") m = re.search(r'<u>Turbo Access</u> to ([\d.]+)', html) if m: @@ -27,17 +29,16 @@ class TurbobitNet(Account): premium = False validuntil = -1 - return {"premium": premium, "trafficleft": -1, "validuntil": validuntil} + return {'premium': premium, 'trafficleft': -1, 'validuntil': validuntil} - def login(self, user, data, req): - req.cj.setCookie("turbobit.net", "user_lang", "en") + def login(self, user, password, data, req): + set_cookie(req.cj, "turbobit.net", "user_lang", "en") - html = req.load("http://turbobit.net/user/login", - post={"user[login]": user, - "user[pass]": data['password'], - "user[submit]": "Login"}, - decode=True) + html = self.load("http://turbobit.net/user/login", + post={"user[login]" : user, + "user[pass]" : password, + "user[submit]": "Login"}) if not '<div class="menu-item user-name">' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/TusfilesNet.py b/module/plugins/accounts/TusfilesNet.py index d06ba0583..c549bbaf7 100644 --- a/module/plugins/accounts/TusfilesNet.py +++ b/module/plugins/accounts/TusfilesNet.py @@ -9,9 +9,10 @@ from module.plugins.internal.XFSAccount import XFSAccount class TusfilesNet(XFSAccount): __name__ = "TusfilesNet" __type__ = "account" - __version__ = "0.06" + __version__ = "0.07" + __status__ = "testing" - __description__ = """ Tusfile.net account plugin """ + __description__ = """Tusfile.net account plugin""" __license__ = "GPLv3" __authors__ = [("guidobelix", "guidobelix@hotmail.it")] diff --git a/module/plugins/accounts/UlozTo.py b/module/plugins/accounts/UlozTo.py index f95c8834b..00e125dbc 100644 --- a/module/plugins/accounts/UlozTo.py +++ b/module/plugins/accounts/UlozTo.py @@ -3,13 +3,14 @@ import re import urlparse -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class UlozTo(Account): __name__ = "UlozTo" __type__ = "account" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __description__ = """Uloz.to account plugin""" __license__ = "GPLv3" @@ -20,8 +21,8 @@ class UlozTo(Account): TRAFFIC_LEFT_PATTERN = r'<li class="menu-kredit"><a .*?title=".+?GB = ([\d.]+) MB"' - def loadAccountInfo(self, user, req): - html = req.load("http://www.ulozto.net/", decode=True) + def parse_info(self, user, password, data, req): + html = self.load("http://www.ulozto.net/") m = re.search(self.TRAFFIC_LEFT_PATTERN, html) @@ -31,19 +32,18 @@ class UlozTo(Account): return {'validuntil': -1, 'trafficleft': trafficleft, 'premium': premium} - def login(self, user, data, req): - login_page = req.load('http://www.ulozto.net/?do=web-login', decode=True) + def login(self, user, password, data, req): + login_page = self.load('http://www.ulozto.net/?do=web-login') action = re.findall('<form action="(.+?)"', login_page)[1].replace('&', '&') token = re.search('_token_" value="(.+?)"', login_page).group(1) - html = req.load(urlparse.urljoin("http://www.ulozto.net/", action), - post={'_token_' : token, - 'do' : "loginForm-submit", - 'login' : u"PÅihlásit", - 'password': data['password'], - 'username': user, - 'remember': "on"}, - decode=True) + html = self.load(urlparse.urljoin("https://www.ulozto.net/", action), + post={'_token_' : token, + 'do' : "loginForm-submit", + 'login' : u"PÅihlásit", + 'password': password, + 'username': user, + 'remember': "on"}) if '<div class="flash error">' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/UploadableCh.py b/module/plugins/accounts/UploadableCh.py index 86ae5dd17..9c2649e51 100644 --- a/module/plugins/accounts/UploadableCh.py +++ b/module/plugins/accounts/UploadableCh.py @@ -1,20 +1,21 @@ # -*- coding: utf-8 -*- -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class UploadableCh(Account): __name__ = "UploadableCh" __type__ = "account" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" __description__ = """Uploadable.ch account plugin""" __license__ = "GPLv3" __authors__ = [("Sasch", "gsasch@gmail.com")] - def loadAccountInfo(self, user, req): - html = req.load("http://www.uploadable.ch/login.php") + def parse_info(self, user, password, data, req): + html = self.load("http://www.uploadable.ch/login.php") premium = '<a href="/logout.php"' in html trafficleft = -1 if premium else None @@ -22,13 +23,12 @@ class UploadableCh(Account): return {'validuntil': None, 'trafficleft': trafficleft, 'premium': premium} #@TODO: validuntil - def login(self, user, data, req): - html = req.load("http://www.uploadable.ch/login.php", - post={'userName' : user, - 'userPassword' : data["password"], - 'autoLogin' : "1", - 'action__login': "normalLogin"}, - decode=True) + def login(self, user, password, data, req): + html = self.load("http://www.uploadable.ch/login.php", + post={'userName' : user, + 'userPassword' : password, + 'autoLogin' : "1", + 'action__login': "normalLogin"}) if "Login failed" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/UploadcCom.py b/module/plugins/accounts/UploadcCom.py index d1e1a2ead..5b834ac3b 100644 --- a/module/plugins/accounts/UploadcCom.py +++ b/module/plugins/accounts/UploadcCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class UploadcCom(XFSAccount): __name__ = "UploadcCom" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """Uploadc.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/UploadedTo.py b/module/plugins/accounts/UploadedTo.py index d1556b6db..59d3fcff9 100644 --- a/module/plugins/accounts/UploadedTo.py +++ b/module/plugins/accounts/UploadedTo.py @@ -3,30 +3,33 @@ import re import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class UploadedTo(Account): __name__ = "UploadedTo" __type__ = "account" - __version__ = "0.30" + __version__ = "0.35" + __status__ = "testing" __description__ = """Uploaded.to account plugin""" __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - PREMIUM_PATTERN = r'<em>Premium</em>' - VALID_UNTIL_PATTERN = r'<td>Duration:</td>\s*<th>(.+?)<' + COOKIES = False + + PREMIUM_PATTERN = r'<em>Premium</em>' + VALID_UNTIL_PATTERN = r'<td>Duration:</td>\s*<th>(.+?)<' TRAFFIC_LEFT_PATTERN = r'<b class="cB">(?P<S>[\d.,]+) (?P<U>[\w^_]+)' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = None premium = None - html = req.load("http://uploaded.net/me") + html = self.load("http://uploaded.net/me") premium = True if re.search(self.PREMIUM_PATTERN, html) else False @@ -53,19 +56,20 @@ class UploadedTo(Account): trafficleft = float(size.replace(',', '.')) / 1024 trafficleft *= 1 << 40 else: - trafficleft = self.parseTraffic(size + unit) + trafficleft = self.parse_traffic(size + unit) return {'validuntil' : validuntil, 'trafficleft': trafficleft, 'premium' : premium} - def login(self, user, data, req): - # req.cj.setCookie("uploaded.net", "lang", "en") + def login(self, user, password, data, req): + self.load("http://uploaded.net/language/en") - html = req.load("http://uploaded.net/io/login", - post={'id': user, 'pw': data['password'], '_': ""}, - decode=True) + html = self.load("http://uploaded.net/io/login", + post={'id': user, + 'pw': password}) - if '"err"' in html: - self.wrongPassword() + m = re.search(r'"err":"(.+?)"', html) + if m is not None: + self.login_fail(m.group(1)) diff --git a/module/plugins/accounts/UploadheroCom.py b/module/plugins/accounts/UploadheroCom.py index 714f5b0a6..f31b01d03 100644 --- a/module/plugins/accounts/UploadheroCom.py +++ b/module/plugins/accounts/UploadheroCom.py @@ -4,39 +4,40 @@ import re import datetime import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class UploadheroCom(Account): __name__ = "UploadheroCom" __type__ = "account" - __version__ = "0.21" + __version__ = "0.23" + __status__ = "testing" __description__ = """Uploadhero.co account plugin""" __license__ = "GPLv3" __authors__ = [("mcmyst", "mcmyst@hotmail.fr")] - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): premium_pattern = re.compile('Il vous reste <span class="bleu">(\d+)</span> jours premium') - data = self.getAccountData(user) - html = req.load("http://uploadhero.co/my-account") + data = self.get_data(user) + html = self.load("http://uploadhero.co/my-account") if premium_pattern.search(html): end_date = datetime.date.today() + datetime.timedelta(days=int(premium_pattern.search(html).group(1))) end_date = time.mktime(future.timetuple()) - account_info = {"validuntil": end_date, "trafficleft": -1, "premium": True} + account_info = {'validuntil': end_date, 'trafficleft': -1, 'premium': True} else: - account_info = {"validuntil": -1, "trafficleft": -1, "premium": False} + account_info = {'validuntil': -1, 'trafficleft': -1, 'premium': False} return account_info - def login(self, user, data, req): - html = req.load("http://uploadhero.co/lib/connexion.php", - post={"pseudo_login": user, "password_login": data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load("http://uploadhero.co/lib/connexion.php", + post={'pseudo_login': user, + 'password_login': password}) if "mot de passe invalide" in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/UploadingCom.py b/module/plugins/accounts/UploadingCom.py index a20c44535..d269abde7 100644 --- a/module/plugins/accounts/UploadingCom.py +++ b/module/plugins/accounts/UploadingCom.py @@ -3,14 +3,15 @@ import re import time -from module.plugins.Account import Account -from module.plugins.internal.SimpleHoster import set_cookies +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import set_cookies class UploadingCom(Account): __name__ = "UploadingCom" __type__ = "account" - __version__ = "0.12" + __version__ = "0.14" + __status__ = "testing" __description__ = """Uploading.com account plugin""" __license__ = "GPLv3" @@ -21,25 +22,25 @@ class UploadingCom(Account): VALID_UNTIL_PATTERN = r'Valid Until:(.+?)<' - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = None premium = None - html = req.load("http://uploading.com/") + html = self.load("http://uploading.com/") premium = False if re.search(self.PREMIUM_PATTERN, html) else True m = re.search(self.VALID_UNTIL_PATTERN, html) if m: expiredate = m.group(1).strip() - self.logDebug("Expire date: " + expiredate) + self.log_debug("Expire date: " + expiredate) try: validuntil = time.mktime(time.strptime(expiredate, "%b %d, %Y")) except Exception, e: - self.logError(e) + self.log_error(e) else: if validuntil > time.mktime(time.gmtime()): @@ -53,13 +54,15 @@ class UploadingCom(Account): 'premium' : premium} - def login(self, user, data, req): + def login(self, user, password, data, req): set_cookies(req.cj, [("uploading.com", "lang" , "1" ), ("uploading.com", "language", "1" ), ("uploading.com", "setlang" , "en"), ("uploading.com", "_lang" , "en")]) - req.load("http://uploading.com/") - req.load("http://uploading.com/general/login_form/?JsHttpRequest=%s-xml" % long(time.time() * 1000), - post={'email': user, 'password': data['password'], 'remember': "on"}) + self.load("http://uploading.com/") + self.load("https://uploading.com/general/login_form/?JsHttpRequest=%s-xml" % long(time.time() * 1000), + post={'email' : user, + 'password': password, + 'remember': "on"}) diff --git a/module/plugins/accounts/UptoboxCom.py b/module/plugins/accounts/UptoboxCom.py index c40dbd6e6..68aaecc47 100644 --- a/module/plugins/accounts/UptoboxCom.py +++ b/module/plugins/accounts/UptoboxCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class UptoboxCom(XFSAccount): __name__ = "UptoboxCom" __type__ = "account" - __version__ = "0.08" + __version__ = "0.09" + __status__ = "testing" __description__ = """DDLStorage.com account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/VidPlayNet.py b/module/plugins/accounts/VidPlayNet.py index 5bfc24963..d543c5671 100644 --- a/module/plugins/accounts/VidPlayNet.py +++ b/module/plugins/accounts/VidPlayNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class VidPlayNet(XFSAccount): __name__ = "VidPlayNet" __type__ = "account" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __description__ = """VidPlay.net account plugin""" __license__ = "GPLv3" diff --git a/module/plugins/accounts/WebshareCz.py b/module/plugins/accounts/WebshareCz.py index f032e2317..bbfb90a92 100644 --- a/module/plugins/accounts/WebshareCz.py +++ b/module/plugins/accounts/WebshareCz.py @@ -6,13 +6,14 @@ import time from passlib.hash import md5_crypt -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class WebshareCz(Account): __name__ = "WebshareCz" __type__ = "account" - __version__ = "0.07" + __version__ = "0.10" + __status__ = "testing" __description__ = """Webshare.cz account plugin""" __license__ = "GPLv3" @@ -24,45 +25,42 @@ class WebshareCz(Account): TRAFFIC_LEFT_PATTERN = r'<bytes>(.+)</bytes>' - def loadAccountInfo(self, user, req): - html = req.load("https://webshare.cz/api/user_data/", - post={'wst': self.infos['wst']}, - decode=True) + def parse_info(self, user, password, data, req): + html = self.load("https://webshare.cz/api/user_data/", + post={'wst': self.get_data(user).get('wst', None)}) - self.logDebug("Response: " + html) + self.log_debug("Response: " + html) expiredate = re.search(self.VALID_UNTIL_PATTERN, html).group(1) - self.logDebug("Expire date: " + expiredate) + self.log_debug("Expire date: " + expiredate) validuntil = time.mktime(time.strptime(expiredate, "%Y-%m-%d %H:%M:%S")) - trafficleft = self.parseTraffic(re.search(self.TRAFFIC_LEFT_PATTERN, html).group(1)) + trafficleft = self.parse_traffic(re.search(self.TRAFFIC_LEFT_PATTERN, html).group(1)) premium = validuntil > time.time() return {'validuntil': validuntil, 'trafficleft': -1, 'premium': premium} - def login(self, user, data, req): - salt = req.load("https://webshare.cz/api/salt/", - post={'username_or_email': user, - 'wst' : ""}, - decode=True) + def login(self, user, password, data, req): + salt = self.load("https://webshare.cz/api/salt/", + post={'username_or_email': user, + 'wst' : ""}) if "<status>OK</status>" not in salt: - self.wrongPassword() + self.login_fail() salt = re.search('<salt>(.+)</salt>', salt).group(1) - password = hashlib.sha1(md5_crypt.encrypt(data["password"], salt=salt)).hexdigest() + password = hashlib.sha1(md5_crypt.encrypt(password, salt=salt)).hexdigest() digest = hashlib.md5(user + ":Webshare:" + password).hexdigest() - login = req.load("https://webshare.cz/api/login/", - post={'digest' : digest, - 'keep_logged_in' : 1, - 'password' : password, - 'username_or_email': user, - 'wst' : ""}, - decode=True) + login = self.load("https://webshare.cz/api/login/", + post={'digest' : digest, + 'keep_logged_in' : 1, + 'password' : password, + 'username_or_email': user, + 'wst' : ""}) if "<status>OK</status>" not in login: - self.wrongPassword() + self.login_fail() - 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..ea409fd58 --- /dev/null +++ b/module/plugins/accounts/WorldbytezCom.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.XFSAccount import XFSAccount + + +class WorldbytezCom(XFSAccount): + __name__ = "WorldbytezCom" + __type__ = "account" + __version__ = "0.02" + __status__ = "testing" + + __description__ = """Worldbytez.com account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + HOSTER_DOMAIN = "worldbytez.com" diff --git a/module/plugins/accounts/XFileSharingPro.py b/module/plugins/accounts/XFileSharingPro.py index 8dc7f3a30..f21247cf4 100644 --- a/module/plugins/accounts/XFileSharingPro.py +++ b/module/plugins/accounts/XFileSharingPro.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSAccount import XFSAccount class XFileSharingPro(XFSAccount): __name__ = "XFileSharingPro" __type__ = "account" - __version__ = "0.06" + __version__ = "0.09" + __status__ = "testing" __description__ = """XFileSharingPro multi-purpose account plugin""" __license__ = "GPLv3" @@ -16,19 +17,10 @@ class XFileSharingPro(XFSAccount): HOSTER_DOMAIN = None - def init(self): - if self.HOSTER_DOMAIN: - return super(XFileSharingPro, self).init() + def login(self, user, password, data, req): + try: + return super(XFileSharingPro, self).login(user, data, req) - - def loadAccountInfo(self, user, req): - return super(XFileSharingPro if self.HOSTER_DOMAIN else XFSAccount, self).loadAccountInfo(user, req) - - - def login(self, user, data, req): - if self.HOSTER_DOMAIN: - try: - return super(XFileSharingPro, self).login(user, data, req) - except Exception: - self.HOSTER_URL = self.HOSTER_URL.replace("www.", "") - return super(XFileSharingPro, self).login(user, data, req) + except Fail: + self.HOSTER_URL = self.HOSTER_URL.replace("www.", "") + return super(XFileSharingPro, self).login(user, data, req) diff --git a/module/plugins/accounts/YibaishiwuCom.py b/module/plugins/accounts/YibaishiwuCom.py index 33602a2fe..c5dda0921 100644 --- a/module/plugins/accounts/YibaishiwuCom.py +++ b/module/plugins/accounts/YibaishiwuCom.py @@ -2,13 +2,14 @@ import re -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class YibaishiwuCom(Account): __name__ = "YibaishiwuCom" __type__ = "account" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __description__ = """115.com account plugin""" __license__ = "GPLv3" @@ -18,23 +19,22 @@ class YibaishiwuCom(Account): ACCOUNT_INFO_PATTERN = r'var USER_PERMISSION = {(.*?)}' - def loadAccountInfo(self, user, req): - #self.relogin(user) - html = req.load("http://115.com/", decode=True) + def parse_info(self, user, password, data, req): + # self.relogin(user) + html = self.load("http://115.com/") m = re.search(self.ACCOUNT_INFO_PATTERN, html, re.S) premium = True if m and 'is_vip: 1' in m.group(1) else False validuntil = trafficleft = (-1 if m else 0) - return dict({"validuntil": validuntil, "trafficleft": trafficleft, "premium": premium}) + return dict({'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium}) - def login(self, user, data, req): - html = req.load("http://passport.115.com/?ac=login", - post={"back": "http://www.115.com/", - "goto": "http://115.com/", - "login[account]": user, - "login[passwd]": data['password']}, - decode=True) + def login(self, user, password, data, req): + html = self.load("https://passport.115.com/?ac=login", + post={'back' : "http://www.115.com/", + 'goto' : "http://115.com/", + "login[account]": user, + "login[passwd]" : password}) if not 'var USER_PERMISSION = {' in html: - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/accounts/ZeveraCom.py b/module/plugins/accounts/ZeveraCom.py index 9bc6d0487..4138ba3cc 100644 --- a/module/plugins/accounts/ZeveraCom.py +++ b/module/plugins/accounts/ZeveraCom.py @@ -2,13 +2,14 @@ import time -from module.plugins.Account import Account +from module.plugins.internal.Account import Account class ZeveraCom(Account): __name__ = "ZeveraCom" __type__ = "account" - __version__ = "0.26" + __version__ = "0.28" + __status__ = "testing" __description__ = """Zevera.com account plugin""" __license__ = "GPLv3" @@ -26,13 +27,13 @@ class ZeveraCom(Account): def init(self): if not self.HOSTER_DOMAIN: - self.logError(_("Missing HOSTER_DOMAIN")) + self.log_error(_("Missing HOSTER_DOMAIN")) if not hasattr(self, "API_URL"): self.API_URL = "http://api.%s/jDownloader.ashx" % (self.HOSTER_DOMAIN or "") - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = None premium = False @@ -47,12 +48,12 @@ class ZeveraCom(Account): return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium} - def login(self, user, data, req): + def login(self, user, password, data, req): self.user = user - self.password = data['password'] + self.password = password if self.api_response(req) == "No trafic": - self.wrongPassword() + self.login_fail() def api_response(self, req, just_header=False, **kwargs): @@ -62,12 +63,11 @@ class ZeveraCom(Account): get_data.update(kwargs) - res = req.load(self.API_URL, - get=get_data, - just_header=just_header, - decode=True) + res = self.load(self.API_URL, + get=get_data, + just_header=just_header) - self.logDebug(res) + self.log_debug(res) if ':' in res: if not just_header: diff --git a/module/plugins/internal/AdYouLike.py b/module/plugins/captcha/AdYouLike.py index a9c194dda..f91b5805c 100644 --- a/module/plugins/internal/AdYouLike.py +++ b/module/plugins/captcha/AdYouLike.py @@ -3,13 +3,14 @@ import re from module.common.json_layer import json_loads -from module.plugins.internal.Captcha import Captcha +from module.plugins.internal.CaptchaService import CaptchaService -class AdYouLike(Captcha): +class AdYouLike(CaptchaService): __name__ = "AdYouLike" __type__ = "captcha" - __version__ = "0.06" + __version__ = "0.07" + __status__ = "testing" __description__ = """AdYouLike captcha service plugin""" __license__ = "GPLv3" @@ -20,28 +21,28 @@ class AdYouLike(Captcha): CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' - def detect_key(self, html=None): - html = html or self.retrieve_html() + def detect_key(self, data=None): + html = data or self.retrieve_data() 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) + self.log_debug("Ayl: %s | Callback: %s" % self.key) + return self.key #: Key is the tuple(ayl, callback) else: - self.logWarning("Ayl or callback pattern not found") + self.log_warning(_("Ayl or callback pattern not found")) return None - def challenge(self, key=None, html=None): - ayl, callback = key or self.retrieve_key(html) + def challenge(self, key=None, data=None): + ayl, callback = key or self.retrieve_key(data) - # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, - # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} + #: {'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", + html = self.plugin.load("http://api-ayl.appspot.com/challenge", get={'key' : ayl['adyoulike']['key'], 'env' : ayl['all']['env'], 'callback': callback}) @@ -51,21 +52,21 @@ class AdYouLike(Captcha): except AttributeError: self.fail(_("AdYouLike challenge pattern not found")) - self.logDebug("Challenge: %s" % challenge) + self.log_debug("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"}) + #: 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) @@ -86,6 +87,6 @@ class AdYouLike(Captcha): '_ayl_token_challenge': challenge['token'], '_ayl_response' : response} - self.logDebug("Result: %s" % result) + self.log_debug("Result: %s" % result) return result diff --git a/module/plugins/internal/AdsCaptcha.py b/module/plugins/captcha/AdsCaptcha.py index 9cab99151..613283e53 100644 --- a/module/plugins/internal/AdsCaptcha.py +++ b/module/plugins/captcha/AdsCaptcha.py @@ -3,13 +3,14 @@ import random import re -from module.plugins.internal.Captcha import Captcha +from module.plugins.internal.CaptchaService import CaptchaService -class AdsCaptcha(Captcha): +class AdsCaptcha(CaptchaService): __name__ = "AdsCaptcha" __type__ = "captcha" - __version__ = "0.09" + __version__ = "0.10" + __status__ = "testing" __description__ = """AdsCaptcha captcha service plugin""" __license__ = "GPLv3" @@ -20,24 +21,24 @@ class AdsCaptcha(Captcha): PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?PublicKey=([\w-]+)' - def detect_key(self, html=None): - html = html or self.retrieve_html() + def detect_key(self, data=None): + html = data or self.retrieve_data() 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) + self.key = (m.group(1).strip(), n.group(1).strip()) #: Key is the tuple(PublicKey, CaptchaId) + self.log_debug("Key: %s | ID: %s" % self.key) return self.key else: - self.logWarning("Key or id pattern not found") + self.log_warning(_("Key or id pattern not found")) return None - def challenge(self, key=None, html=None): - PublicKey, CaptchaId = key or self.retrieve_key(html) + def challenge(self, key=None, data=None): + PublicKey, CaptchaId = key or self.retrieve_key(data) - html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", + html = self.plugin.load("http://api.adscaptcha.com/Get.aspx", get={'CaptchaId': CaptchaId, 'PublicKey': PublicKey}) try: @@ -47,17 +48,17 @@ class AdsCaptcha(Captcha): except AttributeError: self.fail(_("AdsCaptcha challenge pattern not found")) - self.logDebug("Challenge: %s" % challenge) + self.log_debug("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") + result = self.decrypt("%sChallenge.aspx" % server, + get={'cid': challenge, 'dummy': random.random()}, + cookies=True, + input_type="jpg") - self.logDebug("Result: %s" % result) + self.log_debug("Result: %s" % result) return result diff --git a/module/plugins/captcha/CircleCaptcha.py b/module/plugins/captcha/CircleCaptcha.py index d4f08018d..dc04a04c8 100644 --- a/module/plugins/captcha/CircleCaptcha.py +++ b/module/plugins/captcha/CircleCaptcha.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +# +#@TODO: Recheck all from __future__ import division @@ -9,7 +11,7 @@ import math import operator import urllib -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR class ImageSequence: @@ -29,7 +31,8 @@ class ImageSequence: class CircleCaptcha(OCR): __name__ = "CircleCaptcha" __type__ = "ocr" - __version__ = "1.00" + __version__ = "1.04" + __status__ = "testing" __description__ = """Circle captcha ocr plugin""" __license__ = "GPLv3" @@ -43,11 +46,11 @@ class CircleCaptcha(OCR): BLACKCOLOR = 5 - def cleanImage(self, im, pix): + def clean_image(self, im, pix): cleandeep = 1 - imageheight = range(1,int(im.size[1])) - imagewidth = range(1,int(im.size[0])) + imageheight = xrange(1, int(im.size[1])) + imagewidth = xrange(1, int(im.size[0])) howmany = 0 curcolor = self.BACKGROUND @@ -55,184 +58,184 @@ class CircleCaptcha(OCR): jump = True howmany = 0 for x in imagewidth: - curpix = pix[x,y] + curpix = pix[x, y] if curpix > self.BACKGROUND: if howmany <= cleandeep and howmany > 0: - # clean pixel - for ic in range(1,cleandeep+1): + #: Clean pixel + for ic in xrange(1, cleandeep+1): if x -ic > 0: - pix[x-ic,y] = self.BACKGROUND + pix[x-ic, y] = self.BACKGROUND jump = False howmany = 0 curcolor = curpix - # print (x, y), jump,2 + # self.log_debug(x, y, jump, 2) else: if howmany == 0: - # found pixel + #: Found pixel jump = True howmany = howmany + 1 curcolor = curpix - # print (x, y), jump,2 + # self.log_debug(x, y, jump, 2) else: howmany = howmany + 1 if howmany == 1: - # clean pixel - pix[x-1,y] = self.BACKGROUND + #: Clean pixel + pix[x-1, y] = self.BACKGROUND curcolor = self.BACKGROUND for x in imagewidth: jump = True howmany = 0 for y in imageheight: - curpix = pix[x,y] - # if jump == True: + curpix = pix[x, y] + # if jump is True: if curpix > self.BACKGROUND: if howmany <= cleandeep and howmany > 0: - # clean pixel - for ic in range(1,cleandeep+1): - # raw_input('2'+str(ic)) + #: Clean pixel + for ic in xrange(1, cleandeep+1): + #: raw_input('2'+str(ic)) if y-ic > 0: - pix[x,y-ic] = self.BACKGROUND + pix[x, y-ic] = self.BACKGROUND jump = False howmany = 0 curcolor = curpix - # print (x, y), jump + # self.log_debug(x, y, jump) else: if howmany == 0: - # found pixel + #: Found pixel jump = True howmany = howmany + 1 curcolor = curpix - # print (x, y), jump + # self.log_debug(x, y, jump) else: howmany = howmany + 1 if howmany == 1: - # clean pixel - pix[x-1,y] = self.BACKGROUND + #: Clean pixel + pix[x-1, y] = self.BACKGROUND - # return -1 + #: return -1 - def findFirstPixelX(self, im, pix, curx, cury, color = -1, ExitWithBlack = False): - imageheight = range(1,int(im.size[1])) - imagewidth = range(curx+1,int(im.size[0])) + def find_first_pixel_x(self, im, pix, curx, cury, color = -1, ExitWithBlack = False): + imageheight = xrange(1, int(im.size[1])) + imagewidth = xrange(curx+1, int(im.size[0])) jump = True - newx = (-1,-1) + newx = (-1, -1) blackfound = 0 for x in imagewidth: - curpix = pix[x,cury] + curpix = pix[x, cury] if curpix < self.BLACKCOLOR: blackfound = blackfound + 1 - if ExitWithBlack == True and blackfound >= 3: - break; #exit if found black + if ExitWithBlack is True and blackfound >= 3: + break #: Exit if found black else: - continue; + continue if curpix >= self.BACKGROUND: - # found first pixel white + #: Found first pixel white jump = False - continue; + continue - if (curpix < self.BACKGROUND and color == -1) or (curpix == color and color > -1): - if jump == False: - # found pixel + if (curpix < self.BACKGROUND and color == -1) or (curpix is color and color > -1): + if jump is False: + #: Found pixel curcolor = curpix newx = x, curcolor - break; + break return newx - def findLastPixelX(self, im, pix, curx, cury, color = -1, ExitWithBlack = False): - imageheight = range(1,int(im.size[1])) - imagewidth = range(curx+1,int(im.size[0])) - newx = (-1,-1) + def find_last_pixel_x(self, im, pix, curx, cury, color = -1, ExitWithBlack = False): + imageheight = xrange(1, int(im.size[1])) + imagewidth = xrange(curx+1, int(im.size[0])) + newx = (-1, -1) blackfound = 0 for x in imagewidth: - curpix = pix[x,cury] + curpix = pix[x, cury] if curpix < self.BLACKCOLOR: blackfound = blackfound + 1 - if ExitWithBlack == True and blackfound >= 3: - break; #exit if found black + if ExitWithBlack is True and blackfound >= 3: + break #: Exit if found black else: - continue; + continue if curpix >= self.BACKGROUND: - if newx != (-1,-1): - # found last pixel and the first white - break; + if newx != (-1, -1): + #: Found last pixel and the first white + break - if (curpix < self.BACKGROUND and color == -1) or (curpix == color and color > -1): - # found pixel + if (curpix < self.BACKGROUND and color == -1) or (curpix is color and color > -1): + #: Found pixel curcolor = curpix newx = x, curcolor return newx - def findLastPixelY(self, im, pix, curx, cury, DownToUp, color = -1, ExitWithBlack = False): - if DownToUp == False: - imageheight = range(int(cury)+1,int(im.size[1])-1) + def find_last_pixel_y(self, im, pix, curx, cury, DownToUp, color = -1, ExitWithBlack = False): + if DownToUp is False: + imageheight = xrange(int(cury)+1, int(im.size[1])-1) else: - imageheight = range(int(cury)-1,1,-1) - imagewidth = range(int(curx),int(im.size[0])) - newy = (-1,-1) + imageheight = xrange(int(cury)-1, 1, -1) + imagewidth = xrange(int(curx), int(im.size[0])) + newy = (-1, -1) blackfound = 0 for y in imageheight: - curpix = pix[curx,y] + curpix = pix[curx, y] if curpix < self.BLACKCOLOR: blackfound = blackfound + 1 - if ExitWithBlack == True and blackfound >= 3: - break; #exit if found black + if ExitWithBlack is True and blackfound >= 3: + break #: Exit if found black else: - continue; + continue if curpix >= self.BACKGROUND: - if newy != (-1,-1): - # found last pixel and the first white - break; + if newy != (-1, -1): + #: Found last pixel and the first white + break - if (curpix < self.BACKGROUND and color == -1) or (curpix == color and color > -1): - # found pixel + if (curpix < self.BACKGROUND and color == -1) or (curpix is color and color > -1): + #: Found pixel curcolor = curpix newy = y, color return newy - def findCircle(self, pix, x1, y1, x2, y2, x3, y3): - # trasposizione coordinate - # A(0,0) B(x2-x1,y2-y1) C(x3-x1,y3-y1) - # x**2+y**2+ax+bx+c=0 - p1 = (0,0) - p2 = (x2-x1,y2-y1) - p3 = (x3-x1,y3-y1) + def find_circle(self, pix, x1, y1, x2, y2, x3, y3): + #: Trasposizione coordinate + #: A(0, 0) B(x2-x1, y2-y1) C(x3-x1, y3-y1) + #: x**2+y**2+ax+bx+c=0 + p1 = (0, 0) + p2 = (x2-x1, y2-y1) + p3 = (x3-x1, y3-y1) - # 1 + #: 1 c=0 - # 2 - # p2[0]**2+a*p2[0]+c=0 - # a*p2[0]=-1*(p2[0]**2-c) - # a=(-1*(p2[0]**2-c))/p2[0] + #: 2 + #: p2[0]**2+a*p2[0]+c=0 + #: a*p2[0]=-1*(p2[0]**2-c) + #: a=(-1*(p2[0]**2-c))/p2[0] a=(-1*(p2[0]**2-c))/p2[0] - # 3 - # p3[0]**2+p3[1]**2+a*p3[0]+b*p3[1]+c=0 - # b*p3[1]=-(p3[0]**2+p3[1]**2+a*p3[0]+c) - # b=(-1 * (p3[0]**2+p3[1]**2+a*p3[0]+c)) / p3[1] + #: 3 + #: p3[0]**2+p3[1]**2+a*p3[0]+b*p3[1]+c=0 + #: b*p3[1]=-(p3[0]**2+p3[1]**2+a*p3[0]+c) + #: b=(-1 * (p3[0]**2+p3[1]**2+a*p3[0]+c)) / p3[1] b=(-1 * (p3[0]**2+p3[1]**2+a*p3[0]+c)) / p3[1] r=math.floor(math.sqrt((-1*(a/2))**2+(-1*(b/2))**2)) cx=math.floor((-1*(a/2))+x1) cy=math.floor((-1*(b/2))+y1) - return cx,cy,r + return cx, cy, r - def verifyCircleNew(self, im, pix, c): + def verify_circle_new(self, im, pix, c): """ This is the MAIN function to recognize the circle returns: @@ -241,9 +244,8 @@ class CircleCaptcha(OCR): -1 -> Not found circle -2 -> Found black position then leave position """ - - imageheight = range(int(c[1]-c[2]),int(c[1]+c[2])) - imagewidth = range(int(c[0]-c[2]),int(c[0]+c[2])) + imageheight = xrange(int(c[1]-c[2]), int(c[1]+c[2])) + imagewidth = xrange(int(c[0]-c[2]), int(c[0]+c[2])) min_ray = 15 max_ray = 30 @@ -253,68 +255,73 @@ class CircleCaptcha(OCR): missing = 0 missingconsecutive = 0 missinglist = [] - minX = 0; maxX = 0; minY = 0; maxY = 0 + + minX = 0 + maxX = 0 + minY = 0 + maxY = 0 + pointsofcircle = [] if (c[2] < min_ray) or (c[2] > max_ray): return -1 - # check cardinal points (at least 3) (if found i have to leave this position) - if pix[c[0] + c[2],c[1]] < self.BLACKCOLOR: - return -2; - if pix[c[0] - c[2],c[1]] < self.BLACKCOLOR: - return -2; - if pix[c[0],c[1] + c[2]] < self.BLACKCOLOR: - return -2; - if pix[c[0],c[1] - c[2]] < self.BLACKCOLOR: - return -2; + #: Check cardinal points (at least 3) (if found i have to leave this position) + if pix[c[0] + c[2], c[1]] < self.BLACKCOLOR: + return -2 + if pix[c[0] - c[2], c[1]] < self.BLACKCOLOR: + return -2 + if pix[c[0], c[1] + c[2]] < self.BLACKCOLOR: + return -2 + if pix[c[0], c[1] - c[2]] < self.BLACKCOLOR: + return -2 cardinalpoints = 0 - if self.verifyPoint(im, pix,c[0] + c[2],c[1],True) == 1: + if self.verify_point(im, pix, c[0] + c[2], c[1], True) == 1: cardinalpoints = cardinalpoints + 1 - if self.verifyPoint(im, pix,c[0] + c[2],c[1],False) == -1: - return -2; - if self.verifyPoint(im, pix,c[0] - c[2],c[1],True) == 1: + if self.verify_point(im, pix, c[0] + c[2], c[1], False) == -1: + return -2 + if self.verify_point(im, pix, c[0] - c[2], c[1], True) == 1: cardinalpoints = cardinalpoints + 1 - if self.verifyPoint(im, pix,c[0] - c[2],c[1],False) == -1: - return -2; - if self.verifyPoint(im, pix,c[0],c[1] + c[2],True) == 1: + if self.verify_point(im, pix, c[0] - c[2], c[1], False) == -1: + return -2 + if self.verify_point(im, pix, c[0], c[1] + c[2], True) == 1: cardinalpoints = cardinalpoints + 1 - if self.verifyPoint(im, pix,c[0],c[1] + c[2],False) == -1: - return -2; - if self.verifyPoint(im, pix,c[0],c[1] - c[2],True) == 1: + if self.verify_point(im, pix, c[0], c[1] + c[2], False) == -1: + return -2 + if self.verify_point(im, pix, c[0], c[1] - c[2], True) == 1: cardinalpoints = cardinalpoints + 1 - if self.verifyPoint(im, pix,c[0],c[1] - c[2],False) == -1: - return -2; + if self.verify_point(im, pix, c[0], c[1] - c[2], False) == -1: + return -2 if cardinalpoints < 3: - return -1; + return -1 for x in imagewidth: - # Pitagora + #: Pitagora y = int(round(c[1]- math.sqrt(c[2]**2-(c[0]-x)**2))) y2= int(round(c[1]+ math.sqrt(c[2]**2-(c[0]-x)**2))) howmany = howmany + 2 - if self.verifyPoint(im, pix, x,y,exactfind) == 0: + if self.verify_point(im, pix, x, y, exactfind) == 0: missing = missing + 1 - missinglist.append((x,y)) + missinglist.append((x, y)) else: - pointsofcircle.append((x,y)) + pointsofcircle.append((x, y)) - if self.verifyPoint(im, pix, x,y,False) == -1: - return -2; + if self.verify_point(im, pix, x, y, False) == -1: + return -2 - if self.verifyPoint(im, pix, x,y2,exactfind) == 0: + if self.verify_point(im, pix, x, y2, exactfind) == 0: missing = missing + 1 - missinglist.append((x,y2)) + missinglist.append((x, y2)) else: - pointsofcircle.append((x,y2)) + pointsofcircle.append((x, y2)) - if self.verifyPoint(im, pix, x,y2,False) == -1: - return -2; + if self.verify_point(im, pix, x, y2, False) == -1: + return -2 - def verifyCircle(self, im, pix, c): + def verify_circle(self, im, pix, c): """ This is the MAIN function to recognize the circle returns: @@ -323,9 +330,8 @@ class CircleCaptcha(OCR): -1 -> Not found circle -2 -> Found black position then leave position """ - - imageheight = range(int(c[1]-c[2]),int(c[1]+c[2])) - imagewidth = range(int(c[0]-c[2]),int(c[0]+c[2])) + imageheight = xrange(int(c[1]-c[2]), int(c[1]+c[2])) + imagewidth = xrange(int(c[0]-c[2]), int(c[0]+c[2])) min_ray = 15 max_ray = 30 @@ -335,119 +341,124 @@ class CircleCaptcha(OCR): missing = 0 missingconsecutive = 0 missinglist = [] - minX = 0; maxX = 0; minY = 0; maxY = 0 + + minX = 0 + maxX = 0 + minY = 0 + maxY = 0 + pointsofcircle = [] if (c[2] < min_ray) or (c[2] > max_ray): return -1 - # check cardinal points (at least 3) (if found i have to leave this position) - if pix[c[0] + c[2],c[1]] < self.BLACKCOLOR: - return -2; - if pix[c[0] - c[2],c[1]] < self.BLACKCOLOR: - return -2; - if pix[c[0],c[1] + c[2]] < self.BLACKCOLOR: - return -2; - if pix[c[0],c[1] - c[2]] < self.BLACKCOLOR: - return -2; + #: Check cardinal points (at least 3) (if found i have to leave this position) + if pix[c[0] + c[2], c[1]] < self.BLACKCOLOR: + return -2 + if pix[c[0] - c[2], c[1]] < self.BLACKCOLOR: + return -2 + if pix[c[0], c[1] + c[2]] < self.BLACKCOLOR: + return -2 + if pix[c[0], c[1] - c[2]] < self.BLACKCOLOR: + return -2 cardinalpoints = 0 - if self.verifyPoint(im, pix,c[0] + c[2],c[1],True) == 1: + if self.verify_point(im, pix, c[0] + c[2], c[1], True) == 1: cardinalpoints = cardinalpoints + 1 - if self.verifyPoint(im, pix,c[0] + c[2],c[1],False) == -1: - return -2; - if self.verifyPoint(im, pix,c[0] - c[2],c[1],True) == 1: + if self.verify_point(im, pix, c[0] + c[2], c[1], False) == -1: + return -2 + if self.verify_point(im, pix, c[0] - c[2], c[1], True) == 1: cardinalpoints = cardinalpoints + 1 - if self.verifyPoint(im, pix,c[0] - c[2],c[1],False) == -1: - return -2; - if self.verifyPoint(im, pix,c[0],c[1] + c[2],True) == 1: + if self.verify_point(im, pix, c[0] - c[2], c[1], False) == -1: + return -2 + if self.verify_point(im, pix, c[0], c[1] + c[2], True) == 1: cardinalpoints = cardinalpoints + 1 - if self.verifyPoint(im, pix,c[0],c[1] + c[2],False) == -1: - return -2; - if self.verifyPoint(im, pix,c[0],c[1] - c[2],True) == 1: + if self.verify_point(im, pix, c[0], c[1] + c[2], False) == -1: + return -2 + if self.verify_point(im, pix, c[0], c[1] - c[2], True) == 1: cardinalpoints = cardinalpoints + 1 - if self.verifyPoint(im, pix,c[0],c[1] - c[2],False) == -1: - return -2; + if self.verify_point(im, pix, c[0], c[1] - c[2], False) == -1: + return -2 if cardinalpoints < 3: - return -1; + return -1 for x in imagewidth: - # Pitagora + #: Pitagora y = int(round(c[1]- math.sqrt(c[2]**2-(c[0]-x)**2))) y2= int(round(c[1]+ math.sqrt(c[2]**2-(c[0]-x)**2))) howmany = howmany + 2 - if self.verifyPoint(im, pix, x,y,exactfind) == 0: + if self.verify_point(im, pix, x, y, exactfind) == 0: missing = missing + 1 - missinglist.append((x,y)) + missinglist.append((x, y)) else: - pointsofcircle.append((x,y)) + pointsofcircle.append((x, y)) - if self.verifyPoint(im, pix, x,y,False) == -1: - return -2; + if self.verify_point(im, pix, x, y, False) == -1: + return -2 - if self.verifyPoint(im, pix, x,y2,exactfind) == 0: + if self.verify_point(im, pix, x, y2, exactfind) == 0: missing = missing + 1 - missinglist.append((x,y2)) + missinglist.append((x, y2)) else: - pointsofcircle.append((x,y2)) + pointsofcircle.append((x, y2)) - if self.verifyPoint(im, pix, x,y2,False) == -1: - return -2; + if self.verify_point(im, pix, x, y2, False) == -1: + return -2 for y in imageheight: - # Pitagora + #: Pitagora x = int(round(c[0]- math.sqrt(c[2]**2-(c[1]-y)**2))) x2= int(round(c[0]+ math.sqrt(c[2]**2-(c[1]-y)**2))) howmany = howmany + 2 - if self.verifyPoint(im, pix, x,y,exactfind) == 0: + if self.verify_point(im, pix, x, y, exactfind) == 0: missing = missing + 1 - missinglist.append((x,y)) + missinglist.append((x, y)) else: - pointsofcircle.append((x,y)) + pointsofcircle.append((x, y)) - if self.verifyPoint(im, pix, x,y,False) == -1: - return -2; + if self.verify_point(im, pix, x, y, False) == -1: + return -2 - if self.verifyPoint(im, pix, x2,y,exactfind) == 0: + if self.verify_point(im, pix, x2, y, exactfind) == 0: missing = missing + 1 - missinglist.append((x2,y)) + missinglist.append((x2, y)) else: - pointsofcircle.append((x2,y)) + pointsofcircle.append((x2, y)) - if self.verifyPoint(im, pix, x2,y,exactfind) == -1: - return -2; + if self.verify_point(im, pix, x2, y, exactfind) == -1: + return -2 for p in missinglist: - # left and bottom - if (self.verifyPoint(im, pix, p[0]-1, p[1],exactfind) == 1 and \ - self.verifyPoint(im, pix, p[0], p[1]+1,exactfind) == 1): + #: Left and bottom + if (self.verify_point(im, pix, p[0]-1, p[1], exactfind) == 1 + and self.verify_point(im, pix, p[0], p[1]+1, exactfind) == 1): missing = missing - 1 - elif (self.verifyPoint(im, pix, p[0]-1, p[1],exactfind) == 1 and \ - self.verifyPoint(im, pix, p[0], p[1]-1,exactfind) == 1): + elif (self.verify_point(im, pix, p[0]-1, p[1], exactfind) == 1 + and self.verify_point(im, pix, p[0], p[1]-1, exactfind) == 1): missing = missing - 1 - # right and bottom - elif (self.verifyPoint(im, pix, p[0]+1, p[1],exactfind) == 1 and \ - self.verifyPoint(im, pix, p[0], p[1]+1,exactfind) == 1): + #: Right and bottom + elif (self.verify_point(im, pix, p[0]+1, p[1], exactfind) == 1 + and self.verify_point(im, pix, p[0], p[1]+1, exactfind) == 1): missing = missing - 1 - # right and up - elif (self.verifyPoint(im, pix, p[0]+1, p[1],exactfind) == 1 and \ - self.verifyPoint(im, pix, p[0], p[1]-1,exactfind) == 1): + #: Right and up + elif (self.verify_point(im, pix, p[0]+1, p[1], exactfind) == 1 + and self.verify_point(im, pix, p[0], p[1]-1, exactfind) == 1): missing = missing - 1 - if (p[0], p[1]+1) in missinglist or \ - (p[0], p[1]-1) in missinglist or \ - (p[0]+1, p[1]) in missinglist or \ - (p[0]-1, p[1]) in missinglist or \ - (p[0]+1, p[1]+1) in missinglist or \ - (p[0]-1, p[1]+1) in missinglist or \ - (p[0]+1, p[1]-1) in missinglist or \ - (p[0]-1, p[1]-1) in missinglist or \ - self.verifyPoint(im, pix, p[0], p[1],False) == 1: + if ((p[0], p[1]+1) in missinglist + or (p[0], p[1]-1) in missinglist + or (p[0]+1, p[1]) in missinglist + or (p[0]-1, p[1]) in missinglist + or (p[0]+1, p[1]+1) in missinglist + or (p[0]-1, p[1]+1) in missinglist + or (p[0]+1, p[1]-1) in missinglist + or (p[0]-1, p[1]-1) in missinglist + or self.verify_point(im, pix, p[0], p[1], False) == 1): missingconsecutive = missingconsecutive + 1 # else: - # pix[p[0], p[1]] = 0 + # pix[p[0], p[1]] = 0 if missing / howmany > 0: indice = c[2] * (missing / howmany) @@ -461,80 +472,79 @@ class CircleCaptcha(OCR): minY = min(missinglist, key=operator.itemgetter(1))[1] maxY = max(missinglist, key=operator.itemgetter(1))[1] - # Assial Simmetric - if self._DEBUG == True: - print "Center: " + str(c) - print "Missing: " + str(missing) - print "Howmany: " + str(howmany) - print "Ratio: " + str(missing / howmany) - print "Missing consecutives: " + str(missingconsecutive) - print "Missing X lenght: " + str(minX) + ":" + str(maxX) - print "Missing Y lenght: " + str(minY) + ":" + str(maxY) - print "Ratio without consecutives: " + str((missing - missingconsecutive) / howmany) - print "List missing: " + str(missinglist) + #: Assial Simmetric + if self.pyload.debug: + self.log_debug("Center: " + str(c), + "Missing: " + str(missing), + "Howmany: " + str(howmany), + "Ratio: " + str(missing / howmany), + "Missing consecutives: " + str(missingconsecutive), + "Missing X lenght: " + str(minX) + ":" + str(maxX), + "Missing Y lenght: " + str(minY) + ":" + str(maxY), + "Ratio without consecutives: " + str((missing - missingconsecutive) / howmany), + "List missing: " + str(missinglist)) - # Lenght of missing cannot be over 75% of diameter + #: Lenght of missing cannot be over 75% of diameter if maxX - minX >= c[2] * 2 * 0.75: - return -1; + return -1 if maxY - minY >= c[2] * 2 * 0.75: - # raw_input('tro') - return -1; + #: raw_input('tro') + return -1 """ - # Lenght of missing cannot be less 10% of diameter + #: Lenght of missing cannot be less 10% of diameter if maxX - minX < c[2] * 2 * 0.10 and maxY - minY < c[2] * 2 * 0.10: - return -1; + return -1 """ - if missing / howmany > 0.25 or \ missingconsecutive >= (howmany / 4) * 2 or \ howmany < 80: - return -1; + return -1 # elif missing / howmany < 0.10: elif missing == 0: self.pointsofcirclefound.extend(pointsofcircle) - return 1; + return 1 elif (missing - missingconsecutive) / howmany < 0.20: - return 0; + return 0 else: self.pointsofcirclefound.extend(pointsofcircle) - return 1; + return 1 - def verifyPoint(self, im, pix, x,y,exact,color = -1): - # Verify point + def verify_point(self, im, pix, x, y, exact, color = -1): + #: Verify point result = 0 if x < 0 or x >= im.size[0]: - return result; + return result if y < 0 or y >= im.size[1]: - return result; + return result - curpix = pix[x,y] - if (curpix == color and color > -1) or (curpix < self.BACKGROUND and color == -1): + curpix = pix[x, y] + if (curpix is color and color > -1) or (curpix < self.BACKGROUND and color == -1): if curpix > self.BLACKCOLOR: result = 1 else: result = -1 - # Verify around - if (exact == False): + #: Verify around + if exact is False: if x + 1 < im.size[0]: - curpix = pix[x+1,y] - if (curpix == color and color > -1) or (curpix < self.BACKGROUND and color == -1): + curpix = pix[x+1, y] + if (curpix is color and color > -1) or (curpix < self.BACKGROUND and color == -1): if curpix > self.BLACKCOLOR: result = 1 if curpix <= self.BLACKCOLOR: result = -1 if x > 0: - curpix = pix[x-1,y] - if (curpix == color and color > -1) or (curpix < self.BACKGROUND and color == -1): + curpix = pix[x-1, y] + if (curpix is color and color > -1) or (curpix < self.BACKGROUND and color == -1): if curpix > self.BLACKCOLOR: result = 1 if curpix <= self.BLACKCOLOR: result = -1 - # print str((x,y)) + " = " + str(result); + # self.log_debug(str((x, y)) + " = " + str(result)) return result @@ -543,22 +553,23 @@ class CircleCaptcha(OCR): mypalette = None for im in ImageSequence(img): im.save("orig.png", "png") - if mypalette != None: + if mypalette is not None: im.putpalette(mypalette) mypalette = im.getpalette() im = im.convert('L') - if self._DEBUG == True: + if self.pyload.debug: iDebugSaveFile = iDebugSaveFile + 1 - # if iDebugSaveFile < 7: continue; + # if iDebugSaveFile < 7: + # continue im.save("output" + str(iDebugSaveFile) + ".png", "png") raw_input('frame: '+ str(im)) pix = im.load() - stepheight = range(1,im.size[1],2) - # stepheight = range(45,47) - imagewidth = range(1,im.size[0]) + stepheight = xrange(1, im.size[1], 2) + #: stepheight = xrange(45, 47) + imagewidth = xrange(1, im.size[0]) lstPoints = [] # Declares an empty list for the points lstX = [] # CoordinateX lstY = [] # CoordinateY @@ -566,209 +577,211 @@ class CircleCaptcha(OCR): min_distance = 10 max_diameter = 70 - if self._DEBUG == True: + if self.pyload.debug: imdebug = im.copy() draw = ImageDraw.Draw(imdebug) pixcopy = imdebug.load() - # Clean image for powerfull search - self.cleanImage(im, pix) + #: Clean image for powerfull search + self.clean_image(im, pix) im.save("cleaned" + str(iDebugSaveFile) + ".png", "png") found = set() findnewcircle = True - # finding all the circles + #: Finding all the circles for y1 in stepheight: x1 = 1 curcolor = -1 - for k in range(1,100): + for k in xrange(1, 100): findnewcircle = False - retval = self.findFirstPixelX(im, pix, x1, y1, -1, False) + retval = self.find_first_pixel_x(im, pix, x1, y1, -1, False) x1 = retval[0] curcolor = retval[1] if x1 == -2: - break; + break if x1 == -1: - break; - if self._DEBUG == True: print "x1, y1 -> " + str((x1,y1)) + ": " + str(pix[x1,y1]) - - if (x1,y1) in self.pointsofcirclefound: - if self._DEBUG == True: print 'found ' + str((x1,y1)) - continue; - - if self._DEBUG == True: pixcopy[x1,y1] = 45 #(255,0,0,255) - # found 1 pixel, seeking x2,y2 + break + if self.pyload.debug: + self.log_debug("x1, y1 -> " + str((x1, y1)) + ": " + str(pix[x1, y1])) + + if (x1, y1) in self.pointsofcirclefound: + if self.pyload.debug: + self.log_debug("Found " + str((x1, y1))) + continue + + if self.pyload.debug: + pixcopy[x1, y1] = 45 #(255, 0, 0, 255) + #: found 1 pixel, seeking x2, y2 x2 = x1 y2 = y1 - for i in range(1,100): - retval = self.findLastPixelX(im, pix, x2, y2, -1, True) + for i in xrange(1, 100): + retval = self.find_last_pixel_x(im, pix, x2, y2, -1, True) x2 = retval[0] if x1 == -2: findnewcircle = True - break; + break if x2 == -1: - break; - if self._DEBUG == True: print "x2, y2 -> " + str((x2,y1)) + ": " + str(pix[x2,y1]) + break + if self.pyload.debug: + self.log_debug("x2, y2 -> " + str((x2, y1)) + ": " + str(pix[x2, y1])) if abs(x2 - x1) < min_distance: - continue; + continue if abs(x2 - x1) > (im.size[1] * 2 / 3): - break; + break if abs(x2 - x1) > max_diameter: - break; + break - if self._DEBUG == True: pixcopy[x2,y2] = 65 #(0,255,0,255) - # found 2 pixel, seeking x3,y3 - # verify cord + if self.pyload.debug: + pixcopy[x2, y2] = 65 #(0, 255, 0, 255) + #: found 2 pixel, seeking x3, y3 + #: Verify cord - for invert in range(0,2): + for invert in xrange(0, 2): x3 = math.floor(x2 - ((x2 - x1) / 2)) y3 = y1 - for j in range(1,50): - retval = self.findLastPixelY(im, pix, x3, y3, True if invert == 1 else False, -1, True) - # print (x3, y3,retval[0],invert) + for j in xrange(1, 50): + retval = self.find_last_pixel_y(im, pix, x3, y3, True if invert == 1 else False, -1, True) + # self.log_debug(x3, y3, retval[0], invert) y3 = retval[0] if y3 == -2: findnewcircle = True - break; + break if y3 == -1: - break; + break - if self._DEBUG == True: print "x3, y3 -> " + str((x3,y3)) + ": " + str(pix[x3,y3]) - # verify cord + if self.pyload.debug: + self.log_debug("x3, y3 -> " + str((x3, y3)) + ": " + str(pix[x3, y3])) + #: Verify cord if abs(y3 - y2) < min_distance: - continue; + continue if abs(y3 - y2) > (im.size[1] * 2 / 3): - break; + break if abs(y3 - y2) > max_diameter: - break; + break - if self._DEBUG == True: pixcopy[x3,y3] = 85 - # found 3 pixel. try circle - c = self.findCircle(pix, x1,y1,x2,y2,x3,y3) + if self.pyload.debug: + pixcopy[x3, y3] = 85 + #: found 3 pixel. try circle + c = self.find_circle(pix, x1, y1, x2, y2, x3, y3) if c[0] + c[2] >= im.size[0] or c[1] + c[2] >= im.size[1] or c[0] - c[2] <= 0 or c[1] - c[2] <= 0: - continue; + continue - if self._DEBUG == True: pixcopy[c[0],c[1]] = 0 - # (x-r, y-r, x+r, y+r) - verified = self.verifyCircle(im, pix, c) + if self.pyload.debug: + pixcopy[c[0], c[1]] = 0 + #: (x-r, y-r, x+r, y+r) + verified = self.verify_circle(im, pix, c) if verified == -1: verified = -1 elif verified == 0: - found.add(((c[0],c[1],c[2]),verified)) + found.add(((c[0], c[1], c[2]), verified)) findnewcircle = True elif verified == 1: - found.add(((c[0],c[1],c[2]),verified)) + found.add(((c[0], c[1], c[2]), verified)) findnewcircle = True - if self._DEBUG == True: + if self.pyload.debug: _pause = "" # if verified == -1: - # draw.ellipse((c[0]-c[2],c[1]-c[2],c[0]+c[2],c[1]+c[2]),outline=0) + # draw.ellipse((c[0]-c[2], c[1]-c[2], c[0]+c[2], c[1]+c[2]), outline=0) # _pause = "NOTDOUND" # imdebug.save("debug.png", "png") if verified == 0: - draw.ellipse((c[0]-c[2],c[1]-c[2],c[0]+c[2],c[1]+c[2]),outline=120) + draw.ellipse((c[0]-c[2], c[1]-c[2], c[0]+c[2], c[1]+c[2]), outline=120) _pause = "OPENED" if verified == 1: - draw.ellipse((c[0]-c[2],c[1]-c[2],c[0]+c[2],c[1]+c[2]),outline=65) + draw.ellipse((c[0]-c[2], c[1]-c[2], c[0]+c[2], c[1]+c[2]), outline=65) _pause = "CLOSED" imdebug.save("debug.png", "png") if _pause != "": valore = raw_input('Found ' + _pause + ' CIRCLE circle press [Enter] = continue / [q] for Quit: ' + str(verified)) - if valore == 'q': - sys.exit(); + if valore == "q": + sys.exit() - if findnewcircle == True: - break; - if findnewcircle == True: - break; - if findnewcircle == True: - break; + if findnewcircle is True: + break + if findnewcircle is True: + break + if findnewcircle is True: + break - if self._DEBUG == True: - print 'Howmany opened circle? ' + str(len(found)) + ' ' + str(found) + if self.pyload.debug: + self.log_debug('Howmany opened circle? ' + str(len(found)) + ' ' + str(found)) - # clean results + #: Clean results for c in found: verify = c[1] if verify == 0: p = c[0] - if ( - ((p[0], p[1]+1,p[2]),1) in found or \ - ((p[0], p[1]-1,p[2]),1) in found or \ - ((p[0]+1, p[1],p[2]),1) in found or \ - ((p[0]-1, p[1],p[2]),1) in found or \ - ((p[0]+1, p[1]+1,p[2]),1) in found or \ - ((p[0]-1, p[1]+1,p[2]),1) in found or \ - ((p[0]+1, p[1]-1,p[2]),1) in found or \ - ((p[0]-1, p[1]-1,p[2]),1) in found \ - ): - - # delete nearly circle + if (((p[0], p[1]+1, p[2]), 1) in found + or ((p[0], p[1]-1, p[2]), 1) in found + or ((p[0]+1, p[1], p[2]), 1) in found + or ((p[0]-1, p[1], p[2]), 1) in found + or ((p[0]+1, p[1]+1, p[2]), 1) in found + or ((p[0]-1, p[1]+1, p[2]), 1) in found + or ((p[0]+1, p[1]-1, p[2]), 1) in found + or ((p[0]-1, p[1]-1, p[2]), 1) in found): + + #: Delete nearly circle verify = -1 - if ( - ((p[0], p[1]+1,p[2]+1),1) in found or \ - ((p[0], p[1]-1,p[2]+1),1) in found or \ - ((p[0]+1, p[1],p[2]+1),1) in found or \ - ((p[0]-1, p[1],p[2]+1),1) in found or \ - ((p[0]+1, p[1]+1,p[2]+1),1) in found or \ - ((p[0]-1, p[1]+1,p[2]+1),1) in found or \ - ((p[0]+1, p[1]-1,p[2]+1),1) in found or \ - ((p[0]-1, p[1]-1,p[2]+1),1) in found \ - ): - - # delete nearly circle + if (((p[0], p[1]+1, p[2]+1), 1) in found + or ((p[0], p[1]-1, p[2]+1), 1) in found + or ((p[0]+1, p[1], p[2]+1), 1) in found + or ((p[0]-1, p[1], p[2]+1), 1) in found + or ((p[0]+1, p[1]+1, p[2]+1), 1) in found + or ((p[0]-1, p[1]+1, p[2]+1), 1) in found + or ((p[0]+1, p[1]-1, p[2]+1), 1) in found + or ((p[0]-1, p[1]-1, p[2]+1), 1) in found): + + #: Delete nearly circle verify = -1 - if ( - ((p[0], p[1]+1,p[2]-1),1) in found or \ - ((p[0], p[1]-1,p[2]-1),1) in found or \ - ((p[0]+1, p[1],p[2]-1),1) in found or \ - ((p[0]-1, p[1],p[2]-1),1) in found or \ - ((p[0]+1, p[1]+1,p[2]-1),1) in found or \ - ((p[0]-1, p[1]+1,p[2]-1),1) in found or \ - ((p[0]+1, p[1]-1,p[2]-1),1) in found or \ - ((p[0]-1, p[1]-1,p[2]-1),1) in found \ - ): - - # delete nearly circle + if (((p[0], p[1]+1, p[2]-1), 1) in found + or ((p[0], p[1]-1, p[2]-1), 1) in found + or ((p[0]+1, p[1], p[2]-1), 1) in found + or ((p[0]-1, p[1], p[2]-1), 1) in found + or ((p[0]+1, p[1]+1, p[2]-1), 1) in found + or ((p[0]-1, p[1]+1, p[2]-1), 1) in found + or ((p[0]+1, p[1]-1, p[2]-1), 1) in found + or ((p[0]-1, p[1]-1, p[2]-1), 1) in found): + + #: Delete nearly circle verify = -1 # if verify == 0: - # if self._DEBUG == True: - # pix[c[0][0],c[0][1]] = 90 #(255,255,0) + # if self.pyload.debug: + # pix[c[0][0], c[0][1]] = 90 #(255, 255, 0) # im.save("output.png", "png") - # return c[0][0],c[0][1] + # return c[0][0], c[0][1] # elif verify == 1: - # if self._DEBUG == True: - # pix[c[0][0],c[0][1]] = 40 #(255,0,0) + # if self.pyload.debug: + # pix[c[0][0], c[0][1]] = 40 #(255, 0, 0) # im.save("output.png", "png") # else: - # if self._DEBUG == True: - # pix[c[0][0],c[0][1]] = 180 #(0,0,255) + # if self.pyload.debug: + # pix[c[0][0], c[0][1]] = 180 #(0, 0, 255) # im.save("output.png", "png") - if self._DEBUG == True: + if self.pyload.debug: im.save("output.png", "png") - # Return coordinates of opened circle (eg (x,y)) + #: Return coordinates of opened circle (eg (x, y)) def decrypt_from_web(self, url): file = cStringIO.StringIO(urllib.urlopen(url).read()) img = Image.open(file) - coords = self.decrypt(img); - print "Coords: " + str(coords) + coords = self.decrypt(img) + self.log_info(_("Coords: %s") % coords) - # Return coordinates of opened circle (eg (x,y)) + #: Return coordinates of opened circle (eg (x, y)) def decrypt_from_file(self, filename): - coords = self.decrypt(Image.open(filename)); #Can be many different formats. - print "Coords: " + str(coords) + coords = self.decrypt(Image.open(filename)) #: Can be many different formats. + self.log_info(_("Coords: %s") % coords) ##DEBUG @@ -778,4 +791,4 @@ class CircleCaptcha(OCR): # coords = x.decrypt_from_file("decripter/captx.html2.gif") # coords = x.decrypt_from_web("http://ncrypt.in/classes/captcha/circlecaptcha.php") # b = datetime.datetime.now() -# print 'Elapsed time: ' + str((b-a).seconds) + ' seconds' +# self.log_debug("Elapsed time: %s seconds" % (b-a).seconds) diff --git a/module/plugins/captcha/GigasizeCom.py b/module/plugins/captcha/GigasizeCom.py index 52c41729b..12f123c41 100644 --- a/module/plugins/captcha/GigasizeCom.py +++ b/module/plugins/captcha/GigasizeCom.py @@ -1,23 +1,20 @@ # -*- coding: utf-8 -*- -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR class GigasizeCom(OCR): __name__ = "GigasizeCom" __type__ = "ocr" - __version__ = "0.11" + __version__ = "0.14" + __status__ = "testing" __description__ = """Gigasize.com ocr plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - def __init__(self): - OCR.__init__(self) - - - def get_captcha(self, image): + def recognize(self, image): self.load_image(image) self.threshold(2.8) self.run_tesser(True, False, False, True) diff --git a/module/plugins/captcha/LinksaveIn.py b/module/plugins/captcha/LinksaveIn.py index 95b107977..4d2e2bc34 100644 --- a/module/plugins/captcha/LinksaveIn.py +++ b/module/plugins/captcha/LinksaveIn.py @@ -2,27 +2,28 @@ try: from PIL import Image + except ImportError: import Image import glob import os -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR class LinksaveIn(OCR): __name__ = "LinksaveIn" __type__ = "ocr" - __version__ = "0.11" + __version__ = "0.14" + __status__ = "testing" __description__ = """Linksave.in ocr plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - def __init__(self): - OCR.__init__(self) + def init(self): self.data_dir = os.path.dirname(os.path.abspath(__file__)) + os.sep + "LinksaveIn" + os.sep @@ -31,7 +32,7 @@ class LinksaveIn(OCR): frame_nr = 0 lut = im.resize((256, 1)) - lut.putdata(range(256)) + lut.putdata(xrange(256)) lut = list(lut.convert("RGB").getdata()) new = Image.new("RGB", im.size) @@ -51,7 +52,7 @@ class LinksaveIn(OCR): new.save(self.data_dir+"unblacked.png") self.image = new.copy() self.pixels = self.image.load() - self.result_captcha = '' + self.result_captcha = "" def get_bg(self): @@ -63,11 +64,11 @@ class LinksaveIn(OCR): bg = Image.open(bgpath) bglut = bg.resize((256, 1)) - bglut.putdata(range(256)) + bglut.putdata(xrange(256)) bglut = list(bglut.convert("RGB").getdata()) lut = img.resize((256, 1)) - lut.putdata(range(256)) + lut.putdata(xrange(256)) lut = list(lut.convert("RGB").getdata()) bgpix = bg.load() @@ -80,11 +81,11 @@ class LinksaveIn(OCR): cstat[rgb_c] += 1 except Exception: cstat[rgb_c] = 1 - if rgb_bg == rgb_c: + if rgb_bg is rgb_c: stat[bgpath] += 1 max_p = 0 bg = "" - for bgpath, value in stat.iteritems(): + for bgpath, value in stat.items(): if max_p < value: bg = bgpath max_p = value @@ -96,11 +97,11 @@ class LinksaveIn(OCR): img = self.image.convert("P") bglut = bg.resize((256, 1)) - bglut.putdata(range(256)) + bglut.putdata(xrange(256)) bglut = list(bglut.convert("RGB").getdata()) lut = img.resize((256, 1)) - lut.putdata(range(256)) + lut.putdata(xrange(256)) lut = list(lut.convert("RGB").getdata()) bgpix = bg.load() @@ -110,7 +111,7 @@ class LinksaveIn(OCR): for y in xrange(bg.size[1]): rgb_bg = bglut[bgpix[x, y]] rgb_c = lut[pix[x, y]] - if rgb_c == rgb_bg: + if rgb_c is rgb_bg: orgpix[x, y] = (255, 255, 255) @@ -136,7 +137,7 @@ class LinksaveIn(OCR): self.pixels = self.image.load() - def get_captcha(self, image): + def recognize(self, image): self.load_image(image) bg = self.get_bg() self.substract_bg(bg) diff --git a/module/plugins/captcha/NetloadIn.py b/module/plugins/captcha/NetloadIn.py index 1fb258c47..50174684d 100644 --- a/module/plugins/captcha/NetloadIn.py +++ b/module/plugins/captcha/NetloadIn.py @@ -1,23 +1,20 @@ # -*- coding: utf-8 -*- -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR class NetloadIn(OCR): __name__ = "NetloadIn" __type__ = "ocr" - __version__ = "0.11" + __version__ = "0.14" + __status__ = "testing" __description__ = """Netload.in ocr plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - def __init__(self): - OCR.__init__(self) - - - def get_captcha(self, image): + def recognize(self, image): self.load_image(image) self.to_greyscale() self.clean(3) diff --git a/module/plugins/internal/ReCaptcha.py b/module/plugins/captcha/ReCaptcha.py index dea714a62..5931159c5 100644 --- a/module/plugins/internal/ReCaptcha.py +++ b/module/plugins/captcha/ReCaptcha.py @@ -7,13 +7,14 @@ import urlparse from base64 import b64encode -from module.plugins.internal.Captcha import Captcha +from module.plugins.internal.CaptchaService import CaptchaService -class ReCaptcha(Captcha): +class ReCaptcha(CaptchaService): __name__ = "ReCaptcha" __type__ = "captcha" - __version__ = "0.17" + __version__ = "0.18" + __status__ = "testing" __description__ = """ReCaptcha captcha service plugin""" __license__ = "GPLv3" @@ -22,36 +23,36 @@ class ReCaptcha(Captcha): ("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-]+)' + KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)' - def detect_key(self, html=None): - html = html or self.retrieve_html() + def detect_key(self, data=None): + html = data or self.retrieve_data() 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) + self.log_debug("Key: %s" % self.key) return self.key else: - self.logWarning("Key pattern not found") + self.log_warning(_("Key pattern not found")) return None - def challenge(self, key=None, html=None, version=None): - key = key or self.retrieve_key(html) + def challenge(self, key=None, data=None, version=None): + key = key or self.retrieve_key(data) 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) + version=2 if re.search(self.KEY_V2_PATTERN, data or self.retrieve_data()) else 1) def _challenge_v1(self, key): - html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", + html = self.plugin.load("http://www.google.com/recaptcha/api/challenge", get={'k': key}) try: challenge = re.search("challenge : '(.+?)',", html).group(1) @@ -60,14 +61,14 @@ class ReCaptcha(Captcha): except AttributeError: self.fail(_("ReCaptcha challenge pattern not found")) - self.logDebug("Challenge: %s" % challenge) + self.log_debug("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", + self.plugin.load("http://www.google.com/recaptcha/api/js/recaptcha.js") + html = self.plugin.load("http://www.google.com/recaptcha/api/reload", get={'c' : challenge, 'k' : key, 'reason': "i", @@ -79,50 +80,49 @@ class ReCaptcha(Captcha): 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.log_debug("Second challenge: %s" % challenge) + result = self.decrypt(urlparse.urljoin(server, "image"), + get={'c': challenge}, + cookies=True, + input_type="jpg") - self.logDebug("Result: %s" % result) + self.log_debug("Result: %s" % result) return result, challenge - def _collectApiInfo(self): - html = self.plugin.req.load("http://www.google.com/recaptcha/api.js") + def _collect_api_info(self): + html = self.plugin.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) + self.log_debug("API version: %s" % vers) language = a.split("__")[1].split(".")[0] - self.logDebug("API language: %s" % language) + self.log_debug("API language: %s" % language) - html = self.plugin.req.load("https://apis.google.com/js/api.js") + html = self.plugin.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) + self.log_debug("API jsh-string: %s" % jsh) return vers, language, jsh - def _prepareTimeAndRpc(self): - self.plugin.req.load("http://www.google.com/recaptcha/api2/demo") + def _prepare_time_and_rpc(self): + self.plugin.load("http://www.google.com/recaptcha/api2/demo") millis = int(round(time.time() * 1000)) - self.logDebug("Time: %s" % millis) + self.log_debug("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) + self.log_debug("Rpc-token: %s" % rpc) return millis, rpc @@ -136,10 +136,10 @@ class ReCaptcha(Captcha): parent = "" botguardstring = "!A" - vers, language, jsh = self._collectApiInfo() - millis, rpc = self._prepareTimeAndRpc() + vers, language, jsh = self._collect_api_info() + millis, rpc = self._prepare_time_and_rpc() - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/anchor", + html = self.plugin.load("https://www.google.com/recaptcha/api2/anchor", get={'k' : key, 'hl' : language, 'v' : vers, @@ -150,36 +150,38 @@ class ReCaptcha(Captcha): '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') + self.log_debug("Token #1: %s" % token1.group(1)) + + html = self.plugin.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)) + self.log_debug("Token #2: %s" % token2.group(1)) token3 = re.search(r'"rresp","(.*?)",', html) - self.logDebug("Token #3: %s" % token3.group(1)) + self.log_debug("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) + captcha_response = self.decrypt("https://www.google.com/recaptcha/api2/payload", + get={'c':token3.group(1), 'k':key}, + cookies=True, + ocr=False, + timeout=30) response = b64encode('{"response":"%s"}' % captcha_response) - self.logDebug("Result: %s" % response) + self.log_debug("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", + html = self.plugin.load("https://www.google.com/recaptcha/api2/userverify", post={'k' : key, 'c' : token3.group(1), 'response': response, @@ -188,7 +190,7 @@ class ReCaptcha(Captcha): 'bg' : botguardstring}) token4 = re.search(r'"uvresp","(.*?)",', html) - self.logDebug("Token #4: %s" % token4.group(1)) + self.log_debug("Token #4: %s" % token4.group(1)) result = token4.group(1) diff --git a/module/plugins/captcha/ShareonlineBiz.py b/module/plugins/captcha/ShareonlineBiz.py index 6fad66600..edf14df87 100644 --- a/module/plugins/captcha/ShareonlineBiz.py +++ b/module/plugins/captcha/ShareonlineBiz.py @@ -1,30 +1,27 @@ # -*- coding: utf-8 -*- -from module.plugins.captcha.OCR import OCR +from module.plugins.internal.OCR import OCR class ShareonlineBiz(OCR): __name__ = "ShareonlineBiz" __type__ = "ocr" - __version__ = "0.11" + __version__ = "0.14" + __status__ = "testing" __description__ = """Shareonline.biz ocr plugin""" __license__ = "GPLv3" __authors__ = [("RaNaN", "RaNaN@pyload.org")] - def __init__(self): - OCR.__init__(self) - - - def get_captcha(self, image): + def recognize(self, image): self.load_image(image) self.to_greyscale() self.image = self.image.resize((160, 50)) self.pixels = self.image.load() self.threshold(1.85) - #self.eval_black_white(240) - #self.derotate_by_average() + # self.eval_black_white(240) + # self.derotate_by_average() letters = self.split_captcha_letters() @@ -36,4 +33,4 @@ class ShareonlineBiz(OCR): return final - #tesseract at 60% + #: Tesseract at 60% diff --git a/module/plugins/internal/SolveMedia.py b/module/plugins/captcha/SolveMedia.py index 7f5de51e1..870b5fc10 100644 --- a/module/plugins/internal/SolveMedia.py +++ b/module/plugins/captcha/SolveMedia.py @@ -2,14 +2,15 @@ import re -from module.plugins.Plugin import Fail -from module.plugins.internal.Captcha import Captcha +from module.plugins.internal.Plugin import Fail +from module.plugins.internal.CaptchaService import CaptchaService -class SolveMedia(Captcha): +class SolveMedia(CaptchaService): __name__ = "SolveMedia" __type__ = "captcha" - __version__ = "0.13" + __version__ = "0.15" + __status__ = "testing" __description__ = """SolveMedia captcha service plugin""" __license__ = "GPLv3" @@ -19,23 +20,23 @@ class SolveMedia(Captcha): KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' - def detect_key(self, html=None): - html = html or self.retrieve_html() + def detect_key(self, data=None): + html = data or self.retrieve_data() m = re.search(self.KEY_PATTERN, html) if m: self.key = m.group(1).strip() - self.logDebug("Key: %s" % self.key) + self.log_debug("Key: %s" % self.key) return self.key else: - self.logWarning("Key pattern not found") + self.log_warning(_("Key pattern not found")) return None - def challenge(self, key=None, html=None): - key = key or self.retrieve_key(html) + def challenge(self, key=None, data=None): + key = key or self.retrieve_key(data) - html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript", + html = self.plugin.load("http://api.solvemedia.com/papi/challenge.noscript", get={'k': key}) for i in xrange(1, 11): @@ -43,7 +44,7 @@ class SolveMedia(Captcha): magic = re.search(r'name="magic" value="(.+?)"', html).group(1) except AttributeError: - self.logWarning("Magic pattern not found") + self.log_warning(_("Magic pattern not found")) magic = None try: @@ -54,17 +55,17 @@ class SolveMedia(Captcha): self.fail(_("SolveMedia challenge pattern not found")) else: - self.logDebug("Challenge: %s" % challenge) + self.log_debug("Challenge: %s" % challenge) try: result = self.result("http://api.solvemedia.com/papi/media", challenge) except Fail, e: - self.logWarning(e) + self.log_warning(e) self.plugin.invalidCaptcha() result = None - html = self.plugin.req.load("http://api.solvemedia.com/papi/verify.noscript", + html = self.plugin.load("http://api.solvemedia.com/papi/verify.noscript", post={'adcopy_response' : result, 'k' : key, 'l' : "en", @@ -81,9 +82,9 @@ class SolveMedia(Captcha): else: if "error" in html: - self.logWarning("Captcha code was invalid") - self.logDebug("Retry #%d" % i) - html = self.plugin.req.load(redirect) + self.log_warning(_("Captcha code was invalid")) + self.log_debug("Retry #%d" % i) + html = self.plugin.load(redirect) else: break @@ -94,11 +95,11 @@ class SolveMedia(Captcha): def result(self, server, challenge): - result = self.plugin.decryptCaptcha(server, - get={'c': challenge}, - cookies=True, - imgtype="gif") + result = self.decrypt(server, + get={'c': challenge}, + cookies=True, + input_type="gif") - self.logDebug("Result: %s" % result) + self.log_debug("Result: %s" % result) return result diff --git a/module/plugins/container/CCF.py b/module/plugins/container/CCF.py index 235d5dc1d..3126d69a5 100644 --- a/module/plugins/container/CCF.py +++ b/module/plugins/container/CCF.py @@ -6,14 +6,15 @@ import MultipartPostHandler import re import urllib2 -from module.plugins.Container import Container -from module.utils import fs_encode, save_join +from module.plugins.internal.Container import Container +from module.utils import fs_encode, save_join as fs_join class CCF(Container): __name__ = "CCF" __type__ = "container" - __version__ = "0.23" + __version__ = "0.25" + __status__ = "testing" __pattern__ = r'.+\.ccf$' @@ -32,8 +33,8 @@ class CCF(Container): 'filename': "test.ccf", 'upload' : open(fs_filename, "rb")}).read() - download_folder = self.config['general']['download_folder'] - dlc_file = save_join(download_folder, "tmp_%s.dlc" % pyfile.name) + download_folder = self.pyload.config.get("general", "download_folder") + dlc_file = fs_join(download_folder, "tmp_%s.dlc" % pyfile.name) try: dlc = re.search(r'<dlc>(.+)</dlc>', dlc_content, re.S).group(1).decode('base64') diff --git a/module/plugins/container/DLC.py b/module/plugins/container/DLC.py index ff2f0104a..145322942 100644 --- a/module/plugins/container/DLC.py +++ b/module/plugins/container/DLC.py @@ -7,14 +7,15 @@ import xml.dom.minidom from Crypto.Cipher import AES -from module.plugins.Container import Container +from module.plugins.internal.Container import Container from module.utils import decode, fs_encode class DLC(Container): __name__ = "DLC" __type__ = "container" - __version__ = "0.24" + __version__ = "0.26" + __status__ = "testing" __pattern__ = r'.+\.dlc$' @@ -53,20 +54,20 @@ class DLC(Container): self.data = AES.new(key, AES.MODE_CBC, iv).decrypt(dlc_data).decode('base64') self.packages = [(name or pyfile.name, links, name or pyfile.name) \ - for name, links in self.getPackages()] + for name, links in self.get_packages()] - def getPackages(self): + def get_packages(self): root = xml.dom.minidom.parseString(self.data).documentElement content = root.getElementsByTagName("content")[0] - return self.parsePackages(content) + return self.parse_packages(content) - def parsePackages(self, startNode): - return [(decode(node.getAttribute("name")).decode('base64'), self.parseLinks(node)) \ + def parse_packages(self, startNode): + return [(decode(node.getAttribute("name")).decode('base64'), self.parse_links(node)) \ for node in startNode.getElementsByTagName("package")] - def parseLinks(self, startNode): + def parse_links(self, startNode): return [node.getElementsByTagName("url")[0].firstChild.data.decode('base64') \ for node in startNode.getElementsByTagName("file")] diff --git a/module/plugins/container/RSDF.py b/module/plugins/container/RSDF.py index dd2d14cf7..cedb2b605 100644 --- a/module/plugins/container/RSDF.py +++ b/module/plugins/container/RSDF.py @@ -7,14 +7,15 @@ import re from Crypto.Cipher import AES -from module.plugins.Container import Container +from module.plugins.internal.Container import Container from module.utils import fs_encode class RSDF(Container): __name__ = "RSDF" __type__ = "container" - __version__ = "0.29" + __version__ = "0.31" + __status__ = "testing" __pattern__ = r'.+\.rsdf$' diff --git a/module/plugins/container/TXT.py b/module/plugins/container/TXT.py index d419ee060..8c9f99c27 100644 --- a/module/plugins/container/TXT.py +++ b/module/plugins/container/TXT.py @@ -2,14 +2,15 @@ import codecs -from module.plugins.Container import Container +from module.plugins.internal.Container import Container from module.utils import fs_encode class TXT(Container): __name__ = "TXT" __type__ = "container" - __version__ = "0.15" + __version__ = "0.17" + __status__ = "testing" __pattern__ = r'.+\.(txt|text)$' __config__ = [("flush" , "bool" , "Flush list after adding", False ), @@ -23,7 +24,7 @@ class TXT(Container): def decrypt(self, pyfile): try: - encoding = codecs.lookup(self.getConfig('encoding')).name + encoding = codecs.lookup(self.get_config('encoding')).name except Exception: encoding = "utf-8" @@ -43,7 +44,7 @@ class TXT(Container): continue if link.startswith("[") and link.endswith("]"): - # new package + #: New package curPack = link[1:-1] packages[curPack] = [] continue @@ -52,18 +53,18 @@ class TXT(Container): txt.close() - # empty packages fix - for key, value in packages.iteritems(): + #: Empty packages fix + for key, value in packages.items(): if not value: packages.pop(key, None) - if self.getConfig('flush'): + if self.get_config('flush'): try: txt = open(fs_filename, 'wb') txt.close() except IOError: - self.logWarning(_("Failed to flush list")) + self.log_warning(_("Failed to flush list")) - for name, links in packages.iteritems(): + for name, links in packages.items(): self.packages.append((name, links, name)) diff --git a/module/plugins/crypter/BitshareComFolder.py b/module/plugins/crypter/BitshareComFolder.py index 256c5b5aa..d7a51cb1c 100644 --- a/module/plugins/crypter/BitshareComFolder.py +++ b/module/plugins/crypter/BitshareComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class BitshareComFolder(SimpleCrypter): __name__ = "BitshareComFolder" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?bitshare\.com/\?d=\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -19,7 +20,7 @@ class BitshareComFolder(SimpleCrypter): LINK_PATTERN = r'<a href="(http://bitshare\.com/files/.+)">.+</a></td>' - NAME_PATTERN = r'View public folder "(?P<N>.+)"</h1>' + NAME_PATTERN = r'View public folder "(?P<N>.+?)"</h1>' getInfo = create_getInfo(BitshareComFolder) diff --git a/module/plugins/crypter/C1NeonCom.py b/module/plugins/crypter/C1NeonCom.py index 9b6093081..09acace63 100644 --- a/module/plugins/crypter/C1NeonCom.py +++ b/module/plugins/crypter/C1NeonCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class C1NeonCom(DeadCrypter): __name__ = "C1NeonCom" __type__ = "crypter" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?c1neon\.com/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/ChipDe.py b/module/plugins/crypter/ChipDe.py index f535da48d..3604635e5 100644 --- a/module/plugins/crypter/ChipDe.py +++ b/module/plugins/crypter/ChipDe.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class ChipDe(Crypter): __name__ = "ChipDe" __type__ = "crypter" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?chip\.de/video/.+\.html' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -26,4 +27,4 @@ class ChipDe(Crypter): self.fail(_("Failed to find the URL")) else: self.urls = [f.group(1)] - self.logDebug("The file URL is %s" % self.urls[0]) + self.log_debug("The file URL is %s" % self.urls[0]) diff --git a/module/plugins/crypter/CloudzillaToFolder.py b/module/plugins/crypter/CloudzillaToFolder.py index 96d7245f1..09b4d4c08 100644 --- a/module/plugins/crypter/CloudzillaToFolder.py +++ b/module/plugins/crypter/CloudzillaToFolder.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class CloudzillaToFolder(SimpleHoster): __name__ = "CloudzillaToFolder" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?cloudzilla\.to/share/folder/(?P<ID>[\w^_]+)' @@ -26,10 +27,10 @@ class CloudzillaToFolder(SimpleHoster): PASSWORD_PATTERN = r'<div id="pwd_protected">' - def checkErrors(self): + def check_errors(self): m = re.search(self.PASSWORD_PATTERN, self.html) if m: - self.html = self.load(self.pyfile.url, get={'key': self.getPassword()}) + self.html = self.load(self.pyfile.url, get={'key': self.get_password()}) if re.search(self.PASSWORD_PATTERN, self.html): self.retry(reason="Wrong password") diff --git a/module/plugins/crypter/CrockoComFolder.py b/module/plugins/crypter/CrockoComFolder.py index f56cc449a..81dfcd525 100644 --- a/module/plugins/crypter/CrockoComFolder.py +++ b/module/plugins/crypter/CrockoComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class CrockoComFolder(SimpleCrypter): __name__ = "CrockoComFolder" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?crocko\.com/f/.+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), diff --git a/module/plugins/crypter/CryptItCom.py b/module/plugins/crypter/CryptItCom.py index 1c9e841b7..be0094747 100644 --- a/module/plugins/crypter/CryptItCom.py +++ b/module/plugins/crypter/CryptItCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class CryptItCom(DeadCrypter): __name__ = "CryptItCom" __type__ = "crypter" - __version__ = "0.11" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?crypt-it\.com/(s|e|d|c)/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/CzshareComFolder.py b/module/plugins/crypter/CzshareComFolder.py index c317b1b49..cb41426d7 100644 --- a/module/plugins/crypter/CzshareComFolder.py +++ b/module/plugins/crypter/CzshareComFolder.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class CzshareComFolder(Crypter): __name__ = "CzshareComFolder" __type__ = "crypter" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(czshare|sdilej)\.(com|cz)/folders/.+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/DailymotionComFolder.py b/module/plugins/crypter/DailymotionComFolder.py index 01caa0bb8..8a4a0f258 100644 --- a/module/plugins/crypter/DailymotionComFolder.py +++ b/module/plugins/crypter/DailymotionComFolder.py @@ -4,14 +4,15 @@ import re import urlparse from module.common.json_layer import json_loads -from module.plugins.Crypter import Crypter -from module.utils import save_join +from module.plugins.internal.Crypter import Crypter +from module.utils import save_join as fs_join class DailymotionComFolder(Crypter): __name__ = "DailymotionComFolder" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?dailymotion\.com/((playlists/)?(?P<TYPE>playlist|user)/)?(?P<ID>[\w^_]+)(?(TYPE)|#)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -22,16 +23,16 @@ class DailymotionComFolder(Crypter): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - def api_response(self, ref, req=None): + def api_response(self, ref, data=None): url = urlparse.urljoin("https://api.dailymotion.com/", ref) - html = self.load(url, get=req) + html = self.load(url, get=data) return json_loads(html) - def getPlaylistInfo(self, id): - ref = "playlist/" + id - req = {"fields": "name,owner.screenname"} - playlist = self.api_response(ref, req) + def get_playlist_info(self, id): + ref = "playlist/" + id + data = {'fields': "name,owner.screenname"} + playlist = self.api_response(ref, data) if "error" in playlist: return @@ -41,10 +42,10 @@ class DailymotionComFolder(Crypter): return name, owner - def _getPlaylists(self, user_id, page=1): - ref = "user/%s/playlists" % user_id - req = {"fields": "id", "page": page, "limit": 100} - user = self.api_response(ref, req) + def _get_playlists(self, user_id, page=1): + ref = "user/%s/playlists" % user_id + data = {'fields': "id", 'page': page, 'limit': 100} + user = self.api_response(ref, data) if "error" in user: return @@ -53,18 +54,18 @@ class DailymotionComFolder(Crypter): yield playlist['id'] if user['has_more']: - for item in self._getPlaylists(user_id, page + 1): + for item in self._get_playlists(user_id, page + 1): yield item - def getPlaylists(self, user_id): - return [(id,) + self.getPlaylistInfo(id) for id in self._getPlaylists(user_id)] + def get_playlists(self, user_id): + return [(id,) + self.get_playlist_info(id) for id in self._get_playlists(user_id)] - def _getVideos(self, id, page=1): - ref = "playlist/%s/videos" % id - req = {"fields": "url", "page": page, "limit": 100} - playlist = self.api_response(ref, req) + def _get_videos(self, id, page=1): + ref = "playlist/%s/videos" % id + data = {'fields': "url", 'page': page, 'limit': 100} + playlist = self.api_response(ref, data) if "error" in playlist: return @@ -73,12 +74,12 @@ class DailymotionComFolder(Crypter): yield video['url'] if playlist['has_more']: - for item in self._getVideos(id, page + 1): + for item in self._get_videos(id, page + 1): yield item - def getVideos(self, playlist_id): - return list(self._getVideos(playlist_id))[::-1] + def get_videos(self, playlist_id): + return list(self._get_videos(playlist_id))[::-1] def decrypt(self, pyfile): @@ -87,19 +88,19 @@ class DailymotionComFolder(Crypter): m_type = m.group('TYPE') if m_type == "playlist": - self.logDebug("Url recognized as Playlist") - p_info = self.getPlaylistInfo(m_id) + self.log_debug("Url recognized as Playlist") + p_info = self.get_playlist_info(m_id) playlists = [(m_id,) + p_info] if p_info else None else: - self.logDebug("Url recognized as Channel") - playlists = self.getPlaylists(m_id) - self.logDebug("%s playlist\s found on channel \"%s\"" % (len(playlists), m_id)) + self.log_debug("Url recognized as Channel") + playlists = self.get_playlists(m_id) + self.log_debug("%s playlist\s found on channel \"%s\"" % (len(playlists), m_id)) if not playlists: self.fail(_("No playlist available")) for p_id, p_name, p_owner in playlists: - p_videos = self.getVideos(p_id) - p_folder = save_join(self.config['general']['download_folder'], p_owner, p_name) - self.logDebug("%s video\s found on playlist \"%s\"" % (len(p_videos), p_name)) - self.packages.append((p_name, p_videos, p_folder)) #: folder is NOT recognized by pyload 0.4.9! + p_videos = self.get_videos(p_id) + p_folder = fs_join(self.pyload.config.get("general", "download_folder"), p_owner, p_name) + self.log_debug("%s video\s found on playlist \"%s\"" % (len(p_videos), p_name)) + self.packages.append((p_name, p_videos, p_folder)) #: Folder is NOT recognized by pyload 0.4.9! diff --git a/module/plugins/crypter/DataHuFolder.py b/module/plugins/crypter/DataHuFolder.py index 67f5e788f..e6e3c70a5 100644 --- a/module/plugins/crypter/DataHuFolder.py +++ b/module/plugins/crypter/DataHuFolder.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class DataHuFolder(SimpleCrypter): __name__ = "DataHuFolder" __type__ = "crypter" - __version__ = "0.06" + __version__ = "0.08" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?data\.hu/dir/\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -22,22 +23,22 @@ class DataHuFolder(SimpleCrypter): LINK_PATTERN = r'<a href=\'(http://data\.hu/get/.+)\' target=\'_blank\'>\1</a>' - NAME_PATTERN = ur'<title>(?P<N>.+) Let\xf6lt\xe9se</title>' + NAME_PATTERN = ur'<title>(?P<N>.+?) Let\xf6lt\xe9se</title>' def prepare(self): super(DataHuFolder, self).prepare() - if u'K\xe9rlek add meg a jelsz\xf3t' in self.html: # Password protected - password = self.getPassword() + if u'K\xe9rlek add meg a jelsz\xf3t' in self.html: #: Password protected + password = self.get_password() if not password: self.fail(_("Password required")) - self.logDebug("The folder is password protected', 'Using password: " + password) + self.log_debug("The folder is password protected', 'Using password: " + password) - self.html = self.load(self.pyfile.url, post={'mappa_pass': password}, decode=True) + self.html = self.load(self.pyfile.url, post={'mappa_pass': password}) - if u'Hib\xe1s jelsz\xf3' in self.html: # Wrong password + if u'Hib\xe1s jelsz\xf3' in self.html: #: Wrong password self.fail(_("Wrong password")) diff --git a/module/plugins/crypter/DdlstorageComFolder.py b/module/plugins/crypter/DdlstorageComFolder.py index dc6ec1da5..ffc9f1d01 100644 --- a/module/plugins/crypter/DdlstorageComFolder.py +++ b/module/plugins/crypter/DdlstorageComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class DdlstorageComFolder(DeadCrypter): __name__ = "DdlstorageComFolder" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?ddlstorage\.com/folder/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/DepositfilesComFolder.py b/module/plugins/crypter/DepositfilesComFolder.py index 46ec265c3..0c795279e 100644 --- a/module/plugins/crypter/DepositfilesComFolder.py +++ b/module/plugins/crypter/DepositfilesComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class DepositfilesComFolder(SimpleCrypter): __name__ = "DepositfilesComFolder" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?depositfiles\.com/folders/\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), diff --git a/module/plugins/crypter/Dereferer.py b/module/plugins/crypter/Dereferer.py index 8e56a7bfc..9051abcc2 100644 --- a/module/plugins/crypter/Dereferer.py +++ b/module/plugins/crypter/Dereferer.py @@ -1,12 +1,15 @@ # -*- 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.12" + __version__ = "0.18" + __status__ = "testing" __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), @@ -21,24 +24,18 @@ class Dereferer(SimpleDereferer): 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 _log(self, level, plugintype, pluginname, messages): + return super(Dereferer, self)._log(level, plugintype, pluginname, (self.HOSTER_NAME,) + messages) def init(self): super(Dereferer, self).init() - self.__pattern__ = self.core.pluginManager.crypterPlugins[self.__name__]['pattern'] #@TODO: Recheck in 0.4.10 + self.__pattern__ = self.pyload.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 getLink(self): - try: - return re.match(self.__pattern__, pyfile.url).group('LINK').strip() - - except Exception, e: - self.logWarning(e) + def get_links(self): + return [re.match(self.__pattern__, self.pyfile.url).group('LINK').strip()] diff --git a/module/plugins/crypter/DevhostStFolder.py b/module/plugins/crypter/DevhostStFolder.py index 4d15e2058..8340adeb8 100644 --- a/module/plugins/crypter/DevhostStFolder.py +++ b/module/plugins/crypter/DevhostStFolder.py @@ -12,14 +12,15 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class DevhostStFolder(SimpleCrypter): __name__ = "DevhostStFolder" __type__ = "crypter" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?d-h\.st/users/(?P<USER>\w+)(/\?fld_id=(?P<ID>\d+))?' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), ("use_subfolder" , "bool", "Save package to subfolder" , True), ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] - __description__ = """d-h.st folder decrypter plugin""" + __description__ = """D-h.st folder decrypter plugin""" __license__ = "GPLv3" __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"), ("Walter Purcaro", "vuolter@gmail.com")] @@ -29,11 +30,11 @@ class DevhostStFolder(SimpleCrypter): OFFLINE_PATTERN = r'"/cHP">test\.png<' - def checkNameSize(self, getinfo=True): + def check_name_size(self, getinfo=True): if not self.info or getinfo: - self.logDebug("File info (BEFORE): %s" % self.info) - self.info.update(self.getInfo(self.pyfile.url, self.html)) - self.logDebug("File info (AFTER): %s" % self.info) + self.log_debug("File info (BEFORE): %s" % self.info) + self.info.update(self.get_info(self.pyfile.url, self.html)) + self.log_debug("File info (AFTER): %s" % self.info) try: if self.info['pattern']['ID'] == "0": @@ -49,7 +50,7 @@ class DevhostStFolder(SimpleCrypter): self.pyfile.name = m.group(1) except Exception, e: - self.logDebug(e) + self.log_debug(e) self.pyfile.name = self.info['pattern']['USER'] try: @@ -58,7 +59,7 @@ class DevhostStFolder(SimpleCrypter): except Exception: pass - self.logDebug("File name: %s" % self.pyfile.name, + self.log_debug("File name: %s" % self.pyfile.name, "File folder: %s" % self.pyfile.name) diff --git a/module/plugins/crypter/DlProtectCom.py b/module/plugins/crypter/DlProtectCom.py index a9f39c6f3..0c776ac61 100644 --- a/module/plugins/crypter/DlProtectCom.py +++ b/module/plugins/crypter/DlProtectCom.py @@ -11,7 +11,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class DlProtectCom(SimpleCrypter): __name__ = "DlProtectCom" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?dl-protect\.com/((en|fr)/)?\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -28,15 +29,15 @@ class DlProtectCom(SimpleCrypter): OFFLINE_PATTERN = r'Unfortunately, the link you are looking for is not found' - def getLinks(self): - # Direct link with redirect + def get_links(self): + #: Direct link with redirect if not re.match(r"https?://(?:www\.)?dl-protect\.com/.+", self.req.http.lastEffectiveURL): return [self.req.http.lastEffectiveURL] post_req = {'key' : re.search(r'name="key" value="(.+?)"', self.html).group(1), 'submitform': ""} - if "Please click on continue to see the content" in self.html: + if "Please click on continue to see the links" in self.html: post_req['submitform'] = "Continue" self.wait(2) @@ -48,14 +49,13 @@ class DlProtectCom(SimpleCrypter): 'submitform': "Decrypt+link"}) if "Password :" in self.html: - post_req['pwd'] = self.getPassword() + post_req['pwd'] = self.get_password() if "Security Code" in self.html: - captcha_id = re.search(r'/captcha\.php\?uid=(.+?)"', self.html).group(1) - captcha_url = "http://www.dl-protect.com/captcha.php?uid=" + captcha_id - captcha_code = self.decryptCaptcha(captcha_url, imgtype="gif") - - post_req['secure'] = captcha_code + m = re.search(r'/captcha\.php\?key=(.+?)"', self.html) + if m: + captcha_code = self.captcha.decrypt("http://www.dl-protect.com/captcha.php?key=" + m.group(1), input_type="gif") + post_req['secure'] = captcha_code self.html = self.load(self.pyfile.url, post=post_req) diff --git a/module/plugins/crypter/DuckCryptInfo.py b/module/plugins/crypter/DuckCryptInfo.py index cc108d101..c9269b05e 100644 --- a/module/plugins/crypter/DuckCryptInfo.py +++ b/module/plugins/crypter/DuckCryptInfo.py @@ -2,15 +2,16 @@ import re -from BeautifulSoup import BeautifulSoup +import BeautifulSoup -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class DuckCryptInfo(Crypter): __name__ = "DuckCryptInfo" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?duckcrypt\.info/(folder|wait|link)/(\w+)/?(\w*)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -31,29 +32,29 @@ class DuckCryptInfo(Crypter): if m is None: self.fail(_("Weird error in link")) if str(m.group(1)) == "link": - self.handleLink(url) + self.handle_link(url) else: - self.handleFolder(m) + self.handle_folder(m) - def handleFolder(self, m): + def handle_folder(self, m): html = self.load("http://duckcrypt.info/ajax/auth.php?hash=" + str(m.group(2))) m = re.match(self.__pattern__, html) - self.logDebug("Redirectet to " + str(m.group(0))) + self.log_debug("Redirectet to " + str(m.group(0))) html = self.load(str(m.group(0))) - soup = BeautifulSoup(html) - cryptlinks = soup.findAll("div", attrs={"class": "folderbox"}) - self.logDebug("Redirectet to " + str(cryptlinks)) + soup = BeautifulSoup.BeautifulSoup(html) + cryptlinks = soup.findAll("div", attrs={'class': "folderbox"}) + self.log_debug("Redirectet to " + str(cryptlinks)) if not cryptlinks: self.error(_("No link found")) for clink in cryptlinks: if clink.find("a"): - self.handleLink(clink.find("a")['href']) + self.handle_link(clink.find("a")['href']) - def handleLink(self, url): + def handle_link(self, url): html = self.load(url) soup = BeautifulSoup(html) self.urls = [soup.find("iframe")['src']] if not self.urls: - self.logInfo(_("No link found")) + self.log_info(_("No link found")) diff --git a/module/plugins/crypter/DuploadOrgFolder.py b/module/plugins/crypter/DuploadOrgFolder.py index d505806b7..f0e9b8c96 100644 --- a/module/plugins/crypter/DuploadOrgFolder.py +++ b/module/plugins/crypter/DuploadOrgFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class DuploadOrgFolder(DeadCrypter): __name__ = "DuploadOrgFolder" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?dupload\.org/folder/\d+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/EasybytezComFolder.py b/module/plugins/crypter/EasybytezComFolder.py index fdd3d4ff4..0c070b6f1 100644 --- a/module/plugins/crypter/EasybytezComFolder.py +++ b/module/plugins/crypter/EasybytezComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo class EasybytezComFolder(XFSCrypter): __name__ = "EasybytezComFolder" __type__ = "crypter" - __version__ = "0.10" + __version__ = "0.11" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?easybytez\.com/users/\d+/\d+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/EmbeduploadCom.py b/module/plugins/crypter/EmbeduploadCom.py index 28633f634..341b3e315 100644 --- a/module/plugins/crypter/EmbeduploadCom.py +++ b/module/plugins/crypter/EmbeduploadCom.py @@ -1,14 +1,15 @@ # -*- coding: utf-8 -*- import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter from module.network.HTTPRequest import BadHeader class EmbeduploadCom(Crypter): __name__ = "EmbeduploadCom" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?embedupload\.com/\?d=.+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True ), @@ -25,30 +26,30 @@ class EmbeduploadCom(Crypter): def decrypt(self, pyfile): - self.html = self.load(pyfile.url, decode=True) + self.html = self.load(pyfile.url) tmp_links = [] m = re.findall(self.LINK_PATTERN, self.html) if m: - prefered_set = set(self.getConfig('preferedHoster').split('|')) + prefered_set = set(self.get_config('preferedHoster').split('|')) prefered_set = map(lambda s: s.lower().split('.')[0], prefered_set) - self.logDebug("PF: %s" % prefered_set) + self.log_debug("PF: %s" % prefered_set) tmp_links.extend(x[1] for x in m if x[0] in prefered_set) - self.urls = self.getLocation(tmp_links) + self.urls = self.get_location(tmp_links) if not self.urls: - ignored_set = set(self.getConfig('ignoredHoster').split('|')) + ignored_set = set(self.get_config('ignoredHoster').split('|')) ignored_set = map(lambda s: s.lower().split('.')[0], ignored_set) - self.logDebug("IG: %s" % ignored_set) + self.log_debug("IG: %s" % ignored_set) tmp_links.extend(x[1] for x in m if x[0] not in ignored_set) - self.urls = self.getLocation(tmp_links) + self.urls = self.get_location(tmp_links) - def getLocation(self, tmp_links): + def get_location(self, tmp_links): new_links = [] for link in tmp_links: try: diff --git a/module/plugins/crypter/FilebeerInfoFolder.py b/module/plugins/crypter/FilebeerInfoFolder.py index 5b401c555..5d0e26329 100644 --- a/module/plugins/crypter/FilebeerInfoFolder.py +++ b/module/plugins/crypter/FilebeerInfoFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class FilebeerInfoFolder(DeadCrypter): __name__ = "FilebeerInfoFolder" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filebeer\.info/\d*~f\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/FilecloudIoFolder.py b/module/plugins/crypter/FilecloudIoFolder.py index f900f4910..6c7b5be15 100644 --- a/module/plugins/crypter/FilecloudIoFolder.py +++ b/module/plugins/crypter/FilecloudIoFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FilecloudIoFolder(SimpleCrypter): __name__ = "FilecloudIoFolder" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(filecloud\.io|ifile\.it)/_\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), diff --git a/module/plugins/crypter/FilecryptCc.py b/module/plugins/crypter/FilecryptCc.py index 4d2b42f90..9f4ad69aa 100644 --- a/module/plugins/crypter/FilecryptCc.py +++ b/module/plugins/crypter/FilecryptCc.py @@ -9,14 +9,15 @@ import urlparse from Crypto.Cipher import AES -from module.plugins.Crypter import Crypter -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.internal.Crypter import Crypter +from module.plugins.captcha.ReCaptcha import ReCaptcha class FilecryptCc(Crypter): __name__ = "FilecryptCc" __type__ = "crypter" - __version__ = "0.15" + __version__ = "0.18" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?filecrypt\.cc/Container/\w+' @@ -47,66 +48,63 @@ class FilecryptCc(Crypter): if "content notfound" in self.html: #@NOTE: "content notfound" is NOT a typo self.offline() - self.handlePasswordProtection() - self.handleCaptcha() - self.handleMirrorPages() + self.handle_password_protection() + self.handle_captcha() + self.handle_mirror_pages() - for handle in (self.handleCNL, self.handleWeblinks, self.handleDlcContainer): + for handle in (self.handle_CNL, self.handle_weblinks, self.handle_dlc_container): handle() if self.links: self.packages = [(pyfile.package().name, self.links, pyfile.package().name)] return - def handleMirrorPages(self): - if "mirror=" not in self.siteWithLinks: + def handle_mirror_pages(self): + if "mirror=" not in self.site_with_links: return - mirror = re.findall(self.MIRROR_PAGE_PATTERN, self.siteWithLinks) + mirror = re.findall(self.MIRROR_PAGE_PATTERN, self.site_with_links) - self.logInfo(_("Found %d mirrors") % len(mirror)) + self.log_info(_("Found %d mirrors") % len(mirror)) for i in mirror[1:]: - self.siteWithLinks = self.siteWithLinks + self.load(i).decode("utf-8", "replace") + self.site_with_links = self.site_with_links + self.load(i) - def handlePasswordProtection(self): + def handle_password_protection(self): if '<input type="text" name="password"' not in self.html: return - self.logInfo(_("Folder is password protected")) + self.log_info(_("Folder is password protected")) - password = self.getPassword() + password = self.get_password() if not password: self.fail(_("Please enter the password in package section and try again")) - self.html = self.load(self.pyfile.url, post={"password": password}) + self.html = self.load(self.pyfile.url, post={'password': password}) - def handleCaptcha(self): + def handle_captcha(self): m = re.search(self.CAPTCHA_PATTERN, self.html) m2 = re.search(self.CIRCLE_CAPTCHA_PATTERN, self.html) - if m: #: normal captcha - self.logDebug("Captcha-URL: %s" % m.group(1)) + if m: #: Normal captcha + self.log_debug("Captcha-URL: %s" % m.group(1)) - captcha_code = self.decryptCaptcha(urlparse.urljoin(self.base_url, m.group(1)), - forceUser=True, - imgtype="gif") + captcha_code = self.captcha.decrypt(urlparse.urljoin(self.base_url, m.group(1)), + input_type="gif") - self.siteWithLinks = self.load(self.pyfile.url, - post={'recaptcha_response_field': captcha_code}, - decode=True) - elif m2: #: circle captcha - self.logDebug("Captcha-URL: %s" % m2.group(1)) + self.site_with_links = self.load(self.pyfile.url, + post={'recaptcha_response_field': captcha_code}) + elif m2: #: Circle captcha + self.log_debug("Captcha-URL: %s" % m2.group(1)) - captcha_code = self.decryptCaptcha('%s%s?c=abc' %(self.base_url, m2.group(1)), - result_type='positional') + captcha_code = self.captcha.decrypt('%s%s?c=abc' %(self.base_url, m2.group(1)), + output_type='positional') - self.siteWithLinks = self.load(self.pyfile.url, - post={'button.x': captcha_code[0], 'button.y': captcha_code[1]}, - decode=True) + self.site_with_links = self.load(self.pyfile.url, + post={'button.x': captcha_code[0], 'button.y': captcha_code[1]}) else: recaptcha = ReCaptcha(self) @@ -114,20 +112,19 @@ class FilecryptCc(Crypter): if captcha_key: response, challenge = recaptcha.challenge(captcha_key) - self.siteWithLinks = self.load(self.pyfile.url, - post={'g-recaptcha-response': response}, - decode=True) + self.site_with_links = self.load(self.pyfile.url, + post={'g-recaptcha-response': response}) else: - self.logInfo(_("No captcha found")) - self.siteWithLinks = self.html + self.log_info(_("No captcha found")) + self.site_with_links = self.html - if "recaptcha_image" in self.siteWithLinks or "data-sitekey" in self.siteWithLinks: - self.invalidCaptcha() + if "recaptcha_image" in self.site_with_links or "data-sitekey" in self.site_with_links: + self.captcha.invalid() self.retry() - def handleDlcContainer(self): - dlc = re.findall(self.DLC_LINK_PATTERN, self.siteWithLinks) + def handle_dlc_container(self): + dlc = re.findall(self.DLC_LINK_PATTERN, self.site_with_links) if not dlc: return @@ -136,9 +133,9 @@ class FilecryptCc(Crypter): self.links.append("%s/DLC/%s.dlc" % (self.base_url, i)) - def handleWeblinks(self): + def handle_weblinks(self): try: - weblinks = re.findall(self.WEBLINK_PATTERN, self.siteWithLinks) + weblinks = re.findall(self.WEBLINK_PATTERN, self.site_with_links) for link in weblinks: res = self.load("%s/Link/%s.html" % (self.base_url, link)) @@ -147,32 +144,32 @@ class FilecryptCc(Crypter): self.links.append(res2['location']) except Exception, e: - self.logDebug("Error decrypting weblinks: %s" % e) + self.log_debug("Error decrypting weblinks: %s" % e) - def handleCNL(self): + def handle_CNL(self): try: - vjk = re.findall('<input type="hidden" name="jk" value="function f\(\){ return \'(.*)\';}">', self.siteWithLinks) - vcrypted = re.findall('<input type="hidden" name="crypted" value="(.*)">', self.siteWithLinks) + vjk = re.findall('<input type="hidden" name="jk" value="function f\(\){ return \'(.*)\';}">', self.site_with_links) + vcrypted = re.findall('<input type="hidden" name="crypted" value="(.*)">', self.site_with_links) for i in xrange(len(vcrypted)): - self.links.extend(self._getLinks(vcrypted[i], vjk[i])) + self.links.extend(self._get_links(vcrypted[i], vjk[i])) except Exception, e: - self.logDebug("Error decrypting CNL: %s" % e) + self.log_debug("Error decrypting CNL: %s" % e) - def _getLinks(self, crypted, jk): - # Get key + def _get_links(self, crypted, jk): + #: Get key key = binascii.unhexlify(str(jk)) - # Decrypt + #: Decrypt Key = key IV = key obj = AES.new(Key, AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) - # Extract links + #: Extract links text = text.replace("\x00", "").replace("\r", "") links = filter(bool, text.split('\n')) diff --git a/module/plugins/crypter/FilefactoryComFolder.py b/module/plugins/crypter/FilefactoryComFolder.py index c0cd028cc..aec73f33c 100644 --- a/module/plugins/crypter/FilefactoryComFolder.py +++ b/module/plugins/crypter/FilefactoryComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FilefactoryComFolder(SimpleCrypter): __name__ = "FilefactoryComFolder" __type__ = "crypter" - __version__ = "0.32" + __version__ = "0.33" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?filefactory\.com/(?:f|folder)/\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -25,7 +26,7 @@ class FilefactoryComFolder(SimpleCrypter): PAGES_PATTERN = r'data-paginator-totalPages="(\d+)' - def loadPage(self, page_n): + def load_page(self, page_n): return self.load(self.pyfile.url, get={'page': page_n, 'show': 100}) diff --git a/module/plugins/crypter/FilerNetFolder.py b/module/plugins/crypter/FilerNetFolder.py index e2b44e868..4814c5933 100644 --- a/module/plugins/crypter/FilerNetFolder.py +++ b/module/plugins/crypter/FilerNetFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FilerNetFolder(SimpleCrypter): __name__ = "FilerNetFolder" __type__ = "crypter" - __version__ = "0.42" + __version__ = "0.43" + __status__ = "testing" __pattern__ = r'https?://filer\.net/folder/\w{16}' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), diff --git a/module/plugins/crypter/FileserveComFolder.py b/module/plugins/crypter/FileserveComFolder.py index 1363e2d45..44de55581 100644 --- a/module/plugins/crypter/FileserveComFolder.py +++ b/module/plugins/crypter/FileserveComFolder.py @@ -2,13 +2,14 @@ import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class FileserveComFolder(Crypter): __name__ = "FileserveComFolder" __type__ = "crypter" - __version__ = "0.11" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?fileserve\.com/list/\w+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/FilesonicComFolder.py b/module/plugins/crypter/FilesonicComFolder.py index 6cd4d8b8c..7ebba702a 100644 --- a/module/plugins/crypter/FilesonicComFolder.py +++ b/module/plugins/crypter/FilesonicComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class FilesonicComFolder(DeadCrypter): __name__ = "FilesonicComFolder" __type__ = "crypter" - __version__ = "0.12" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filesonic\.com/folder/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/FilestubeCom.py b/module/plugins/crypter/FilestubeCom.py index 133f4a53f..5fcd72c64 100644 --- a/module/plugins/crypter/FilestubeCom.py +++ b/module/plugins/crypter/FilestubeCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FilestubeCom(SimpleCrypter): __name__ = "FilestubeCom" __type__ = "crypter" - __version__ = "0.05" + __version__ = "0.07" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filestube\.(?:com|to)/\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -19,7 +20,7 @@ class FilestubeCom(SimpleCrypter): LINK_PATTERN = r'<a class=\"file-link-main(?: noref)?\" [^>]* href=\"(http://[^\"]+)' - NAME_PATTERN = r'<h1\s*> (?P<N>.+) download\s*</h1>' + NAME_PATTERN = r'<h1\s*> (?P<N>.+?) download\s*</h1>' getInfo = create_getInfo(FilestubeCom) diff --git a/module/plugins/crypter/FiletramCom.py b/module/plugins/crypter/FiletramCom.py index b012d35bc..6603a3542 100644 --- a/module/plugins/crypter/FiletramCom.py +++ b/module/plugins/crypter/FiletramCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FiletramCom(SimpleCrypter): __name__ = "FiletramCom" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filetram\.com/[^/]+/.+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), diff --git a/module/plugins/crypter/FiredriveComFolder.py b/module/plugins/crypter/FiredriveComFolder.py index 792f3198b..84b6cf34a 100644 --- a/module/plugins/crypter/FiredriveComFolder.py +++ b/module/plugins/crypter/FiredriveComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class FiredriveComFolder(DeadCrypter): __name__ = "FiredriveComFolder" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(firedrive|putlocker)\.com/share/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/FourChanOrg.py b/module/plugins/crypter/FourChanOrg.py index 366adef14..65a2ac788 100644 --- a/module/plugins/crypter/FourChanOrg.py +++ b/module/plugins/crypter/FourChanOrg.py @@ -5,13 +5,14 @@ import re import urlparse -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class FourChanOrg(Crypter): __name__ = "FourChanOrg" __type__ = "crypter" - __version__ = "0.31" + __version__ = "0.33" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?boards\.4chan\.org/\w+/res/(\d+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/FreakhareComFolder.py b/module/plugins/crypter/FreakhareComFolder.py index 173660668..f7f1946f4 100644 --- a/module/plugins/crypter/FreakhareComFolder.py +++ b/module/plugins/crypter/FreakhareComFolder.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FreakhareComFolder(SimpleCrypter): __name__ = "FreakhareComFolder" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?freakshare\.com/folder/.+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -25,7 +26,7 @@ class FreakhareComFolder(SimpleCrypter): PAGES_PATTERN = r'Pages: +(\d+)' - def loadPage(self, page_n): + def load_page(self, page_n): if not hasattr(self, 'f_id') and not hasattr(self, 'f_md5'): m = re.search(r'http://freakshare.com/\?x=folder&f_id=(\d+)&f_md5=(\w+)', self.html) if m: @@ -36,7 +37,7 @@ class FreakhareComFolder(SimpleCrypter): 'f_md5': self.f_md5, 'entrys': '20', 'page': page_n - 1, - 'order': ''}, decode=True) + 'order': ''}) getInfo = create_getInfo(FreakhareComFolder) diff --git a/module/plugins/crypter/FreetexthostCom.py b/module/plugins/crypter/FreetexthostCom.py index cf6fbb8a4..350f89202 100644 --- a/module/plugins/crypter/FreetexthostCom.py +++ b/module/plugins/crypter/FreetexthostCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FreetexthostCom(SimpleCrypter): __name__ = "FreetexthostCom" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?freetexthost\.com/\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -20,7 +21,7 @@ class FreetexthostCom(SimpleCrypter): __authors__ = [("stickell", "l.stickell@yahoo.it")] - def getLinks(self): + def get_links(self): m = re.search(r'<div id="contentsinner">\s*(.+)<div class="viewcount">', self.html, re.S) if m is None: self.error(_("Unable to extract links")) diff --git a/module/plugins/crypter/FshareVnFolder.py b/module/plugins/crypter/FshareVnFolder.py index bbee53337..f4941007a 100644 --- a/module/plugins/crypter/FshareVnFolder.py +++ b/module/plugins/crypter/FshareVnFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class FshareVnFolder(SimpleCrypter): __name__ = "FshareVnFolder" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?fshare\.vn/folder/.+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), diff --git a/module/plugins/crypter/FurLy.py b/module/plugins/crypter/FurLy.py new file mode 100644 index 000000000..595fcb34d --- /dev/null +++ b/module/plugins/crypter/FurLy.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class FurLy(SimpleCrypter): + __name__ = "FurLy" + __type__ = "crypter" + __version__ = "0.02" + __status__ = "testing" + + __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/Go4UpCom.py b/module/plugins/crypter/Go4UpCom.py index 22f31f6f6..026982014 100644 --- a/module/plugins/crypter/Go4UpCom.py +++ b/module/plugins/crypter/Go4UpCom.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class Go4UpCom(SimpleCrypter): __name__ = "Go4UpCom" __type__ = "crypter" - __version__ = "0.12" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://go4up\.com/(dl/\w{12}|rd/\w{12}/\d+)' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -29,7 +30,7 @@ class Go4UpCom(SimpleCrypter): OFFLINE_PATTERN = r'>\s*(404 Page Not Found|File not Found|Mirror does not exist)' - def getLinks(self): + def get_links(self): links = [] m = re.search(r'(/download/gethosts/.+?)"', self.html) diff --git a/module/plugins/crypter/GooGl.py b/module/plugins/crypter/GooGl.py index 30e193b9d..76a542408 100644 --- a/module/plugins/crypter/GooGl.py +++ b/module/plugins/crypter/GooGl.py @@ -1,13 +1,14 @@ # -*- 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.04" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?goo\.gl/([a-zA-Z]+/)?\w+' @@ -22,11 +23,11 @@ class GooGl(SimpleDereferer): OFFLINE_PATTERN = r'has been disabled|does not exist' - def getLink(self): + def get_links(self): rep = self.load(self.API_URL, get={'shortUrl': self.pyfile.url}) - self.logDebug("JSON data: " + rep) + self.log_debug("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/GoogledriveComFolder.py b/module/plugins/crypter/GoogledriveComFolder.py index 70898b313..88c7ebab2 100644 --- a/module/plugins/crypter/GoogledriveComFolder.py +++ b/module/plugins/crypter/GoogledriveComFolder.py @@ -6,10 +6,11 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class GoogledriveComFolder(SimpleCrypter): __name__ = "GoogledriveCom" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?drive\.google\.com/folderview\?.*id=\w+' - __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides core.config['general']['folder_per_package'] + __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides pyload.config['general']['folder_per_package'] ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] __description__ = """Drive.google.com folder decrypter plugin""" diff --git a/module/plugins/crypter/HoerbuchIn.py b/module/plugins/crypter/HoerbuchIn.py index ccc3ab664..27075324d 100644 --- a/module/plugins/crypter/HoerbuchIn.py +++ b/module/plugins/crypter/HoerbuchIn.py @@ -2,15 +2,16 @@ import re -from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup +import BeautifulSoup -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class HoerbuchIn(Crypter): __name__ = "HoerbuchIn" __type__ = "crypter" - __version__ = "0.60" + __version__ = "0.62" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?hoerbuch\.in/(wp/horbucher/\d+/.+/|tp/out\.php\?.+|protection/folder_\d+\.html)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -31,26 +32,26 @@ class HoerbuchIn(Crypter): if self.article.match(pyfile.url): html = self.load(pyfile.url) - soup = BeautifulSoup(html, convertEntities=BeautifulStoneSoup.HTML_ENTITIES) + soup = BeautifulSoup.BeautifulSoup(html, convertEntities=BeautifulSoup.BeautifulStoneSoup.HTML_ENTITIES) - abookname = soup.find("a", attrs={"rel": "bookmark"}).text - for a in soup.findAll("a", attrs={"href": self.protection}): + abookname = soup.find("a", attrs={'rel': "bookmark"}).text + for a in soup.findAll("a", attrs={'href': self.protection}): package = "%s (%s)" % (abookname, a.previousSibling.previousSibling.text[:-1]) - links = self.decryptFolder(a['href']) + links = self.decrypt_folder(a['href']) self.packages.append((package, links, package)) else: - self.urls = self.decryptFolder(pyfile.url) + self.urls = self.decrypt_folder(pyfile.url) - def decryptFolder(self, url): + def decrypt_folder(self, url): m = self.protection.search(url) if m is None: self.fail(_("Bad URL")) url = m.group(0) self.pyfile.url = url - html = self.load(url, post={"viewed": "adpg"}) + html = self.load(url, post={'viewed': "adpg"}) links = [] pattern = re.compile("http://www\.hoerbuch\.in/protection/(\w+)/(.*?)\"") diff --git a/module/plugins/crypter/HotfileComFolder.py b/module/plugins/crypter/HotfileComFolder.py index f1dd56228..1b2429f4a 100644 --- a/module/plugins/crypter/HotfileComFolder.py +++ b/module/plugins/crypter/HotfileComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class HotfileComFolder(DeadCrypter): __name__ = "HotfileComFolder" __type__ = "crypter" - __version__ = "0.30" + __version__ = "0.31" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?hotfile\.com/list/\w+/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/ILoadTo.py b/module/plugins/crypter/ILoadTo.py index 4c7387739..03826cc5a 100644 --- a/module/plugins/crypter/ILoadTo.py +++ b/module/plugins/crypter/ILoadTo.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class ILoadTo(DeadCrypter): __name__ = "ILoadTo" __type__ = "crypter" - __version__ = "0.11" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?iload\.to/go/\d+-[\w.-]+/' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/ImgurComAlbum.py b/module/plugins/crypter/ImgurComAlbum.py index 9ef7797af..488979b48 100644 --- a/module/plugins/crypter/ImgurComAlbum.py +++ b/module/plugins/crypter/ImgurComAlbum.py @@ -7,7 +7,8 @@ from module.utils import uniqify class ImgurComAlbum(SimpleCrypter): __name__ = "ImgurComAlbum" __type__ = "crypter" - __version__ = "0.51" + __version__ = "0.52" + __status__ = "testing" __pattern__ = r'https?://(?:www\.|m\.)?imgur\.com/(a|gallery|)/?\w{5,7}' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -23,7 +24,7 @@ class ImgurComAlbum(SimpleCrypter): LINK_PATTERN = r'i\.imgur\.com/\w{7}s?\.(?:jpeg|jpg|png|gif|apng)' - def getLinks(self): + def get_links(self): f = lambda url: "http://" + re.sub(r'(\w{7})s\.', r'\1.', url) return uniqify(map(f, re.findall(self.LINK_PATTERN, self.html))) diff --git a/module/plugins/crypter/LetitbitNetFolder.py b/module/plugins/crypter/LetitbitNetFolder.py index b60d754a7..e560306f5 100644 --- a/module/plugins/crypter/LetitbitNetFolder.py +++ b/module/plugins/crypter/LetitbitNetFolder.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class LetitbitNetFolder(Crypter): __name__ = "LetitbitNetFolder" __type__ = "crypter" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?letitbit\.net/folder/\w+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/LinkCryptWs.py b/module/plugins/crypter/LinkCryptWs.py index 5c65e726d..af13f55f6 100644 --- a/module/plugins/crypter/LinkCryptWs.py +++ b/module/plugins/crypter/LinkCryptWs.py @@ -7,14 +7,15 @@ import pycurl from Crypto.Cipher import AES -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter from module.utils import html_unescape class LinkCryptWs(Crypter): __name__ = "LinkCryptWs" __type__ = "crypter" - __version__ = "0.08" + __version__ = "0.10" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?linkcrypt\.ws/(dir|container)/(?P<ID>\w+)' @@ -36,13 +37,13 @@ class LinkCryptWs(Crypter): def prepare(self): - # Init + #: Init self.fileid = re.match(self.__pattern__, self.pyfile.url).group('ID') self.req.cj.setCookie("linkcrypt.ws", "language", "en") - # Request package - self.req.http.c.setopt(pycurl.USERAGENT, "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko") #: better chance to not get those key-captchas + #: Request package + self.req.http.c.setopt(pycurl.USERAGENT, "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko") #: Better chance to not get those key-captchas self.html = self.load(self.pyfile.url) @@ -52,34 +53,34 @@ class LinkCryptWs(Crypter): self.prepare() - if not self.isOnline(): + if not self.is_online(): self.offline() - if self.isKeyCaptchaProtected(): + if self.is_key_captcha_protected(): self.retry(8, 15, _("Can't handle Key-Captcha")) - if self.isCaptchaProtected(): + if self.is_captcha_protected(): self.captcha = True - self.unlockCaptchaProtection() - self.handleCaptchaErrors() + self.unlock_captcha_protection() + self.handle_captcha_errors() - # Check for protection - if self.isPasswordProtected(): - self.unlockPasswordProtection() - self.handleErrors() + #: Check for protection + if self.is_password_protected(): + self.unlock_password_protection() + self.handle_errors() - # get unrar password + #: Get unrar password self.getunrarpw() - # Get package name and folder - package_name, folder_name = self.getPackageInfo() + #: Get package name and folder + package_name, folder_name = self.get_package_info() - #get the container definitions from script section + #: Get the container definitions from script section self.get_container_html() - # Extract package links + #: Extract package links for type in self.sources: - links = self.handleLinkSource(type) + links = self.handle_link_source(type) if links: self.links.extend(links) @@ -89,59 +90,59 @@ class LinkCryptWs(Crypter): self.packages = [(package_name, self.links, folder_name)] - def isOnline(self): + def is_online(self): if "<title>Linkcrypt.ws // Error 404</title>" in self.html: - self.logDebug("Folder doesn't exist anymore") + self.log_debug("Folder doesn't exist anymore") return False else: return True - def isPasswordProtected(self): + def is_password_protected(self): if "Authorizing" in self.html: - self.logDebug("Links are password protected") + self.log_debug("Links are password protected") return True else: return False - def isCaptchaProtected(self): + def is_captcha_protected(self): if 'id="captcha">' in self.html: - self.logDebug("Links are captcha protected") + self.log_debug("Links are captcha protected") return True else: return False - def isKeyCaptchaProtected(self): + def is_key_captcha_protected(self): if re.search(r'>If the folder does not open after klick on <', self.html, re.I): return True else: return False - def unlockPasswordProtection(self): - password = self.getPassword() + def unlock_password_protection(self): + password = self.get_password() if password: - self.logDebug("Submitting password [%s] for protected links" % password) - self.html = self.load(self.pyfile.url, post={"password": password, 'x': "0", 'y': "0"}) + self.log_debug("Submitting password [%s] for protected links" % password) + self.html = self.load(self.pyfile.url, post={'password': password, 'x': "0", 'y': "0"}) else: self.fail(_("Folder is password protected")) - def unlockCaptchaProtection(self): + def unlock_captcha_protection(self): captcha_url = re.search(r'<form.*?id\s*?=\s*?"captcha"[^>]*?>.*?<\s*?input.*?src="(.+?)"', self.html, re.I | re.S).group(1) - captcha_code = self.decryptCaptcha(captcha_url, forceUser=True, imgtype="gif", result_type='positional') + captcha_code = self.captcha.decrypt(captcha_url, input_type="gif", output_type='positional') - self.html = self.load(self.pyfile.url, post={"x": captcha_code[0], "y": captcha_code[1]}) + self.html = self.load(self.pyfile.url, post={'x': captcha_code[0], 'y': captcha_code[1]}) - def getPackageInfo(self): + def get_package_info(self): name = self.pyfile.package().name folder = self.pyfile.package().folder - self.logDebug("Defaulting to pyfile name [%s] and folder [%s] for package" % (name, folder)) + self.log_debug("Defaulting to pyfile name [%s] and folder [%s] for package" % (name, folder)) return name, folder @@ -149,51 +150,51 @@ class LinkCryptWs(Crypter): def getunrarpw(self): sitein = self.html indexi = sitein.find("|source|") + 8 - indexe = sitein.find("|",indexi) + indexe = sitein.find("|", indexi) unrarpw = sitein[indexi:indexe] if not (unrarpw == "Password" or "Dateipasswort") : - self.logDebug("File password set to: [%s]"% unrarpw) + self.log_debug("File password set to: [%s]"% unrarpw) self.pyfile.package().password = unrarpw - def handleErrors(self): - if self.isPasswordProtected(): + def handle_errors(self): + if self.is_password_protected(): self.fail(_("Incorrect password")) - def handleCaptchaErrors(self): + def handle_captcha_errors(self): if self.captcha: if "Your choice was wrong!" in self.html: - self.invalidCaptcha() + self.captcha.invalid() self.retry() else: - self.correctCaptcha() + self.captcha.correct() - def handleLinkSource(self, type): - if type == 'cnl': - return self.handleCNL2() + def handle_link_source(self, type): + if type == "cnl": + return self.handle_CNL2() - elif type == 'web': - return self.handleWebLinks() + elif type == "web": + return self.handle_web_links() elif type in ('rsdf', 'ccf', 'dlc'): - return self.handleContainer(type) + return self.handle_container(type) else: self.fail(_("Unknown source type: %s") % type) #@TODO: Replace with self.error in 0.4.10 - def handleWebLinks(self): - self.logDebug("Search for Web links ") + def handle_web_links(self): + self.log_debug("Search for Web links ") package_links = [] pattern = r'<form action="http://linkcrypt.ws/out.html"[^>]*?>.*?<input[^>]*?value="(.+?)"[^>]*?name="file"' ids = re.findall(pattern, self.html, re.I | re.S) - self.logDebug("Decrypting %d Web links" % len(ids)) + self.log_debug("Decrypting %d Web links" % len(ids)) for idx, weblink_id in enumerate(ids): try: @@ -208,7 +209,7 @@ class LinkCryptWs(Crypter): package_links.append(link2) except Exception, detail: - self.logDebug("Error decrypting Web link %s, %s" % (weblink_id, detail)) + self.log_debug("Error decrypting Web link %s, %s" % (weblink_id, detail)) return package_links @@ -228,13 +229,13 @@ class LinkCryptWs(Crypter): return self.js.eval(line.replace('{}))',"{}).replace('document.open();document.write','').replace(';document.close();',''))")) - def handleContainer(self, type): + def handle_container(self, type): package_links = [] type = type.lower() - self.logDebug('Search for %s Container links' % type.upper()) + self.log_debug('Search for %s Container links' % type.upper()) - if not type.isalnum(): # check to prevent broken re-pattern (cnl2,rsdf,ccf,dlc,web are all alpha-numeric) + if not type.isalnum(): #: Check to prevent broken re-pattern (cnl2, rsdf, ccf, dlc, web are all alpha-numeric) self.fail(_("Unknown container type: %s") % type) #@TODO: Replace with self.error in 0.4.10 for line in self.container_html: @@ -245,18 +246,18 @@ class LinkCryptWs(Crypter): if not clink: continue - self.logDebug("clink avaible") + self.log_debug("clink avaible") - package_name, folder_name = self.getPackageInfo() - self.logDebug("Added package with name %s.%s and container link %s" %( package_name, type, clink.group(1))) - self.core.api.uploadContainer( "%s.%s" %(package_name, type), self.load(clink.group(1))) + package_name, folder_name = self.get_package_info() + self.log_debug("Added package with name %s.%s and container link %s" %( package_name, type, clink.group(1))) + self.pyload.api.uploadContainer('.'.join([package_name, type]), self.load(clink.group(1))) return "Found it" return package_links - def handleCNL2(self): - self.logDebug("Search for CNL links") + def handle_CNL2(self): + self.log_debug("Search for CNL links") package_links = [] cnl_line = None @@ -267,52 +268,52 @@ class LinkCryptWs(Crypter): break if cnl_line: - self.logDebug("cnl_line gefunden") + self.log_debug("cnl_line gefunden") try: cnl_section = self.handle_javascript(cnl_line) - (vcrypted, vjk) = self._getCipherParams(cnl_section) + (vcrypted, vjk) = self._get_cipher_params(cnl_section) for (crypted, jk) in zip(vcrypted, vjk): - package_links.extend(self._getLinks(crypted, jk)) + package_links.extend(self._get_links(crypted, jk)) except Exception: - self.logError(_("Unable to decrypt CNL links (JS Error) try to get over links")) - return self.handleWebLinks() + self.log_error(_("Unable to decrypt CNL links (JS Error) try to get over links")) + return self.handle_web_links() return package_links - def _getCipherParams(self, cnl_section): - # Get jk + def _get_cipher_params(self, cnl_section): + #: Get jk jk_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkCryptWs.JK_KEY vjk = re.findall(jk_re, cnl_section) - # Get crypted + #: Get crypted crypted_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkCryptWs.CRYPTED_KEY vcrypted = re.findall(crypted_re, cnl_section) - # Log and return - self.logDebug("Detected %d crypted blocks" % len(vcrypted)) + #: Log and return + self.log_debug("Detected %d crypted blocks" % len(vcrypted)) return vcrypted, vjk - def _getLinks(self, crypted, jk): - # Get key + def _get_links(self, crypted, jk): + #: Get key jreturn = self.js.eval("%s f()" % jk) key = binascii.unhexlify(jreturn) - self.logDebug("JsEngine returns value [%s]" % jreturn) + self.log_debug("JsEngine returns value [%s]" % jreturn) - # Decrypt + #: Decrypt Key = key IV = key obj = AES.new(Key, AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) - # Extract links + #: Extract links text = text.replace("\x00", "").replace("\r", "") links = filter(bool, text.split('\n')) - # Log and return - self.logDebug("Package has %d links" % len(links)) + #: Log and return + self.log_debug("Package has %d links" % len(links)) return links diff --git a/module/plugins/crypter/LinkSaveIn.py b/module/plugins/crypter/LinkSaveIn.py index 95652096d..36b545de8 100644 --- a/module/plugins/crypter/LinkSaveIn.py +++ b/module/plugins/crypter/LinkSaveIn.py @@ -1,12 +1,13 @@ # -*- 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.06" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?linksave\.in/\w+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/LinkdecrypterCom.py b/module/plugins/crypter/LinkdecrypterCom.py index 0704214d0..d8812dbd5 100644 --- a/module/plugins/crypter/LinkdecrypterCom.py +++ b/module/plugins/crypter/LinkdecrypterCom.py @@ -2,13 +2,14 @@ import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.MultiCrypter import MultiCrypter -class LinkdecrypterCom(Crypter): +class LinkdecrypterCom(MultiCrypter): __name__ = "LinkdecrypterCom" __type__ = "crypter" - __version__ = "0.29" + __version__ = "0.32" + __status__ = "testing" __pattern__ = r'^unmatchable$' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -27,15 +28,15 @@ class LinkdecrypterCom(Crypter): def setup(self): - self.password = self.getPassword() + self.password = self.get_password() self.req.setOption("timeout", 300) def decrypt(self, pyfile): retries = 5 - post_dict = {"link_cache": "on", "pro_links": pyfile.url, "modo_links": "text"} - self.html = self.load('http://linkdecrypter.com/', post=post_dict, decode=True) + post_dict = {'link_cache': "on", 'pro_links': pyfile.url, 'modo_links': "text"} + self.html = self.load('http://linkdecrypter.com/', post=post_dict) while retries: m = re.search(self.TEXTAREA_PATTERN, self.html, re.S) @@ -49,21 +50,21 @@ class LinkdecrypterCom(Crypter): m = re.search(r"<p><i><b>([^<]+)</b></i></p>", self.html) msg = m.group(1) if m else "" - self.logInfo(_("Captcha protected link"), result_type, msg) + self.log_info(_("Captcha protected link"), result_type, msg) - captcha = self.decryptCaptcha(captcha_url, result_type=result_type) + captcha = self.captcha.decrypt(captcha_url, output_type=result_type) if result_type == "positional": captcha = "%d|%d" % captcha - self.html = self.load('http://linkdecrypter.com/', post={"captcha": captcha}, decode=True) + self.html = self.load('http://linkdecrypter.com/', post={'captcha': captcha}) retries -= 1 elif self.PASSWORD_PATTERN in self.html: if self.password: - self.logInfo(_("Password protected link")) - self.html = self.load('http://linkdecrypter.com/', post={'password': self.password}, decode=True) + self.log_info(_("Password protected link")) + self.html = self.load('http://linkdecrypter.com/', post={'password': self.password}) else: self.fail(_("Missing password")) else: retries -= 1 - self.html = self.load('http://linkdecrypter.com/', decode=True) + self.html = self.load('http://linkdecrypter.com/') diff --git a/module/plugins/crypter/LixIn.py b/module/plugins/crypter/LixIn.py index 5c77eae5e..2d26564e8 100644 --- a/module/plugins/crypter/LixIn.py +++ b/module/plugins/crypter/LixIn.py @@ -3,13 +3,14 @@ import re import urlparse -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class LixIn(Crypter): __name__ = "LixIn" __type__ = "crypter" - __version__ = "0.22" + __version__ = "0.24" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?lix\.in/(?P<ID>.+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -33,9 +34,9 @@ class LixIn(Crypter): self.error(_("Unable to identify file ID")) id = m.group('ID') - self.logDebug("File id is %s" % id) + self.log_debug("File id is %s" % id) - self.html = self.load(url, decode=True) + self.html = self.load(url) m = re.search(self.SUBMIT_PATTERN, self.html) if m is None: @@ -46,18 +47,18 @@ class LixIn(Crypter): for _i in xrange(5): m = re.search(self.CAPTCHA_PATTERN, self.html) if m: - self.logDebug("Trying captcha") - captcharesult = self.decryptCaptcha(urlparse.urljoin("http://lix.in/", m.group(1))) - self.html = self.load(url, decode=True, - post={"capt": captcharesult, "submit": "submit", "tiny": id}) + self.log_debug("Trying captcha") + captcharesult = self.captcha.decrypt(urlparse.urljoin("http://lix.in/", m.group(1))) + self.html = self.load(url, + post={'capt': captcharesult, 'submit': "submit", 'tiny': id}) else: - self.logDebug("No captcha/captcha solved") + self.log_debug("No captcha/captcha solved") else: - self.html = self.load(url, decode=True, post={"submit": "submit", "tiny": id}) + self.html = self.load(url, post={'submit': "submit", 'tiny': id}) m = re.search(self.LINK_PATTERN, self.html) if m is None: self.error(_("Unable to find destination url")) else: self.urls = [m.group(1)] - self.logDebug("Found link %s, adding to package" % self.urls[0]) + self.log_debug("Found link %s, adding to package" % self.urls[0]) diff --git a/module/plugins/crypter/LofCc.py b/module/plugins/crypter/LofCc.py index 62e05f299..b25c9485a 100644 --- a/module/plugins/crypter/LofCc.py +++ b/module/plugins/crypter/LofCc.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class LofCc(DeadCrypter): __name__ = "LofCc" __type__ = "crypter" - __version__ = "0.21" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?lof\.cc/(.+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/MBLinkInfo.py b/module/plugins/crypter/MBLinkInfo.py index 7ff400f7e..98c63b9d4 100644 --- a/module/plugins/crypter/MBLinkInfo.py +++ b/module/plugins/crypter/MBLinkInfo.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class MBLinkInfo(DeadCrypter): __name__ = "MBLinkInfo" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?mblink\.info/?\?id=(\d+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/MediafireComFolder.py b/module/plugins/crypter/MediafireComFolder.py index c1612bb6a..81d880725 100644 --- a/module/plugins/crypter/MediafireComFolder.py +++ b/module/plugins/crypter/MediafireComFolder.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter from module.plugins.hoster.MediafireCom import checkHTMLHeader from module.common.json_layer import json_loads @@ -9,7 +9,8 @@ from module.common.json_layer import json_loads class MediafireComFolder(Crypter): __name__ = "MediafireComFolder" __type__ = "crypter" - __version__ = "0.14" + __version__ = "0.16" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?mediafire\.com/(folder/|\?sharekey=|\?\w{13}($|[/#]))' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -26,27 +27,27 @@ class MediafireComFolder(Crypter): def decrypt(self, pyfile): url, result = checkHTMLHeader(pyfile.url) - self.logDebug("Location (%d): %s" % (result, url)) + self.log_debug("Location (%d): %s" % (result, url)) if result == 0: - # load and parse html + #: Load and parse html html = self.load(pyfile.url) m = re.search(self.LINK_PATTERN, html) if m: - # file page + #: File page self.urls.append("http://www.mediafire.com/file/%s" % m.group(1)) else: - # folder page + #: Folder page m = re.search(self.FOLDER_KEY_PATTERN, html) if m: folder_key = m.group(1) - self.logDebug("FOLDER KEY: %s" % folder_key) + self.log_debug("FOLDER KEY: %s" % folder_key) json_resp = json_loads(self.load("http://www.mediafire.com/api/folder/get_info.php", get={'folder_key' : folder_key, 'response_format': "json", 'version' : 1})) - #self.logInfo(json_resp) + # self.log_info(json_resp) if json_resp['response']['result'] == "Success": for link in json_resp['response']['folder_info']['files']: self.urls.append("http://www.mediafire.com/file/%s" % link['quickkey']) diff --git a/module/plugins/crypter/MegaCoNzFolder.py b/module/plugins/crypter/MegaCoNzFolder.py index bd135ac5f..107746819 100644 --- a/module/plugins/crypter/MegaCoNzFolder.py +++ b/module/plugins/crypter/MegaCoNzFolder.py @@ -2,15 +2,16 @@ import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class MegaCoNzFolder(Crypter): __name__ = "MegaCoNzFolder" __type__ = "crypter" - __version__ = "0.04" + __version__ = "0.06" + __status__ = "testing" - __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 +27,4 @@ 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) - - if not self.urls: #@TODO: Remove in 0.4.10 - self.fail(_("No link grabbed")) + self.urls = re.findall(r'(https://mega(\.co)?\.nz/#N!.+?)<', self.html) diff --git a/module/plugins/crypter/MegaRapidCzFolder.py b/module/plugins/crypter/MegaRapidCzFolder.py index fadd6dbed..8e7bcdf6b 100644 --- a/module/plugins/crypter/MegaRapidCzFolder.py +++ b/module/plugins/crypter/MegaRapidCzFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class MegaRapidCzFolder(SimpleCrypter): __name__ = "MegaRapidCzFolder" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(share|mega)rapid\.cz/slozka/\d+/\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), diff --git a/module/plugins/crypter/MegauploadComFolder.py b/module/plugins/crypter/MegauploadComFolder.py index 60e4af57e..c0ae6d16a 100644 --- a/module/plugins/crypter/MegauploadComFolder.py +++ b/module/plugins/crypter/MegauploadComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class MegauploadComFolder(DeadCrypter): __name__ = "MegauploadComFolder" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?megaupload\.com/(\?f|xml/folderfiles\.php\?.*&?folderid)=\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/Movie2KTo.py b/module/plugins/crypter/Movie2KTo.py index 919d77c86..53636cda3 100644 --- a/module/plugins/crypter/Movie2KTo.py +++ b/module/plugins/crypter/Movie2KTo.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class Movie2KTo(DeadCrypter): __name__ = "Movie2KTo" __type__ = "crypter" - __version__ = "0.51" + __version__ = "0.52" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?movie2k\.to/(.+)\.html' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/MultiUpOrg.py b/module/plugins/crypter/MultiUpOrg.py index b676c3029..b4326b679 100644 --- a/module/plugins/crypter/MultiUpOrg.py +++ b/module/plugins/crypter/MultiUpOrg.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class MultiUpOrg(SimpleCrypter): __name__ = "MultiUpOrg" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?multiup\.org/(en|fr)/(?P<TYPE>project|download|miror)/\w+(/\w+)?' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -24,7 +25,7 @@ class MultiUpOrg(SimpleCrypter): NAME_PATTERN = r'<title>.*(?:Project|Projet|ownload|élécharger) (?P<N>.+?) (\(|- )' - def getLinks(self): + def get_links(self): m_type = re.match(self.__pattern__, self.pyfile.url).group('TYPE') if m_type == "project": diff --git a/module/plugins/crypter/MultiloadCz.py b/module/plugins/crypter/MultiloadCz.py index eea689a09..d9b6236be 100644 --- a/module/plugins/crypter/MultiloadCz.py +++ b/module/plugins/crypter/MultiloadCz.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class MultiloadCz(Crypter): __name__ = "MultiloadCz" __type__ = "crypter" - __version__ = "0.40" + __version__ = "0.42" + __status__ = "testing" __pattern__ = r'http://(?:[^/]*\.)?multiload\.cz/(stahnout|slozka)/.+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -25,7 +26,7 @@ class MultiloadCz(Crypter): def decrypt(self, pyfile): - self.html = self.load(pyfile.url, decode=True) + self.html = self.load(pyfile.url) if re.match(self.__pattern__, pyfile.url).group(1) == "slozka": m = re.search(self.FOLDER_PATTERN, self.html) @@ -34,9 +35,9 @@ class MultiloadCz(Crypter): else: m = re.findall(self.LINK_PATTERN, self.html) if m: - prefered_set = set(self.getConfig('usedHoster').split('|')) + prefered_set = set(self.get_config('usedHoster').split('|')) self.urls.extend(x[1] for x in m if x[0] in prefered_set) if not self.urls: - ignored_set = set(self.getConfig('ignoredHoster').split('|')) + ignored_set = set(self.get_config('ignoredHoster').split('|')) self.urls.extend(x[1] for x in m if x[0] not in ignored_set) diff --git a/module/plugins/crypter/MultiuploadCom.py b/module/plugins/crypter/MultiuploadCom.py index 41794445a..358758b7a 100644 --- a/module/plugins/crypter/MultiuploadCom.py +++ b/module/plugins/crypter/MultiuploadCom.py @@ -6,12 +6,13 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class MultiuploadCom(DeadCrypter): __name__ = "MultiuploadCom" __type__ = "crypter" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?multiupload\.(com|nl)/\w+' __config__ = [] #@TODO: Remove in 0.4.10 - __description__ = """ MultiUpload.com decrypter plugin """ + __description__ = """MultiUpload.com decrypter plugin""" __license__ = "GPLv3" __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] diff --git a/module/plugins/crypter/NCryptIn.py b/module/plugins/crypter/NCryptIn.py index 593e9b506..d483be323 100644 --- a/module/plugins/crypter/NCryptIn.py +++ b/module/plugins/crypter/NCryptIn.py @@ -5,14 +5,15 @@ import re from Crypto.Cipher import AES -from module.plugins.Crypter import Crypter -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.internal.Crypter import Crypter +from module.plugins.captcha.ReCaptcha import ReCaptcha class NCryptIn(Crypter): __name__ = "NCryptIn" __type__ = "crypter" - __version__ = "1.35" + __version__ = "1.37" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?ncrypt\.in/(?P<TYPE>folder|link|frame)-([^/\?]+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -32,62 +33,62 @@ class NCryptIn(Crypter): def setup(self): self.package = None - self.cleanedHtml = None + self.cleaned_html = None self.links_source_order = ["cnl2", "rsdf", "ccf", "dlc", "web"] self.protection_type = None def decrypt(self, pyfile): - # Init + #: Init self.package = pyfile.package() package_links = [] package_name = self.package.name folder_name = self.package.folder - # Deal with single links - if self.isSingleLink(): - package_links.extend(self.handleSingleLink()) + #: Deal with single links + if self.is_single_link(): + package_links.extend(self.handle_single_link()) - # Deal with folders + #: Deal with folders else: - # Request folder home - self.html = self.requestFolderHome() - self.cleanedHtml = self.removeHtmlCrap(self.html) - if not self.isOnline(): + #: Request folder home + self.html = self.request_folder_home() + self.cleaned_html = self.remove_html_crap(self.html) + if not self.is_online(): self.offline() - # Check for folder protection - if self.isProtected(): - self.html = self.unlockProtection() - self.cleanedHtml = self.removeHtmlCrap(self.html) - self.handleErrors() + #: Check for folder protection + if self.is_protected(): + self.html = self.unlock_protection() + self.cleaned_html = self.remove_html_crap(self.html) + self.handle_errors() - # Prepare package name and folder - (package_name, folder_name) = self.getPackageInfo() + #: Prepare package name and folder + (package_name, folder_name) = self.get_package_info() - # Extract package links + #: Extract package links for link_source_type in self.links_source_order: - package_links.extend(self.handleLinkSource(link_source_type)) - if package_links: # use only first source which provides links + package_links.extend(self.handle_link_source(link_source_type)) + if package_links: #: Use only first source which provides links break package_links = set(package_links) - # Pack and return links + #: Pack and return links if package_links: self.packages = [(package_name, package_links, folder_name)] - def isSingleLink(self): + def is_single_link(self): link_type = re.match(self.__pattern__, self.pyfile.url).group('TYPE') return link_type in ("link", "frame") - def requestFolderHome(self): - return self.load(self.pyfile.url, decode=True) + def request_folder_home(self): + return self.load(self.pyfile.url) - def removeHtmlCrap(self, content): + def remove_html_crap(self, content): patterns = (r'(type="hidden".*?(name=".*?")?.*?value=".*?")', r'display:none;">(.*?)</(div|span)>', r'<div\s+class="jdownloader"(.*?)</div>', @@ -99,148 +100,148 @@ class NCryptIn(Crypter): return content - def isOnline(self): - if "Your folder does not exist" in self.cleanedHtml: - self.logDebug("File not m") + def is_online(self): + if "Your folder does not exist" in self.cleaned_html: + self.log_debug("File not m") return False return True - def isProtected(self): - form = re.search(r'<form.*?name.*?protected.*?>(.*?)</form>', self.cleanedHtml, re.S) + def is_protected(self): + form = re.search(r'<form.*?name.*?protected.*?>(.*?)</form>', self.cleaned_html, re.S) if form: content = form.group(1) for keyword in ("password", "captcha"): if keyword in content: self.protection_type = keyword - self.logDebug("Links are %s protected" % self.protection_type) + self.log_debug("Links are %s protected" % self.protection_type) return True return False - def getPackageInfo(self): + def get_package_info(self): m = re.search(self.NAME_PATTERN, self.html) if m: name = folder = m.group('N').strip() - self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder)) + self.log_debug("Found name [%s] and folder [%s] in package info" % (name, folder)) else: name = self.package.name folder = self.package.folder - self.logDebug("Package info not m, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) + self.log_debug("Package info not m, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) return name, folder - def unlockProtection(self): + def unlock_protection(self): postData = {} - form = re.search(r'<form name="protected"(.*?)</form>', self.cleanedHtml, re.S).group(1) + form = re.search(r'<form name="protected"(.*?)</form>', self.cleaned_html, re.S).group(1) - # Submit package password + #: Submit package password if "password" in form: - password = self.getPassword() - self.logDebug("Submitting password [%s] for protected links" % password) + password = self.get_password() + self.log_debug("Submitting password [%s] for protected links" % password) postData['password'] = password - # Resolve anicaptcha + #: Resolve anicaptcha if "anicaptcha" in form: - self.logDebug("Captcha protected") + self.log_debug("Captcha protected") captchaUri = re.search(r'src="(/temp/anicaptcha/.+?)"', form).group(1) - captcha = self.decryptCaptcha("http://ncrypt.in" + captchaUri) - self.logDebug("Captcha resolved [%s]" % captcha) + captcha = self.captcha.decrypt("http://ncrypt.in" + captchaUri) + self.log_debug("Captcha resolved [%s]" % captcha) postData['captcha'] = captcha - # Resolve recaptcha + #: Resolve recaptcha if "recaptcha" in form: - self.logDebug("ReCaptcha protected") + self.log_debug("ReCaptcha protected") captcha_key = re.search(r'\?k=(.*?)"', form).group(1) - self.logDebug("Resolving ReCaptcha with key [%s]" % captcha_key) + self.log_debug("Resolving ReCaptcha with key [%s]" % captcha_key) recaptcha = ReCaptcha(self) response, challenge = recaptcha.challenge(captcha_key) postData['recaptcha_challenge_field'] = challenge postData['recaptcha_response_field'] = response - # Resolve circlecaptcha + #: Resolve circlecaptcha if "circlecaptcha" in form: - self.logDebug("CircleCaptcha protected") + self.log_debug("CircleCaptcha protected") captcha_img_url = "http://ncrypt.in/classes/captcha/circlecaptcha.php" - coords = self.decryptCaptcha(captcha_img_url, forceUser=True, imgtype="png", result_type='positional') - self.logDebug("Captcha resolved, coords [%s]" % str(coords)) + coords = self.captcha.decrypt(captcha_img_url, input_type="png", output_type='positional', ocr="CircleCaptcha") + self.log_debug("Captcha resolved, coords [%s]" % str(coords)) postData['circle.x'] = coords[0] postData['circle.y'] = coords[1] - # Unlock protection + #: Unlock protection postData['submit_protected'] = 'Continue to folder' - return self.load(self.pyfile.url, post=postData, decode=True) + return self.load(self.pyfile.url, post=postData) - def handleErrors(self): + def handle_errors(self): if self.protection_type == "password": - if "This password is invalid!" in self.cleanedHtml: - self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry") + if "This password is invalid!" in self.cleaned_html: + self.log_debug("Incorrect password, please set right password on 'Edit package' form and retry") self.fail(_("Incorrect password, please set right password on 'Edit package' form and retry")) if self.protection_type == "captcha": - if "The securitycheck was wrong!" in self.cleanedHtml: - self.invalidCaptcha() + if "The securitycheck was wrong!" in self.cleaned_html: + self.captcha.invalid() self.retry() else: - self.correctCaptcha() + self.captcha.correct() - def handleLinkSource(self, link_source_type): - # Check for JS engine + def handle_link_source(self, link_source_type): + #: Check for JS engine require_js_engine = link_source_type in ("cnl2", "rsdf", "ccf", "dlc") if require_js_engine and not self.js: - self.logDebug("No JS engine available, skip %s links" % link_source_type) + self.log_debug("No JS engine available, skip %s links" % link_source_type) return [] - # Select suitable handler - if link_source_type == 'single': - return self.handleSingleLink() - if link_source_type == 'cnl2': - return self.handleCNL2() + #: Select suitable handler + if link_source_type == "single": + return self.handle_single_link() + if link_source_type == "cnl2": + return self.handle_CNL2() elif link_source_type in ("rsdf", "ccf", "dlc"): - return self.handleContainer(link_source_type) + return self.handle_container(link_source_type) elif link_source_type == "web": - return self.handleWebLinks() + return self.handle_web_links() else: self.error(_('Unknown source type "%s"') % link_source_type) - def handleSingleLink(self): - self.logDebug("Handling Single link") + def handle_single_link(self): + self.log_debug("Handling Single link") package_links = [] - # Decrypt single link - decrypted_link = self.decryptLink(self.pyfile.url) + #: Decrypt single link + decrypted_link = self.decrypt_link(self.pyfile.url) if decrypted_link: package_links.append(decrypted_link) return package_links - def handleCNL2(self): - self.logDebug("Handling CNL2 links") + def handle_CNL2(self): + self.log_debug("Handling CNL2 links") package_links = [] - if 'cnl2_output' in self.cleanedHtml: + if 'cnl2_output' in self.cleaned_html: try: - (vcrypted, vjk) = self._getCipherParams() + (vcrypted, vjk) = self._get_cipher_params() for (crypted, jk) in zip(vcrypted, vjk): - package_links.extend(self._getLinks(crypted, jk)) + package_links.extend(self._get_links(crypted, jk)) except Exception: self.fail(_("Unable to decrypt CNL2 links")) return package_links - def handleContainers(self): - self.logDebug("Handling Container links") + def handle_containers(self): + self.log_debug("Handling Container links") package_links = [] pattern = r'/container/(rsdf|dlc|ccf)/(\w+)' containersLinks = re.findall(pattern, self.html) - self.logDebug("Decrypting %d Container links" % len(containersLinks)) + self.log_debug("Decrypting %d Container links" % len(containersLinks)) for containerLink in containersLinks: link = "http://ncrypt.in/container/%s/%s.%s" % (containerLink[0], containerLink[1], containerLink[0]) package_links.append(link) @@ -248,15 +249,15 @@ class NCryptIn(Crypter): return package_links - def handleWebLinks(self): - self.logDebug("Handling Web links") + def handle_web_links(self): + self.log_debug("Handling Web links") pattern = r'(http://ncrypt\.in/link-.*?=)' links = re.findall(pattern, self.html) package_links = [] - self.logDebug("Decrypting %d Web links" % len(links)) + self.log_debug("Decrypting %d Web links" % len(links)) for i, link in enumerate(links): - self.logDebug("Decrypting Web link %d, %s" % (i + 1, link)) + self.log_debug("Decrypting Web link %d, %s" % (i + 1, link)) decrypted_link = self.decrypt(link) if decrypted_link: package_links.append(decrypted_link) @@ -264,47 +265,47 @@ class NCryptIn(Crypter): return package_links - def decryptLink(self, link): + def decrypt_link(self, link): try: url = link.replace("link-", "frame-") link = self.load(url, just_header=True)['location'] return link except Exception, detail: - self.logDebug("Error decrypting link %s, %s" % (link, detail)) + self.log_debug("Error decrypting link %s, %s" % (link, detail)) - def _getCipherParams(self): + def _get_cipher_params(self): pattern = r'<input.*?name="%s".*?value="(.*?)"' - # Get jk + #: Get jk jk_re = pattern % NCryptIn.JK_KEY vjk = re.findall(jk_re, self.html) - # Get crypted + #: Get crypted crypted_re = pattern % NCryptIn.CRYPTED_KEY vcrypted = re.findall(crypted_re, self.html) - # Log and return - self.logDebug("Detected %d crypted blocks" % len(vcrypted)) + #: Log and return + self.log_debug("Detected %d crypted blocks" % len(vcrypted)) return vcrypted, vjk - def _getLinks(self, crypted, jk): - # Get key + def _get_links(self, crypted, jk): + #: Get key jreturn = self.js.eval("%s f()" % jk) - self.logDebug("JsEngine returns value [%s]" % jreturn) + self.log_debug("JsEngine returns value [%s]" % jreturn) key = binascii.unhexlify(jreturn) - # Decrypt + #: Decrypt Key = key IV = key obj = AES.new(Key, AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) - # Extract links + #: Extract links text = text.replace("\x00", "").replace("\r", "") links = filter(bool, text.split('\n')) - # Log and return - self.logDebug("Block has %d links" % len(links)) + #: Log and return + self.log_debug("Block has %d links" % len(links)) return links diff --git a/module/plugins/crypter/NetfolderIn.py b/module/plugins/crypter/NetfolderIn.py index 32d59af03..5b992bf58 100644 --- a/module/plugins/crypter/NetfolderIn.py +++ b/module/plugins/crypter/NetfolderIn.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class NetfolderIn(DeadCrypter): __name__ = "NetfolderIn" __type__ = "crypter" - __version__ = "0.73" + __version__ = "0.74" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?netfolder\.(in|me)/(folder\.php\?folder_id=)?(?P<ID>\w+)(?(1)|/\w+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/NitroflareComFolder.py b/module/plugins/crypter/NitroflareComFolder.py new file mode 100644 index 000000000..0f0443355 --- /dev/null +++ b/module/plugins/crypter/NitroflareComFolder.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +from module.common.json_layer import json_loads +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class NitroflareComFolder(SimpleCrypter): + __name__ = "NitroflareComFolder" + __type__ = "crypter" + __version__ = "0.03" + __status__ = "testing" + + __pattern__ = r'https?://(?:www\.)?nitroflare\.com/folder/(?P<USER>\d+)/(?P<ID>[\w=]+)' + __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), + ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] + + __description__ = """Nitroflare.com folder decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + def get_links(self): + res = json_loads(self.load("http://nitroflare.com/ajax/folder.php", + post={'userId' : self.info['pattern']['USER'], + 'folder' : self.info['pattern']['ID'], + 'page' : 1, + 'perPage': 10000})) + if res['name']: + self.pyfile.name = res['name'] + else: + self.offline() + + return [link['url'] for link in res['files']] if 'files' in res else None + + +getInfo = create_getInfo(NitroflareComFolder) diff --git a/module/plugins/crypter/NosvideoCom.py b/module/plugins/crypter/NosvideoCom.py index 9808837c4..4513440d6 100644 --- a/module/plugins/crypter/NosvideoCom.py +++ b/module/plugins/crypter/NosvideoCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class NosvideoCom(SimpleCrypter): __name__ = "NosvideoCom" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?nosvideo\.com/\?v=\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), diff --git a/module/plugins/crypter/OneKhDe.py b/module/plugins/crypter/OneKhDe.py index 4dcb416f5..341359c5a 100644 --- a/module/plugins/crypter/OneKhDe.py +++ b/module/plugins/crypter/OneKhDe.py @@ -2,15 +2,15 @@ import re -from module.unescape import unescape - -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter +from module.utils import html_unescape class OneKhDe(Crypter): __name__ = "OneKhDe" __type__ = "crypter" - __version__ = "0.11" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?1kh\.de/f/' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -27,7 +27,8 @@ class OneKhDe(Crypter): def file_exists(self): - """ returns True or False + """ + Returns True or False """ return True @@ -37,6 +38,6 @@ class OneKhDe(Crypter): self.html = self.load(url) link_ids = re.findall(r"<a id=\"DownloadLink_(\d*)\" href=\"http://1kh.de/", self.html) for id in link_ids: - new_link = unescape( + new_link = html_unescape( re.search("width=\"100%\" src=\"(.*)\"></iframe>", self.load("http://1kh.de/l/" + id)).group(1)) self.urls.append(new_link) diff --git a/module/plugins/crypter/OronComFolder.py b/module/plugins/crypter/OronComFolder.py index 048af7d82..563c984fc 100644 --- a/module/plugins/crypter/OronComFolder.py +++ b/module/plugins/crypter/OronComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class OronComFolder(DeadCrypter): __name__ = "OronComFolder" __type__ = "crypter" - __version__ = "0.11" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?oron\.com/folder/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/PastebinCom.py b/module/plugins/crypter/PastebinCom.py index 751b47cc9..c8a7473f1 100644 --- a/module/plugins/crypter/PastebinCom.py +++ b/module/plugins/crypter/PastebinCom.py @@ -6,9 +6,10 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class PastebinCom(SimpleCrypter): __name__ = "PastebinCom" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" - __pattern__ = r'http://(?:www\.)?pastebin\.com/\w+' + __pattern__ = r'https://(?:www\.)?pastebin\.com/(.+i=)?(?P<ID>\w{8})' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), ("use_subfolder" , "bool", "Save package to subfolder" , True), ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] @@ -18,8 +19,10 @@ class PastebinCom(SimpleCrypter): __authors__ = [("stickell", "l.stickell@yahoo.it")] - LINK_PATTERN = r'<div class="de\d+">(https?://[^ <]+)(?:[^<]*)</div>' - NAME_PATTERN = r'<div class="paste_box_line1" title="(?P<N>.+?)">' + URL_REPLACEMENTS = [(__pattern__ + '.*', r'http://www.pastebin.com/\g<ID>')] + + NAME_PATTERN = r'<div class="paste_box_line1" title="(?P<N>.+?)"' + LINK_PATTERN = r'<div class="de\d+">(.+?)<' getInfo = create_getInfo(PastebinCom) diff --git a/module/plugins/crypter/PastedCo.py b/module/plugins/crypter/PastedCo.py new file mode 100644 index 000000000..0804f56d4 --- /dev/null +++ b/module/plugins/crypter/PastedCo.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.Crypter import Crypter + +import re + + +class PastedCo(Crypter): + __name__ = "PastedCo" + __type__ = "crypter" + __version__ = "0.02" + __status__ = "testing" + + __pattern__ = r'http://pasted\.co/\w+' + + __description__ = """Pasted.co decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Frederik Möllers", "fred-public@posteo.de")] + + + NAME_PATTERN = r'<title>(?P<N>.+?) - .+</title>' + NAME_PATTERN = r"'save_paste' href=\"(http://pasted.co/[0-9a-f]+)/info" + + FS_URL_PREFIX = '<pre id=\'thepaste\' class="prettyprint">' + FS_URL_SUFFIX = '</pre>' + + def decrypt(self, pyfile): + package = pyfile.package() + package_name = package.name + package_folder = package.folder + html = self.load(pyfile.url, decode = True).splitlines() + fs_url = None + FS_URL_RE = re.compile('%s/fullscreen\.php\?hash=[0-9a-f]*' % pyfile.url) + for line in html: + match = FS_URL_RE.search(line) + if match: + fs_url = match.group() + break + if not fs_url: + raise Exception("Could not find pasted.co fullscreen URL!") + urls = self.load(fs_url, decode = True) + urls = urls[urls.find(PastedCo.FS_URL_PREFIX) + len(PastedCo.FS_URL_PREFIX):] + urls = urls[:urls.find(PastedCo.FS_URL_SUFFIX)].splitlines() + self.packages.append((package_name, urls, package_folder)) diff --git a/module/plugins/crypter/QuickshareCzFolder.py b/module/plugins/crypter/QuickshareCzFolder.py index 3e38d36b4..10b6073e4 100644 --- a/module/plugins/crypter/QuickshareCzFolder.py +++ b/module/plugins/crypter/QuickshareCzFolder.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class QuickshareCzFolder(Crypter): __name__ = "QuickshareCzFolder" __type__ = "crypter" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?quickshare\.cz/slozka-\d+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/RSLayerCom.py b/module/plugins/crypter/RSLayerCom.py index 6f078e9e4..c8637279b 100644 --- a/module/plugins/crypter/RSLayerCom.py +++ b/module/plugins/crypter/RSLayerCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class RSLayerCom(DeadCrypter): __name__ = "RSLayerCom" __type__ = "crypter" - __version__ = "0.21" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?rs-layer\.com/directory-' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/RelinkUs.py b/module/plugins/crypter/RelinkUs.py index ed3da1f9b..b3c13db5d 100644 --- a/module/plugins/crypter/RelinkUs.py +++ b/module/plugins/crypter/RelinkUs.py @@ -7,14 +7,15 @@ import re import os from Crypto.Cipher import AES -from module.plugins.Crypter import Crypter -from module.utils import save_join +from module.plugins.internal.Crypter import Crypter +from module.utils import save_join as fs_join class RelinkUs(Crypter): __name__ = "RelinkUs" __type__ = "crypter" - __version__ = "3.12" + __version__ = "3.14" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?relink\.us/(f/|((view|go)\.php\?id=))(?P<ID>.+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -62,164 +63,164 @@ class RelinkUs(Crypter): def decrypt(self, pyfile): - # Init - self.initPackage(pyfile) + #: Init + self.init_package(pyfile) - # Request package - self.requestPackage() + #: Request package + self.request_package() - # Check for online - if not self.isOnline(): + #: Check for online + if not self.is_online(): self.offline() - # Check for protection - if self.isPasswordProtected(): - self.unlockPasswordProtection() - self.handleErrors() + #: Check for protection + if self.is_password_protected(): + self.unlock_password_protection() + self.handle_errors() - if self.isCaptchaProtected(): + if self.is_captcha_protected(): self.captcha = True - self.unlockCaptchaProtection() - self.handleErrors() + self.unlock_captcha_protection() + self.handle_errors() - # Get package name and folder - (package_name, folder_name) = self.getPackageInfo() + #: Get package name and folder + (package_name, folder_name) = self.get_package_info() - # Extract package links + #: Extract package links package_links = [] for sources in self.PREFERRED_LINK_SOURCES: - package_links.extend(self.handleLinkSource(sources)) - if package_links: # use only first source which provides links + package_links.extend(self.handle_link_source(sources)) + if package_links: #: Use only first source which provides links break package_links = set(package_links) - # Pack + #: Pack if package_links: self.packages = [(package_name, package_links, folder_name)] - def initPackage(self, pyfile): + def init_package(self, pyfile): self.fileid = re.match(self.__pattern__, pyfile.url).group('ID') self.package = pyfile.package() - def requestPackage(self): - self.html = self.load(self.pyfile.url, decode=True) + def request_package(self): + self.html = self.load(self.pyfile.url) - def isOnline(self): + def is_online(self): if self.OFFLINE_TOKEN in self.html: - self.logDebug("File not found") + self.log_debug("File not found") return False return True - def isPasswordProtected(self): + def is_password_protected(self): if self.PASSWORD_TOKEN in self.html: - self.logDebug("Links are password protected") + self.log_debug("Links are password protected") return True - def isCaptchaProtected(self): + def is_captcha_protected(self): if self.CAPTCHA_TOKEN in self.html: - self.logDebug("Links are captcha protected") + self.log_debug("Links are captcha protected") return True return False - def unlockPasswordProtection(self): - password = self.getPassword() + def unlock_password_protection(self): + password = self.get_password() - self.logDebug("Submitting password [%s] for protected links" % password) + self.log_debug("Submitting password [%s] for protected links" % password) if password: passwd_url = self.PASSWORD_SUBMIT_URL + "?id=%s" % self.fileid passwd_data = {'id': self.fileid, 'password': password, 'pw': 'submit'} - self.html = self.load(passwd_url, post=passwd_data, decode=True) + self.html = self.load(passwd_url, post=passwd_data) - def unlockCaptchaProtection(self): - self.logDebug("Request user positional captcha resolving") + def unlock_captcha_protection(self): + self.log_debug("Request user positional captcha resolving") captcha_img_url = self.CAPTCHA_IMG_URL + "?id=%s" % self.fileid - coords = self.decryptCaptcha(captcha_img_url, forceUser=True, imgtype="png", result_type='positional') - self.logDebug("Captcha resolved, coords [%s]" % str(coords)) + coords = self.captcha.decrypt(captcha_img_url, input_type="png", output_type='positional', ocr="CircleCaptcha") + self.log_debug("Captcha resolved, coords [%s]" % str(coords)) captcha_post_url = self.CAPTCHA_SUBMIT_URL + "?id=%s" % self.fileid captcha_post_data = {'button.x': coords[0], 'button.y': coords[1], 'captcha': 'submit'} - self.html = self.load(captcha_post_url, post=captcha_post_data, decode=True) + self.html = self.load(captcha_post_url, post=captcha_post_data) - def getPackageInfo(self): + def get_package_info(self): name = folder = None - # Try to get info from web + #: Try to get info from web m = re.search(self.FILE_TITLE_REGEX, self.html) if m: title = m.group(1).strip() if not self.FILE_NOTITLE in title: name = folder = title - self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder)) + self.log_debug("Found name [%s] and folder [%s] in package info" % (name, folder)) - # Fallback to defaults + #: Fallback to defaults if not name or not folder: name = self.package.name folder = self.package.folder - self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) + self.log_debug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) - # Return package info + #: Return package info return name, folder - def handleErrors(self): + def handle_errors(self): if self.PASSWORD_ERROR_ROKEN in self.html: msg = "Incorrect password, please set right password on 'Edit package' form and retry" - self.logDebug(msg) + self.log_debug(msg) self.fail(_(msg)) if self.captcha: if self.CAPTCHA_ERROR_ROKEN in self.html: - self.invalidCaptcha() + self.captcha.invalid() self.retry() else: - self.correctCaptcha() + self.captcha.correct() - def handleLinkSource(self, source): - if source == 'cnl2': - return self.handleCNL2Links() - elif source == 'dlc': - return self.handleDLCLinks() - elif source == 'web': - return self.handleWEBLinks() + def handle_link_source(self, source): + if source == "cnl2": + return self.handle_CNL2Links() + elif source == "dlc": + return self.handle_DLC_links() + elif source == "web": + return self.handle_WEB_links() else: self.error(_('Unknown source type "%s"') % source) - def handleCNL2Links(self): - self.logDebug("Search for CNL2 links") + def handle_CNL2Links(self): + self.log_debug("Search for CNL2 links") package_links = [] m = re.search(self.CNL2_FORM_REGEX, self.html, re.S) if m: cnl2_form = m.group(1) try: - (vcrypted, vjk) = self._getCipherParams(cnl2_form) + (vcrypted, vjk) = self._get_cipher_params(cnl2_form) for (crypted, jk) in zip(vcrypted, vjk): - package_links.extend(self._getLinks(crypted, jk)) + package_links.extend(self._get_links(crypted, jk)) except Exception: - self.logDebug("Unable to decrypt CNL2 links") + self.log_debug("Unable to decrypt CNL2 links") return package_links - def handleDLCLinks(self): - self.logDebug("Search for DLC links") + def handle_DLC_links(self): + self.log_debug("Search for DLC links") package_links = [] m = re.search(self.DLC_LINK_REGEX, self.html) if m: container_url = self.DLC_DOWNLOAD_URL + "?id=%s&dlc=1" % self.fileid - self.logDebug("Downloading DLC container link [%s]" % container_url) + self.log_debug("Downloading DLC container link [%s]" % container_url) try: dlc = self.load(container_url) dlc_filename = self.fileid + ".dlc" - dlc_filepath = save_join(self.config['general']['download_folder'], dlc_filename) + dlc_filepath = fs_join(self.pyload.config.get("general", "download_folder"), dlc_filename) with open(dlc_filepath, "wb") as f: f.write(dlc) package_links.append(dlc_filepath) @@ -230,64 +231,63 @@ class RelinkUs(Crypter): return package_links - def handleWEBLinks(self): - self.logDebug("Search for WEB links") + def handle_WEB_links(self): + self.log_debug("Search for WEB links") package_links = [] params = re.findall(self.WEB_FORWARD_REGEX, self.html) - self.logDebug("Decrypting %d Web links" % len(params)) + self.log_debug("Decrypting %d Web links" % len(params)) for index, param in enumerate(params): try: url = self.WEB_FORWARD_URL + "?%s" % param - self.logDebug("Decrypting Web link %d, %s" % (index + 1, url)) + self.log_debug("Decrypting Web link %d, %s" % (index + 1, url)) - res = self.load(url, decode=True) + res = self.load(url) link = re.search(self.WEB_LINK_REGEX, res).group(1) package_links.append(link) except Exception, detail: - self.logDebug("Error decrypting Web link %s, %s" % (index, detail)) + self.log_debug("Error decrypting Web link %s, %s" % (index, detail)) - self.setWait(4) - self.wait() + self.wait(4) return package_links - def _getCipherParams(self, cnl2_form): - # Get jk + def _get_cipher_params(self, cnl2_form): + #: Get jk jk_re = self.CNL2_FORMINPUT_REGEX % self.CNL2_JK_KEY vjk = re.findall(jk_re, cnl2_form, re.I) - # Get crypted + #: Get crypted crypted_re = self.CNL2_FORMINPUT_REGEX % RelinkUs.CNL2_CRYPTED_KEY vcrypted = re.findall(crypted_re, cnl2_form, re.I) - # Log and return - self.logDebug("Detected %d crypted blocks" % len(vcrypted)) + #: Log and return + self.log_debug("Detected %d crypted blocks" % len(vcrypted)) return vcrypted, vjk - def _getLinks(self, crypted, jk): - # Get key + def _get_links(self, crypted, jk): + #: Get key jreturn = self.js.eval("%s f()" % jk) - self.logDebug("JsEngine returns value [%s]" % jreturn) + self.log_debug("JsEngine returns value [%s]" % jreturn) key = binascii.unhexlify(jreturn) - # Decrypt + #: Decrypt Key = key IV = key obj = AES.new(Key, AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) - # Extract links + #: Extract links text = text.replace("\x00", "").replace("\r", "") links = filter(bool, text.split('\n')) - # Log and return - self.logDebug("Package has %d links" % len(links)) + #: Log and return + self.log_debug("Package has %d links" % len(links)) return links diff --git a/module/plugins/crypter/SafelinkingNet.py b/module/plugins/crypter/SafelinkingNet.py index 5d822af11..e2b8471ab 100644 --- a/module/plugins/crypter/SafelinkingNet.py +++ b/module/plugins/crypter/SafelinkingNet.py @@ -2,17 +2,18 @@ import re -from BeautifulSoup import BeautifulSoup +import BeautifulSoup from module.common.json_layer import json_loads -from module.plugins.Crypter import Crypter -from module.plugins.internal.SolveMedia import SolveMedia +from module.plugins.internal.Crypter import Crypter +from module.plugins.captcha.SolveMedia import SolveMedia class SafelinkingNet(Crypter): __name__ = "SafelinkingNet" __type__ = "crypter" - __version__ = "0.15" + __version__ = "0.17" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?safelinking\.net/([pd])/\w+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -43,7 +44,7 @@ class SafelinkingNet(Crypter): self.html = self.load(url) if "link-password" in self.html: - postData['link-password'] = self.getPassword() + postData['link-password'] = self.get_password() if "altcaptcha" in self.html: for _i in xrange(5): @@ -66,7 +67,7 @@ class SafelinkingNet(Crypter): break pyfile.package().password = "" - soup = BeautifulSoup(self.html) + soup = BeautifulSoup.BeautifulSoup(self.html) scripts = soup.findAll("script") for s in scripts: if "d_links" in s.text: diff --git a/module/plugins/crypter/SecuredIn.py b/module/plugins/crypter/SecuredIn.py index a2eac4f13..95416585a 100644 --- a/module/plugins/crypter/SecuredIn.py +++ b/module/plugins/crypter/SecuredIn.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class SecuredIn(DeadCrypter): __name__ = "SecuredIn" __type__ = "crypter" - __version__ = "0.21" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?secured\.in/download-[\d]+-\w{8}\.html' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/SexuriaCom.py b/module/plugins/crypter/SexuriaCom.py index 06dcf547e..7942d5e42 100644 --- a/module/plugins/crypter/SexuriaCom.py +++ b/module/plugins/crypter/SexuriaCom.py @@ -2,13 +2,14 @@ import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class SexuriaCom(Crypter): __name__ = "SexuriaCom" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?sexuria\.com/(v1/)?(Pornos_Kostenlos_.+?_(\d+)\.html|dl_links_\d+_\d+\.html|id=\d+\&part=\d+\&link=\d+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -19,76 +20,76 @@ class SexuriaCom(Crypter): __authors__ = [("NETHead", "NETHead.AT.gmx.DOT.net")] - PATTERN_SUPPORTED_MAIN = re.compile(r'http://(www\.)?sexuria\.com/(v1/)?Pornos_Kostenlos_.+?_(\d+)\.html', re.I) - PATTERN_SUPPORTED_CRYPT = re.compile(r'http://(www\.)?sexuria\.com/(v1/)?dl_links_\d+_(?P<ID>\d+)\.html', re.I) - PATTERN_SUPPORTED_REDIRECT = re.compile(r'http://(www\.)?sexuria\.com/out\.php\?id=(?P<ID>\d+)\&part=\d+\&link=\d+', re.I) - PATTERN_TITLE = re.compile(r'<title> - (?P<TITLE>.*) Sexuria - Kostenlose Pornos - Rapidshare XXX Porn</title>', re.I) - PATTERN_PASSWORD = re.compile(r'<strong>Passwort: </strong></div></td>.*?bgcolor="#EFEFEF">(?P<PWD>.*?)</td>', re.I | re.S) - PATTERN_DL_LINK_PAGE = re.compile(r'"(dl_links_\d+_\d+\.html)"', re.I) - PATTERN_REDIRECT_LINKS = re.compile(r'value="(http://sexuria\.com/out\.php\?id=\d+\&part=\d+\&link=\d+)" readonly', re.I) + PATTERN_SUPPORTED_MAIN = r'http://(www\.)?sexuria\.com/(v1/)?Pornos_Kostenlos_.+?_(\d+)\.html' + PATTERN_SUPPORTED_CRYPT = r'http://(www\.)?sexuria\.com/(v1/)?dl_links_\d+_(?P<ID>\d+)\.html' + PATTERN_SUPPORTED_REDIRECT = r'http://(www\.)?sexuria\.com/out\.php\?id=(?P<ID>\d+)\&part=\d+\&link=\d+' + PATTERN_TITLE = r'<title> - (?P<TITLE>.*) Sexuria - Kostenlose Pornos - Rapidshare XXX Porn</title>' + PATTERN_PASSWORD = r'<strong>Passwort: </strong></div></td>.*?bgcolor="#EFEFEF">(?P<PWD>.*?)</td>' + PATTERN_DL_LINK_PAGE = r'"(dl_links_\d+_\d+\.html)"' + PATTERN_REDIRECT_LINKS = r'value="(http://sexuria\.com/out\.php\?id=\d+\&part=\d+\&link=\d+)" readonly' def decrypt(self, pyfile): - # Init + #: Init self.pyfile = pyfile self.package = pyfile.package() - # Get package links - package_name, self.links, folder_name, package_pwd = self.decryptLinks(self.pyfile.url) + #: Get package links + package_name, self.links, folder_name, package_pwd = self.decrypt_links(self.pyfile.url) self.packages = [(package_name, self.links, folder_name)] - def decryptLinks(self, url): + def decrypt_links(self, url): linklist = [] - name = self.package.name - folder = self.package.folder + name = self.package.name + folder = self.package.folder password = None - if re.match(self.PATTERN_SUPPORTED_MAIN, url): - # Processing main page + if re.match(self.PATTERN_SUPPORTED_MAIN, url, re.I): + #: Processing main page html = self.load(url) - links = re.findall(self.PATTERN_DL_LINK_PAGE, html) + links = re.findall(self.PATTERN_DL_LINK_PAGE, html, re.I) for link in links: linklist.append("http://sexuria.com/v1/" + link) - elif re.match(self.PATTERN_SUPPORTED_REDIRECT, url): - # Processing direct redirect link (out.php), redirecting to main page - id = re.search(self.PATTERN_SUPPORTED_REDIRECT, url).group('ID') + elif re.match(self.PATTERN_SUPPORTED_REDIRECT, url, re.I): + #: Processing direct redirect link (out.php), redirecting to main page + id = re.search(self.PATTERN_SUPPORTED_REDIRECT, url, re.I).group('ID') if id: linklist.append("http://sexuria.com/v1/Pornos_Kostenlos_liebe_%s.html" % id) - elif re.match(self.PATTERN_SUPPORTED_CRYPT, url): - # Extract info from main file - id = re.search(self.PATTERN_SUPPORTED_CRYPT, url).group('ID') - html = self.load("http://sexuria.com/v1/Pornos_Kostenlos_info_%s.html" % id, decode=True) + elif re.match(self.PATTERN_SUPPORTED_CRYPT, url, re.I): + #: Extract info from main file + id = re.search(self.PATTERN_SUPPORTED_CRYPT, url, re.I).group('ID') + html = self.load("http://sexuria.com/v1/Pornos_Kostenlos_info_%s.html" % id) - title = re.search(self.PATTERN_TITLE, html).group('TITLE').strip() + title = re.search(self.PATTERN_TITLE, html, re.I).group('TITLE').strip() if title: name = folder = title - self.logDebug("Package info found, name [%s] and folder [%s]" % (name, folder)) + self.log_debug("Package info found, name [%s] and folder [%s]" % (name, folder)) - pwd = re.search(self.PATTERN_PASSWORD, html).group('PWD') - if pwd: + pwd = re.search(self.PATTERN_PASSWORD, html, re.I | re.S).group('PWD') + if pwd and pwd not in ("Kein Passwort", "-"): password = pwd.strip() - self.logDebug("Password info [%s] found" % password) + self.log_debug("Password info [%s] found" % password) - # Process link (dl_link) + #: Process link (dl_link) html = self.load(url) - links = re.findall(self.PATTERN_REDIRECT_LINKS, html) + links = re.findall(self.PATTERN_REDIRECT_LINKS, html, re.I) if len(links) == 0: - self.LogError("Broken for link %s" % link) + self.log_error(_("Broken for link: %s") % link) else: for link in links: link = link.replace("http://sexuria.com/", "http://www.sexuria.com/") finallink = self.load(link, just_header=True)['location'] if not finallink or "sexuria.com/" in finallink: - self.LogError("Broken for link %s" % link) + self.log_error(_("Broken for link: %s") % link) else: linklist.append(finallink) - # Debug log - self.logDebug("%d supported links" % len(linklist)) + #: Debug log + self.log_debug("%d supported links" % len(linklist)) for i, link in enumerate(linklist): - self.logDebug("Supported link %d, %s" % (i + 1, link)) + self.log_debug("Supported link %d, %s" % (i + 1, link)) return name, linklist, folder, password diff --git a/module/plugins/crypter/ShSt.py b/module/plugins/crypter/ShSt.py new file mode 100644 index 000000000..754bc542c --- /dev/null +++ b/module/plugins/crypter/ShSt.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.Crypter import Crypter + +import pycurl +import re + + +class ShSt(Crypter): + __name__ = "ShSt" + __type__ = "crypter" + __version__ = "0.04" + __status__ = "testing" + + __pattern__ = r'http://sh\.st/\w+' + + __description__ = """Sh.St decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Frederik Möllers", "fred-public@posteo.de")] + + + NAME_PATTERN = r'<title>(?P<N>.+?) - .+</title>' + + + def decrypt(self, pyfile): + #: If we use curl as a user agent, we will get a straight redirect (no waiting!) + self.req.http.c.setopt(pycurl.USERAGENT, "curl/7.42.1") + #: Fetch the target URL + header = self.load(self.pyfile.url, just_header = True, decode = False) + target_url = header['location'] + self.urls.append(target_url) diff --git a/module/plugins/crypter/ShareLinksBiz.py b/module/plugins/crypter/ShareLinksBiz.py index f17ba54d7..6fbe59b38 100644 --- a/module/plugins/crypter/ShareLinksBiz.py +++ b/module/plugins/crypter/ShareLinksBiz.py @@ -4,13 +4,14 @@ import binascii import re from Crypto.Cipher import AES -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class ShareLinksBiz(Crypter): __name__ = "ShareLinksBiz" __type__ = "crypter" - __version__ = "1.14" + __version__ = "1.16" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(share-links|s2l)\.biz/(?P<ID>_?\w+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -22,113 +23,113 @@ class ShareLinksBiz(Crypter): def setup(self): - self.baseUrl = None - self.fileId = None + self.base_url = None + self.file_id = None self.package = None self.captcha = False def decrypt(self, pyfile): - # Init - self.initFile(pyfile) + #: Init + self.init_file(pyfile) - # Request package - url = self.baseUrl + '/' + self.fileId - self.html = self.load(url, decode=True) + #: Request package + url = self.base_url + '/' + self.file_id + self.html = self.load(url) - # Unblock server (load all images) - self.unblockServer() + #: Unblock server (load all images) + self.unblock_server() - # Check for protection - if self.isPasswordProtected(): - self.unlockPasswordProtection() - self.handleErrors() + #: Check for protection + if self.is_password_protected(): + self.unlock_password_protection() + self.handle_errors() - if self.isCaptchaProtected(): + if self.is_captcha_protected(): self.captcha = True - self.unlockCaptchaProtection() - self.handleErrors() + self.unlock_captcha_protection() + self.handle_errors() - # Extract package links + #: Extract package links package_links = [] - package_links.extend(self.handleWebLinks()) - package_links.extend(self.handleContainers()) - package_links.extend(self.handleCNL2()) + package_links.extend(self.handle_web_links()) + package_links.extend(self.handle_containers()) + package_links.extend(self.handle_CNL2()) package_links = set(package_links) - # Get package info - package_name, package_folder = self.getPackageInfo() + #: Get package info + package_name, package_folder = self.get_package_info() - # Pack + #: Pack self.packages = [(package_name, package_links, package_folder)] - def initFile(self, pyfile): + def init_file(self, pyfile): url = pyfile.url if 's2l.biz' in url: url = self.load(url, just_header=True)['location'] - self.baseUrl = "http://www.%s.biz" % re.match(self.__pattern__, url).group(1) - self.fileId = re.match(self.__pattern__, url).group('ID') + self.base_url = "http://www.%s.biz" % re.match(self.__pattern__, url).group(1) + self.file_id = re.match(self.__pattern__, url).group('ID') self.package = pyfile.package() - def isOnline(self): + def is_online(self): if "No usable content was found" in self.html: - self.logDebug("File not found") + self.log_debug("File not found") return False return True - def isPasswordProtected(self): - if re.search(r'''<form.*?id="passwordForm".*?>''', self.html): - self.logDebug("Links are protected") + def is_password_protected(self): + if re.search(r'<form.*?id="passwordForm".*?>', self.html): + self.log_debug("Links are protected") return True return False - def isCaptchaProtected(self): + def is_captcha_protected(self): if '<map id="captchamap"' in self.html: - self.logDebug("Links are captcha protected") + self.log_debug("Links are captcha protected") return True return False - def unblockServer(self): + def unblock_server(self): imgs = re.findall(r"(/template/images/.*?\.gif)", self.html) for img in imgs: - self.load(self.baseUrl + img) + self.load(self.base_url + img) - def unlockPasswordProtection(self): - password = self.getPassword() - self.logDebug("Submitting password [%s] for protected links" % password) - post = {"password": password, 'login': 'Submit form'} - url = self.baseUrl + '/' + self.fileId - self.html = self.load(url, post=post, decode=True) + def unlock_password_protection(self): + password = self.get_password() + self.log_debug("Submitting password [%s] for protected links" % password) + post = {'password': password, 'login': 'Submit form'} + url = self.base_url + '/' + self.file_id + self.html = self.load(url, post=post) - def unlockCaptchaProtection(self): - # Get captcha map - captchaMap = self._getCaptchaMap() - self.logDebug("Captcha map with [%d] positions" % len(captchaMap.keys())) + def unlock_captcha_protection(self): + #: Get captcha map + captchaMap = self._get_captcha_map() + self.log_debug("Captcha map with [%d] positions" % len(captchaMap.keys())) - # Request user for captcha coords + #: Request user for captcha coords m = re.search(r'<img src="/captcha.gif\?d=(.*?)&PHPSESSID=(.*?)&legend=1"', self.html) - captchaUrl = self.baseUrl + '/captcha.gif?d=%s&PHPSESSID=%s' % (m.group(1), m.group(2)) - self.logDebug("Waiting user for correct position") - coords = self.decryptCaptcha(captchaUrl, forceUser=True, imgtype="gif", result_type='positional') - self.logDebug("Captcha resolved, coords [%s]" % str(coords)) + captchaUrl = self.base_url + '/captcha.gif?d=%s&PHPSESSID=%s' % (m.group(1), m.group(2)) + self.log_debug("Waiting user for correct position") + coords = self.captcha.decrypt(captchaUrl, input_type="gif", output_type='positional') + self.log_debug("Captcha resolved, coords [%s]" % str(coords)) - # Resolve captcha - href = self._resolveCoords(coords, captchaMap) + #: Resolve captcha + href = self._resolve_coords(coords, captchaMap) if href is None: - self.invalidCaptcha() + self.captcha.invalid() self.retry(wait_time=5) - url = self.baseUrl + href - self.html = self.load(url, decode=True) + url = self.base_url + href + self.html = self.load(url) - def _getCaptchaMap(self): + def _get_captcha_map(self): mapp = {} for m in re.finditer(r'<area shape="rect" coords="(.*?)" href="(.*?)"', self.html): rect = eval('(' + m.group(1) + ')') @@ -137,66 +138,66 @@ class ShareLinksBiz(Crypter): return mapp - def _resolveCoords(self, coords, captchaMap): + def _resolve_coords(self, coords, captchaMap): x, y = coords - for rect, href in captchaMap.iteritems(): + for rect, href in captchaMap.items(): x1, y1, x2, y2 = rect if (x >= x1 and x <= x2) and (y >= y1 and y <= y2): return href - def handleErrors(self): + def handle_errors(self): if "The inserted password was wrong" in self.html: - self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry") + self.log_debug("Incorrect password, please set right password on 'Edit package' form and retry") self.fail(_("Incorrect password, please set right password on 'Edit package' form and retry")) if self.captcha: if "Your choice was wrong" in self.html: - self.invalidCaptcha() + self.captcha.invalid() self.retry(wait_time=5) else: - self.correctCaptcha() + self.captcha.correct() - def getPackageInfo(self): + def get_package_info(self): name = folder = None - # Extract from web package header + #: Extract from web package header title_re = r'<h2><img.*?/>(.*)</h2>' m = re.search(title_re, self.html, re.S) if m: title = m.group(1).strip() if 'unnamed' not in title: name = folder = title - self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder)) + self.log_debug("Found name [%s] and folder [%s] in package info" % (name, folder)) - # Fallback to defaults + #: Fallback to defaults if not name or not folder: name = self.package.name folder = self.package.folder - self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) + self.log_debug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) - # Return package info + #: Return package info return name, folder - def handleWebLinks(self): + def handle_web_links(self): package_links = [] - self.logDebug("Handling Web links") + self.log_debug("Handling Web links") #@TODO: Gather paginated web links pattern = r'javascript:_get\(\'(.*?)\', \d+, \'\'\)' ids = re.findall(pattern, self.html) - self.logDebug("Decrypting %d Web links" % len(ids)) + self.log_debug("Decrypting %d Web links" % len(ids)) for i, ID in enumerate(ids): try: - self.logDebug("Decrypting Web link %d, [%s]" % (i + 1, ID)) + self.log_debug("Decrypting Web link %d, [%s]" % (i + 1, ID)) - dwLink = self.baseUrl + "/get/lnk/" + ID + dwLink = self.base_url + "/get/lnk/" + ID res = self.load(dwLink) code = re.search(r'frm/(\d+)', res).group(1) - fwLink = self.baseUrl + "/get/frm/" + code + fwLink = self.base_url + "/get/frm/" + code res = self.load(fwLink) jscode = re.search(r'<script language="javascript">\s*eval\((.*)\)\s*</script>', res, re.S).group(1) @@ -205,75 +206,75 @@ class ShareLinksBiz(Crypter): dlLink = self.js.eval(jslauncher % jscode) - self.logDebug("JsEngine returns value [%s] for redirection link" % dlLink) + self.log_debug("JsEngine returns value [%s] for redirection link" % dlLink) package_links.append(dlLink) except Exception, detail: - self.logDebug("Error decrypting Web link [%s], %s" % (ID, detail)) + self.log_debug("Error decrypting Web link [%s], %s" % (ID, detail)) return package_links - def handleContainers(self): + def handle_containers(self): package_links = [] - self.logDebug("Handling Container links") + self.log_debug("Handling Container links") pattern = r'javascript:_get\(\'(.*?)\', 0, \'(rsdf|ccf|dlc)\'\)' containersLinks = re.findall(pattern, self.html) - self.logDebug("Decrypting %d Container links" % len(containersLinks)) + self.log_debug("Decrypting %d Container links" % len(containersLinks)) for containerLink in containersLinks: - link = "%s/get/%s/%s" % (self.baseUrl, containerLink[1], containerLink[0]) + link = "%s/get/%s/%s" % (self.base_url, containerLink[1], containerLink[0]) package_links.append(link) return package_links - def handleCNL2(self): + def handle_CNL2(self): package_links = [] - self.logDebug("Handling CNL2 links") + self.log_debug("Handling CNL2 links") if '/lib/cnl2/ClicknLoad.swf' in self.html: try: - (crypted, jk) = self._getCipherParams() - package_links.extend(self._getLinks(crypted, jk)) + (crypted, jk) = self._get_cipher_params() + package_links.extend(self._get_links(crypted, jk)) except Exception: self.fail(_("Unable to decrypt CNL2 links")) return package_links - def _getCipherParams(self): - # Request CNL2 + def _get_cipher_params(self): + #: Request CNL2 code = re.search(r'ClicknLoad.swf\?code=(.*?)"', self.html).group(1) - url = "%s/get/cnl2/%s" % (self.baseUrl, code) + url = "%s/get/cnl2/%s" % (self.base_url, code) res = self.load(url) params = res.split(";;") - # Get jk + #: Get jk strlist = list(params[1].decode('base64')) - jk = ''.join(strlist[::-1]) + jk = "".join(strlist[::-1]) - # Get crypted + #: Get crypted strlist = list(params[2].decode('base64')) - crypted = ''.join(strlist[::-1]) + crypted = "".join(strlist[::-1]) - # Log and return + #: Log and return return crypted, jk - def _getLinks(self, crypted, jk): - # Get key + def _get_links(self, crypted, jk): + #: Get key jreturn = self.js.eval("%s f()" % jk) - self.logDebug("JsEngine returns value [%s]" % jreturn) + self.log_debug("JsEngine returns value [%s]" % jreturn) key = binascii.unhexlify(jreturn) - # Decrypt + #: Decrypt Key = key IV = key obj = AES.new(Key, AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) - # Extract links + #: Extract links text = text.replace("\x00", "").replace("\r", "") links = filter(bool, text.split('\n')) - # Log and return - self.logDebug("Block has %d links" % len(links)) + #: Log and return + self.log_debug("Block has %d links" % len(links)) return links diff --git a/module/plugins/crypter/SharingmatrixComFolder.py b/module/plugins/crypter/SharingmatrixComFolder.py index eb1b4d8a6..bd35cfd8e 100644 --- a/module/plugins/crypter/SharingmatrixComFolder.py +++ b/module/plugins/crypter/SharingmatrixComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class SharingmatrixComFolder(DeadCrypter): __name__ = "SharingmatrixComFolder" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?sharingmatrix\.com/folder/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/SpeedLoadOrgFolder.py b/module/plugins/crypter/SpeedLoadOrgFolder.py index af768ef7b..736d59720 100644 --- a/module/plugins/crypter/SpeedLoadOrgFolder.py +++ b/module/plugins/crypter/SpeedLoadOrgFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class SpeedLoadOrgFolder(DeadCrypter): __name__ = "SpeedLoadOrgFolder" __type__ = "crypter" - __version__ = "0.30" + __version__ = "0.31" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?speedload\.org/(\d+~f$|folder/\d+/)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/StealthTo.py b/module/plugins/crypter/StealthTo.py index 551468980..3a175cd87 100644 --- a/module/plugins/crypter/StealthTo.py +++ b/module/plugins/crypter/StealthTo.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class StealthTo(DeadCrypter): __name__ = "StealthTo" __type__ = "crypter" - __version__ = "0.20" + __version__ = "0.21" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?stealth\.to/folder/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/TNTVillageScambioeticoOrg.py b/module/plugins/crypter/TNTVillageScambioeticoOrg.py new file mode 100644 index 000000000..6ba1ee19b --- /dev/null +++ b/module/plugins/crypter/TNTVillageScambioeticoOrg.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + + +class TNTVillageScambioeticoOrg(SimpleCrypter): + __name__ = "TNTVillageScambioeticoOrg" + __type__ = "crypter" + __version__ = "0.02" + __status__ = "testing" + + __pattern__ = r'http://(?:www\.)?forum\.tntvillage\.scambioetico\.org/index\.php\?.*showtopic=\d+' + __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides pyload.config['general']['folder_per_package'] + ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] + + __description__ = """TNTVillage.scambioetico.org decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + LINK_PATTERNS = [r'<th class="titlemedium"><a href=\'(.+?)\'', r"<a href='(\./index\.php\?act.+?)'"] + + + def get_links(self): + for p in self.LINK_PATTERNS: + self.LINK_PATTERN = p + links = super(TNTVillageScambioeticoOrg, self).getLinks() + if links: + return links + + +getInfo = create_getInfo(TNTVillageScambioeticoOrg) diff --git a/module/plugins/crypter/TinyurlCom.py b/module/plugins/crypter/TinyurlCom.py index 4b5b35457..bff1efa12 100644 --- a/module/plugins/crypter/TinyurlCom.py +++ b/module/plugins/crypter/TinyurlCom.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleDereferer import SimpleDereferer, create_getInfo +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo -class TinyurlCom(SimpleDereferer): +class TinyurlCom(SimpleCrypter): __name__ = "TinyurlCom" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(preview\.)?tinyurl\.com/[\w-]+' diff --git a/module/plugins/crypter/TnyCz.py b/module/plugins/crypter/TnyCz.py index 719c26449..f3fb19cb3 100644 --- a/module/plugins/crypter/TnyCz.py +++ b/module/plugins/crypter/TnyCz.py @@ -1,14 +1,15 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo - import re +from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo + class TnyCz(SimpleCrypter): __name__ = "TnyCz" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?tny\.cz/\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -20,12 +21,12 @@ class TnyCz(SimpleCrypter): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - NAME_PATTERN = r'<title>(?P<N>.+) - .+</title>' + NAME_PATTERN = r'<title>(?P<N>.+?) - .+</title>' - def getLinks(self): + def get_links(self): m = re.search(r'<a id=\'save_paste\' href="(.+save\.php\?hash=.+)">', self.html) - return re.findall(".+", self.load(m.group(1), decode=True)) if m else None + return re.findall(".+", self.load(m.group(1))) if m else None getInfo = create_getInfo(TnyCz) diff --git a/module/plugins/crypter/TrailerzoneInfo.py b/module/plugins/crypter/TrailerzoneInfo.py index 6f1c90612..03ab004a3 100644 --- a/module/plugins/crypter/TrailerzoneInfo.py +++ b/module/plugins/crypter/TrailerzoneInfo.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class TrailerzoneInfo(DeadCrypter): __name__ = "TrailerzoneInfo" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?trailerzone\.info/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/TurbobitNetFolder.py b/module/plugins/crypter/TurbobitNetFolder.py index dcbd6a5d7..3a36f5032 100644 --- a/module/plugins/crypter/TurbobitNetFolder.py +++ b/module/plugins/crypter/TurbobitNetFolder.py @@ -9,7 +9,8 @@ from module.common.json_layer import json_loads class TurbobitNetFolder(SimpleCrypter): __name__ = "TurbobitNetFolder" __type__ = "crypter" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?turbobit\.net/download/folder/(?P<ID>\w+)' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -25,24 +26,22 @@ class TurbobitNetFolder(SimpleCrypter): NAME_PATTERN = r'src=\'/js/lib/grid/icon/folder.png\'> <span>(?P<N>.+?)</span>' - def _getLinks(self, id, page=1): + def _get_links(self, id, page=1): gridFile = self.load("http://turbobit.net/downloadfolder/gridFile", - get={"rootId": id, "rows": 200, "page": page}, decode=True) + get={'rootId': id, 'rows': 200, 'page': page}) grid = json_loads(gridFile) if grid['rows']: for i in grid['rows']: yield i['id'] - for id in self._getLinks(id, page + 1): + for id in self._get_links(id, page + 1): yield id else: return - def getLinks(self): - id = re.match(self.__pattern__, self.pyfile.url).group('ID') - fixurl = lambda id: "http://turbobit.net/%s.html" % id - return map(fixurl, self._getLinks(id)) + def get_links(self): + return ["http://turbobit.net/%s.html" % id for id in self._get_links(self.info['pattern']['ID'])] getInfo = create_getInfo(TurbobitNetFolder) diff --git a/module/plugins/crypter/TusfilesNetFolder.py b/module/plugins/crypter/TusfilesNetFolder.py index 1cc505b81..684fb1e46 100644 --- a/module/plugins/crypter/TusfilesNetFolder.py +++ b/module/plugins/crypter/TusfilesNetFolder.py @@ -10,7 +10,8 @@ from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo class TusfilesNetFolder(XFSCrypter): __name__ = "TusfilesNetFolder" __type__ = "crypter" - __version__ = "0.08" + __version__ = "0.09" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?tusfiles\.net/go/(?P<ID>\w+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -27,11 +28,11 @@ class TusfilesNetFolder(XFSCrypter): URL_REPLACEMENTS = [(__pattern__ + ".*", r'https://www.tusfiles.net/go/\g<ID>/')] - def loadPage(self, page_n): - return self.load(urlparse.urljoin(self.pyfile.url, str(page_n)), decode=True) + def load_page(self, page_n): + return self.load(urlparse.urljoin(self.pyfile.url, str(page_n))) - def handlePages(self, pyfile): + def handle_pages(self, pyfile): pages = re.search(self.PAGES_PATTERN, self.html) if pages: pages = int(math.ceil(int(pages.group('pages')) / 25.0)) @@ -39,8 +40,8 @@ class TusfilesNetFolder(XFSCrypter): return for p in xrange(2, pages + 1): - self.html = self.loadPage(p) - self.links += self.getLinks() + self.html = self.load_page(p) + self.links += self.get_links() getInfo = create_getInfo(TusfilesNetFolder) diff --git a/module/plugins/crypter/UlozToFolder.py b/module/plugins/crypter/UlozToFolder.py index 3f2a60cf7..19569ef31 100644 --- a/module/plugins/crypter/UlozToFolder.py +++ b/module/plugins/crypter/UlozToFolder.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- import re -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class UlozToFolder(Crypter): __name__ = "UlozToFolder" __type__ = "crypter" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj\.cz|zachowajto\.pl)/(m|soubory)/.+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), @@ -28,7 +29,7 @@ class UlozToFolder(Crypter): new_links = [] for i in xrange(1, 100): - self.logInfo(_("Fetching links from page %i") % i) + self.log_info(_("Fetching links from page %i") % i) m = re.search(self.FOLDER_PATTERN, html, re.S) if m is None: self.error(_("FOLDER_PATTERN not found")) @@ -40,7 +41,7 @@ class UlozToFolder(Crypter): else: break else: - self.logInfo(_("Limit of 99 pages reached, aborting")) + self.log_info(_("Limit of 99 pages reached, aborting")) if new_links: self.urls = [map(lambda s: "http://ulozto.net/%s" % s, new_links)] diff --git a/module/plugins/crypter/UploadableChFolder.py b/module/plugins/crypter/UploadableChFolder.py index f1eb93323..767e989d5 100644 --- a/module/plugins/crypter/UploadableChFolder.py +++ b/module/plugins/crypter/UploadableChFolder.py @@ -6,14 +6,15 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class UploadableChFolder(SimpleCrypter): __name__ = "UploadableChFolder" __type__ = "crypter" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?uploadable\.ch/list/\w+' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), ("use_subfolder" , "bool", "Save package to subfolder" , True), ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] - __description__ = """ Uploadable.ch folder decrypter plugin """ + __description__ = """Uploadable.ch folder decrypter plugin""" __license__ = "GPLv3" __authors__ = [("guidobelix", "guidobelix@hotmail.it"), ("Walter Purcaro", "vuolter@gmail.com")] diff --git a/module/plugins/crypter/UploadedToFolder.py b/module/plugins/crypter/UploadedToFolder.py index d54ed47eb..381d744fe 100644 --- a/module/plugins/crypter/UploadedToFolder.py +++ b/module/plugins/crypter/UploadedToFolder.py @@ -9,11 +9,11 @@ from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class UploadedToFolder(SimpleCrypter): __name__ = "UploadedToFolder" __type__ = "crypter" - __version__ = "0.42" + __version__ = "0.44" + __status__ = "testing" - __pattern__ = r'http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/(?P<ID>\w+)' - __config__ = [("use_premium" , "bool", "Use premium account if available" , True), - ("use_subfolder" , "bool", "Save package to subfolder" , True), + __pattern__ = r'https?://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/\w+' + __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] __description__ = """UploadedTo decrypter plugin""" @@ -21,17 +21,11 @@ class UploadedToFolder(SimpleCrypter): __authors__ = [("stickell", "l.stickell@yahoo.it")] - PLAIN_PATTERN = r'<small class="date"><a href="([\w/]+)" onclick=' - NAME_PATTERN = r'<title>(?P<N>.+?)<' + NAME_PATTERN = r'<title>(?P<N>.+?)<' + OFFLINE_PATTERN = r'>Page not found' + TEMP_OFFLINE_PATTERN = r'<title>uploaded\.net - Maintenance' - - def getLinks(self): - m = re.search(self.PLAIN_PATTERN, self.html) - if m is None: - self.error(_("PLAIN_PATTERN not found")) - - plain_link = urlparse.urljoin("http://uploaded.net/", m.group(1)) - return self.load(plain_link).split('\n')[:-1] + LINK_PATTERN = r'<h2><a href="(.+?)"' getInfo = create_getInfo(UploadedToFolder) diff --git a/module/plugins/crypter/WiiReloadedOrg.py b/module/plugins/crypter/WiiReloadedOrg.py index eddc0e5d1..7679836d2 100644 --- a/module/plugins/crypter/WiiReloadedOrg.py +++ b/module/plugins/crypter/WiiReloadedOrg.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class WiiReloadedOrg(DeadCrypter): __name__ = "WiiReloadedOrg" __type__ = "crypter" - __version__ = "0.11" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?wii-reloaded\.org/protect/get\.php\?i=.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/WuploadComFolder.py b/module/plugins/crypter/WuploadComFolder.py index dece467a2..da1fa9bac 100644 --- a/module/plugins/crypter/WuploadComFolder.py +++ b/module/plugins/crypter/WuploadComFolder.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadCrypter import DeadCrypter, create_getInfo class WuploadComFolder(DeadCrypter): __name__ = "WuploadComFolder" __type__ = "crypter" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?wupload\.com/folder/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/crypter/XFileSharingProFolder.py b/module/plugins/crypter/XFileSharingProFolder.py index 2e1a2f022..584cc7668 100644 --- a/module/plugins/crypter/XFileSharingProFolder.py +++ b/module/plugins/crypter/XFileSharingProFolder.py @@ -8,7 +8,8 @@ from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo class XFileSharingProFolder(XFSCrypter): __name__ = "XFileSharingProFolder" __type__ = "crypter" - __version__ = "0.06" + __version__ = "0.13" + __status__ = "testing" __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), @@ -19,34 +20,56 @@ class XFileSharingProFolder(XFSCrypter): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - def _log(self, type, args): - msg = " | ".join(str(a).strip() for a in args if a) - logger = getattr(self.log, type) - logger("%s: %s: %s" % (self.__name__, self.HOSTER_NAME, msg or _("%s MARK" % type.upper()))) + def _log(self, level, plugintype, pluginname, messages): + return super(XFileSharingProFolder, self)._log(level, + plugintype, + "%s: %s" % (pluginname, self.HOSTER_NAME), + messages) def init(self): super(XFileSharingProFolder, self).init() - self.__pattern__ = self.core.pluginManager.crypterPlugins[self.__name__]['pattern'] + self.__pattern__ = self.pyload.pluginManager.crypterPlugins[self.__name__]['pattern'] 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 != '.') + self.HOSTER_NAME = "".join(part.capitalize() for part in re.split(r'(\.|\d+|\-)', self.HOSTER_DOMAIN) if part != '.') - account = self.core.accountManager.getAccountPlugin(self.HOSTER_NAME) - if account and account.canUse(): - self.account = account - - elif self.account: - self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN + def _setup(self): + account_name = self.__name__ if self.account.HOSTER_DOMAIN is None else self.HOSTER_NAME + self.chunk_limit = 1 + self.multiDL = True + if self.account: + self.req = self.pyload.requestFactory.getRequest(accountname, self.user) + self.premium = self.account.is_premium(self.user) + self.resume_download = self.premium else: - return + self.req = self.pyload.requestFactory.getRequest(account_name) + self.premium = False + self.resume_download = False + + + def load_account(self): + if self.req: + self.req.close() + + if not self.account: + self.account = self.pyload.accountManager.getAccountPlugin(self.HOSTER_NAME) + + if not self.account: + self.account = self.pyload.accountManager.getAccountPlugin(self.__name__) + + if self.account: + if not self.account.HOSTER_DOMAIN: + self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN + + if not self.user: + self.user = self.account.select()[0] - self.user, data = self.account.selectAccount() - self.req = self.account.getAccountRequest(self.user) - self.premium = self.account.isPremium(self.user) + if not self.user or not self.account.is_logged(self.user, True): + self.account = False getInfo = create_getInfo(XFileSharingProFolder) diff --git a/module/plugins/crypter/XupPl.py b/module/plugins/crypter/XupPl.py index 5ab6750c4..ac918a6de 100644 --- a/module/plugins/crypter/XupPl.py +++ b/module/plugins/crypter/XupPl.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- -from module.plugins.Crypter import Crypter +from module.plugins.internal.Crypter import Crypter class XupPl(Crypter): __name__ = "XupPl" __type__ = "crypter" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'https?://(?:[^/]*\.)?xup\.pl/.+' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), diff --git a/module/plugins/crypter/YoutubeComFolder.py b/module/plugins/crypter/YoutubeComFolder.py index a2b02b2f1..ea09c63f9 100644 --- a/module/plugins/crypter/YoutubeComFolder.py +++ b/module/plugins/crypter/YoutubeComFolder.py @@ -4,14 +4,15 @@ import re import urlparse from module.common.json_layer import json_loads -from module.plugins.Crypter import Crypter -from module.utils import save_join +from module.plugins.internal.Crypter import Crypter +from module.utils import save_join as fs_join class YoutubeComFolder(Crypter): __name__ = "YoutubeComFolder" __type__ = "crypter" - __version__ = "1.01" + __version__ = "1.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.|m\.)?youtube\.com/(?P<TYPE>user|playlist|view_play_list)(/|.*?[?&](?:list|p)=)(?P<ID>[\w-]+)' __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True ), @@ -29,36 +30,36 @@ class YoutubeComFolder(Crypter): def api_response(self, ref, req): - req.update({"key": self.API_KEY}) + req.update({'key': self.API_KEY}) url = urlparse.urljoin("https://www.googleapis.com/youtube/v3/", ref) html = self.load(url, get=req) return json_loads(html) - def getChannel(self, user): - channels = self.api_response("channels", {"part": "id,snippet,contentDetails", "forUsername": user, "maxResults": "50"}) + def get_channel(self, user): + channels = self.api_response("channels", {'part': "id,snippet,contentDetails", 'forUsername': user, 'maxResults': "50"}) if channels['items']: channel = channels['items'][0] - return {"id": channel['id'], - "title": channel['snippet']['title'], - "relatedPlaylists": channel['contentDetails']['relatedPlaylists'], - "user": user} # One lone channel for user? + return {'id': channel['id'], + 'title': channel['snippet']['title'], + 'relatedPlaylists': channel['contentDetails']['relatedPlaylists'], + 'user': user} #: One lone channel for user? - def getPlaylist(self, p_id): - playlists = self.api_response("playlists", {"part": "snippet", "id": p_id}) + def get_playlist(self, p_id): + playlists = self.api_response("playlists", {'part': "snippet", 'id': p_id}) if playlists['items']: playlist = playlists['items'][0] - return {"id": p_id, - "title": playlist['snippet']['title'], - "channelId": playlist['snippet']['channelId'], - "channelTitle": playlist['snippet']['channelTitle']} + return {'id': p_id, + 'title': playlist['snippet']['title'], + 'channelId': playlist['snippet']['channelId'], + 'channelTitle': playlist['snippet']['channelTitle']} - def _getPlaylists(self, id, token=None): - req = {"part": "id", "maxResults": "50", "channelId": id} + def _get_playlists(self, id, token=None): + req = {'part': "id", 'maxResults': "50", 'channelId': id} if token: - req.update({"pageToken": token}) + req.update({'pageToken': token}) playlists = self.api_response("playlists", req) @@ -66,18 +67,18 @@ class YoutubeComFolder(Crypter): yield playlist['id'] if "nextPageToken" in playlists: - for item in self._getPlaylists(id, playlists['nextPageToken']): + for item in self._get_playlists(id, playlists['nextPageToken']): yield item - def getPlaylists(self, ch_id): - return map(self.getPlaylist, self._getPlaylists(ch_id)) + def get_playlists(self, ch_id): + return map(self.get_playlist, self._get_playlists(ch_id)) - def _getVideosId(self, id, token=None): - req = {"part": "contentDetails", "maxResults": "50", "playlistId": id} + def _get_videos_id(self, id, token=None): + req = {'part': "contentDetails", 'maxResults': "50", 'playlistId': id} if token: - req.update({"pageToken": token}) + req.update({'pageToken': token}) playlist = self.api_response("playlistItems", req) @@ -85,12 +86,12 @@ class YoutubeComFolder(Crypter): yield item['contentDetails']['videoId'] if "nextPageToken" in playlist: - for item in self._getVideosId(id, playlist['nextPageToken']): + for item in self._get_videos_id(id, playlist['nextPageToken']): yield item - def getVideosId(self, p_id): - return list(self._getVideosId(p_id)) + def get_videos_id(self, p_id): + return list(self._get_videos_id(p_id)) def decrypt(self, pyfile): @@ -99,29 +100,29 @@ class YoutubeComFolder(Crypter): m_type = m.group('TYPE') if m_type == "user": - self.logDebug("Url recognized as Channel") + self.log_debug("Url recognized as Channel") user = m_id - channel = self.getChannel(user) + channel = self.get_channel(user) if channel: - playlists = self.getPlaylists(channel['id']) - self.logDebug("%s playlist\s found on channel \"%s\"" % (len(playlists), channel['title'])) + playlists = self.get_playlists(channel['id']) + self.log_debug("%s playlist\s found on channel \"%s\"" % (len(playlists), channel['title'])) - relatedplaylist = {p_name: self.getPlaylist(p_id) for p_name, p_id in channel['relatedPlaylists'].iteritems()} - self.logDebug("Channel's related playlists found = %s" % relatedplaylist.keys()) + relatedplaylist = {p_name: self.get_playlist(p_id) for p_name, p_id in channel['relatedPlaylists'].items()} + self.log_debug("Channel's related playlists found = %s" % relatedplaylist.keys()) relatedplaylist['uploads']['title'] = "Unplaylisted videos" relatedplaylist['uploads']['checkDups'] = True #: checkDups flag - for p_name, p_data in relatedplaylist.iteritems(): - if self.getConfig(p_name): + for p_name, p_data in relatedplaylist.items(): + if self.get_config(p_name): p_data['title'] += " of " + user playlists.append(p_data) else: playlists = [] else: - self.logDebug("Url recognized as Playlist") - playlists = [self.getPlaylist(m_id)] + self.log_debug("Url recognized as Playlist") + playlists = [self.get_playlist(m_id)] if not playlists: self.fail(_("No playlist available")) @@ -130,18 +131,18 @@ class YoutubeComFolder(Crypter): urlize = lambda x: "https://www.youtube.com/watch?v=" + x for p in playlists: p_name = p['title'] - p_videos = self.getVideosId(p['id']) - p_folder = save_join(self.config['general']['download_folder'], p['channelTitle'], p_name) - self.logDebug("%s video\s found on playlist \"%s\"" % (len(p_videos), p_name)) + p_videos = self.get_videos_id(p['id']) + p_folder = fs_join(self.pyload.config.get("general", "download_folder"), p['channelTitle'], p_name) + self.log_debug("%s video\s found on playlist \"%s\"" % (len(p_videos), p_name)) if not p_videos: continue elif "checkDups" in p: p_urls = [urlize(v_id) for v_id in p_videos if v_id not in addedvideos] - self.logDebug("%s video\s available on playlist \"%s\" after duplicates cleanup" % (len(p_urls), p_name)) + self.log_debug("%s video\s available on playlist \"%s\" after duplicates cleanup" % (len(p_urls), p_name)) else: p_urls = map(urlize, p_videos) - self.packages.append((p_name, p_urls, p_folder)) #: folder is NOT recognized by pyload 0.4.9! + self.packages.append((p_name, p_urls, p_folder)) #: Folder is NOT recognized by pyload 0.4.9! addedvideos.extend(p_videos) diff --git a/module/plugins/hooks/AlldebridComHook.py b/module/plugins/hooks/AlldebridComHook.py index 092921134..402850d87 100644 --- a/module/plugins/hooks/AlldebridComHook.py +++ b/module/plugins/hooks/AlldebridComHook.py @@ -6,22 +6,20 @@ from module.plugins.internal.MultiHook import MultiHook class AlldebridComHook(MultiHook): __name__ = "AlldebridComHook" __type__ = "hook" - __version__ = "0.16" + __version__ = "0.17" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 ), - ("ssl" , "bool" , "Use HTTPS" , True )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Alldebrid.com hook plugin""" __license__ = "GPLv3" __authors__ = [("Andy Voigt", "spamsales@online.de")] - def getHosters(self): - https = "https" if self.getConfig('ssl') else "http" - html = self.getURL(https + "://www.alldebrid.com/api.php", get={'action': "get_host"}).replace("\"", "").strip() - + def get_hosters(self): + html = self.load("https://www.alldebrid.com/api.php", + get={'action': "get_host"}).replace("\"", "").strip() return [x.strip() for x in html.split(",") if x.strip()] diff --git a/module/plugins/hooks/AndroidPhoneNotify.py b/module/plugins/hooks/AndroidPhoneNotify.py index a8a1cff72..f79f226e4 100644 --- a/module/plugins/hooks/AndroidPhoneNotify.py +++ b/module/plugins/hooks/AndroidPhoneNotify.py @@ -2,14 +2,14 @@ import time -from module.network.RequestFactory import getURL -from module.plugins.Hook import Hook, Expose +from module.plugins.internal.Addon import Addon, Expose -class AndroidPhoneNotify(Hook): +class AndroidPhoneNotify(Addon): __name__ = "AndroidPhoneNotify" __type__ = "hook" - __version__ = "0.08" + __version__ = "0.10" + __status__ = "testing" __config__ = [("apikey" , "str" , "API key" , "" ), ("notifycaptcha" , "bool", "Notify captcha request" , True ), @@ -27,56 +27,52 @@ class AndroidPhoneNotify(Hook): ("Walter Purcaro", "vuolter@gmail.com" )] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - self.event_list = ["allDownloadsProcessed", "plugin_updated"] + def init(self): + self.event_list = ["plugin_updated"] + self.event_map = {'allDownloadsProcessed': "all_downloads_processed"} self.last_notify = 0 self.notifications = 0 def plugin_updated(self, type_plugins): - if not self.getConfig('notifyupdate'): + if not self.get_config('notifyupdate'): return self.notify(_("Plugins updated"), str(type_plugins)) - def coreReady(self): - self.key = self.getConfig('apikey') + def activate(self): + self.key = self.get_config('apikey') - def coreExiting(self): - if not self.getConfig('notifyexit'): + def exit(self): + if not self.get_config('notifyexit'): return - if self.core.do_restart: + if self.pyload.do_restart: self.notify(_("Restarting pyLoad")) else: self.notify(_("Exiting pyLoad")) - def newCaptchaTask(self, task): - if not self.getConfig('notifycaptcha'): + def captcha_task(self, task): + if not self.get_config('notifycaptcha'): return self.notify(_("Captcha"), _("New request waiting user input")) - def packageFinished(self, pypack): - if self.getConfig('notifypackage'): + def package_finished(self, pypack): + if self.get_config('notifypackage'): self.notify(_("Package finished"), pypack.name) - def allDownloadsProcessed(self): - if not self.getConfig('notifyprocessed'): + def all_downloads_processed(self): + if not self.get_config('notifyprocessed'): return - if any(True for pdata in self.core.api.getQueue() if pdata.linksdone < pdata.linkstotal): + if any(True for pdata in self.pyload.api.getQueue() if pdata.linksdone < pdata.linkstotal): self.notify(_("Package failed"), _("One or more packages was not completed successfully")) else: self.notify(_("All packages finished")) @@ -92,21 +88,21 @@ class AndroidPhoneNotify(Hook): if not key: return - if self.core.isClientConnected() and not self.getConfig('ignoreclient'): + if self.pyload.isClientConnected() and not self.get_config('ignoreclient'): return elapsed_time = time.time() - self.last_notify - if elapsed_time < self.getConf("sendtimewait"): + if elapsed_time < self.get_config("sendtimewait"): return if elapsed_time > 60: self.notifications = 0 - elif self.notifications >= self.getConf("sendpermin"): + elif self.notifications >= self.get_config("sendpermin"): return - getURL("http://www.notifymyandroid.com/publicapi/notify", + self.load("http://www.notifymyandroid.com/publicapi/notify", get={'apikey' : key, 'application': "pyLoad", 'event' : event, diff --git a/module/plugins/hooks/AntiStandby.py b/module/plugins/hooks/AntiStandby.py new file mode 100644 index 000000000..48b86fa55 --- /dev/null +++ b/module/plugins/hooks/AntiStandby.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement + +import os +import time +import subprocess +import sys + +try: + import caffeine +except ImportError: + pass + +from module.plugins.internal.Addon import Addon, Expose +from module.utils import fs_encode, save_join as fs_join + + +class Kernel32(object): + ES_AWAYMODE_REQUIRED = 0x00000040 + ES_CONTINUOUS = 0x80000000 + ES_DISPLAY_REQUIRED = 0x00000002 + ES_SYSTEM_REQUIRED = 0x00000001 + ES_USER_PRESENT = 0x00000004 + + +class AntiStandby(Addon): + __name__ = "AntiStandby" + __type__ = "hook" + __version__ = "0.11" + __status__ = "testing" + + __config__ = [("activated", "bool", "Activated" , True ), + ("hdd" , "bool", "Prevent HDD standby" , True ), + ("system" , "bool", "Prevent OS standby" , True ), + ("display" , "bool", "Prevent display standby" , False), + ("interval" , "int" , "HDD touching interval in seconds", 25 )] + + __description__ = """Prevent OS, HDD and display standby""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + TMP_FILE = ".antistandby" + MIN_INTERVAL = 5 + + + def init(self): + self.pid = None + self.mtime = 0 + + + def activate(self): + hdd = self.get_config('hdd') + system = not self.get_config('system') + display = not self.get_config('display') + + if hdd: + self.interval = max(self.get_config('interval'), self.MIN_INTERVAL) + self.init_periodical(threaded=True) + + if os.name == "nt": + self.win_standby(system, display) + + elif sys.platform == "darwin": + self.osx_standby(system, display) + + else: + self.linux_standby(system, display) + + + def deactivate(self): + try: + os.remove(self.TMP_FILE) + + except OSError: + pass + + if os.name == "nt": + self.win_standby(True) + + elif sys.platform == "darwin": + self.osx_standby(True) + + else: + self.linux_standby(True) + + + @Expose + def win_standby(self, system=True, display=True): + import ctypes + + set = ctypes.windll.kernel32.SetThreadExecutionState + + if system: + if display: + set(Kernel32.ES_CONTINUOUS) + else: + set(Kernel32.ES_CONTINUOUS | Kernel32.ES_DISPLAY_REQUIRED) + else: + if display: + set(Kernel32.ES_CONTINUOUS | Kernel32.ES_SYSTEM_REQUIRED) + else: + set(Kernel32.ES_CONTINUOUS | Kernel32.ES_SYSTEM_REQUIRED | Kernel32.ES_DISPLAY_REQUIRED) + + + @Expose + def osx_standby(self, system=True, display=True): + try: + if system: + caffeine.off() + else: + caffeine.on(display) + + except NameError: + self.log_warning(_("Unable to change power state"), + _("caffeine lib not found")) + + except Exception, e: + self.log_warning(_("Unable to change power state"), e) + + + @Expose + def linux_standby(self, system=True, display=True): + try: + if system: + if self.pid: + self.pid.kill() + + elif not self.pid: + self.pid = subprocess.Popen(["caffeine"]) + + except Exception, e: + self.log_warning(_("Unable to change system power state"), e) + + try: + if display: + subprocess.call(["xset", "+dpms", "s", "default"]) + else: + subprocess.call(["xset", "-dpms", "s", "off"]) + + except Exception, e: + self.log_warning(_("Unable to change display power state"), e) + + + @Expose + def touch(self, path): + with open(path, 'w'): + os.utime(path, None) + + self.mtime = time.time() + + + @Expose + def max_mtime(self, path): + return max(0, 0, + *(os.path.getmtime(fs_join(root, file)) + for root, dirs, files in os.walk(fs_encode(path), topdown=False) + for file in files)) + + + def periodical(self): + if self.get_config('hdd') is False: + return + + if (self.pyload.threadManager.pause or + not self.pyload.api.isTimeDownload() or + not self.pyload.threadManager.getActiveFiles()): + return + + download_folder = self.pyload.config.get("general", "download_folder") + if (self.max_mtime(download_folder) - self.mtime) < self.interval: + return + + self.touch(self.TMP_FILE) diff --git a/module/plugins/hooks/AntiVirus.py b/module/plugins/hooks/AntiVirus.py index c620f556d..b58d0b61d 100644 --- a/module/plugins/hooks/AntiVirus.py +++ b/module/plugins/hooks/AntiVirus.py @@ -9,14 +9,15 @@ try: except ImportError: pass -from module.plugins.Hook import Hook, Expose, threaded -from module.utils import fs_encode, save_join +from module.plugins.internal.Addon import Addon, Expose, threaded +from module.utils import fs_encode, save_join as fs_join -class AntiVirus(Hook): +class AntiVirus(Addon): __name__ = "AntiVirus" __type__ = "hook" - __version__ = "0.09" + __version__ = "0.12" + __status__ = "testing" #@TODO: add trash option (use Send2Trash lib) __config__ = [("action" , "Antivirus default;Delete;Quarantine", "Manage infected files" , "Antivirus default"), @@ -32,20 +33,13 @@ class AntiVirus(Hook): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - @Expose @threaded def scan(self, pyfile, thread): - file = fs_encode(pyfile.plugin.lastDownload) - filename = os.path.basename(pyfile.plugin.lastDownload) - cmdfile = fs_encode(self.getConfig('cmdfile')) - cmdargs = fs_encode(self.getConfig('cmdargs').strip()) + file = fs_encode(pyfile.plugin.last_download) + filename = os.path.basename(pyfile.plugin.last_download) + cmdfile = fs_encode(self.get_config('cmdfile')) + cmdargs = fs_encode(self.get_config('cmdargs').strip()) if not os.path.isfile(file) or not os.path.isfile(cmdfile): return @@ -60,20 +54,20 @@ class AntiVirus(Hook): out, err = map(str.strip, p.communicate()) if out: - self.logInfo(filename, out) + self.log_info(filename, out) if err: - self.logWarning(filename, err) - if not self.getConfig('ignore-err'): - self.logDebug("Delete/Quarantine task is aborted") + self.log_warning(filename, err) + if not self.get_config('ignore-err'): + self.log_debug("Delete/Quarantine task is aborted") return if p.returncode: - pyfile.error = _("infected file") - action = self.getConfig('action') + pyfile.error = _("Infected file") + action = self.get_config('action') try: if action == "Delete": - if not self.getConfig('deltotrash'): + if not self.get_config('deltotrash'): os.remove(file) else: @@ -81,39 +75,38 @@ class AntiVirus(Hook): send2trash.send2trash(file) except NameError: - self.logWarning(_("Send2Trash lib not found, moving to quarantine instead")) + self.log_warning(_("Send2Trash lib not found, moving to quarantine instead")) pyfile.setCustomStatus(_("file moving")) - shutil.move(file, self.getConfig('quardir')) + shutil.move(file, self.get_config('quardir')) except Exception, e: - self.logWarning(_("Unable to move file to trash: %s, moving to quarantine instead") % e.message) + self.log_warning(_("Unable to move file to trash: %s, moving to quarantine instead") % e.message) pyfile.setCustomStatus(_("file moving")) - shutil.move(file, self.getConfig('quardir')) + shutil.move(file, self.get_config('quardir')) else: - self.logDebug(_("Successfully moved file to trash")) + self.log_debug("Successfully moved file to trash") elif action == "Quarantine": pyfile.setCustomStatus(_("file moving")) - shutil.move(file, self.getConfig('quardir')) + shutil.move(file, self.get_config('quardir')) except (IOError, shutil.Error), e: - self.logError(filename, action + " action failed!", e) + self.log_error(filename, action + " action failed!", e) elif not out and not err: - self.logDebug(filename, "No infected file found") + self.log_debug(filename, "No infected file found") finally: pyfile.setProgress(100) thread.finishFile(pyfile) - def downloadFinished(self, pyfile): + def download_finished(self, pyfile): return self.scan(pyfile) - def downloadFailed(self, pyfile): - #: Check if pyfile is still "failed", - # maybe might has been restarted in meantime - if pyfile.status == 8 and self.getConfig('scanfailed'): + def download_failed(self, pyfile): + #: Check if pyfile is still "failed", maybe might has been restarted in meantime + if pyfile.status == 8 and self.get_config('scanfailed'): return self.scan(pyfile) diff --git a/module/plugins/hooks/BypassCaptcha.py b/module/plugins/hooks/BypassCaptcha.py index 9e01edfa2..4b155a67e 100644 --- a/module/plugins/hooks/BypassCaptcha.py +++ b/module/plugins/hooks/BypassCaptcha.py @@ -3,8 +3,8 @@ import pycurl from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getURL, getRequest -from module.plugins.Hook import Hook, threaded +from module.network.RequestFactory import getRequest as get_request +from module.plugins.internal.Hook import Hook, threaded class BypassCaptchaException(Exception): @@ -13,7 +13,7 @@ class BypassCaptchaException(Exception): self.err = err - def getCode(self): + def get_code(self): return self.err @@ -28,10 +28,11 @@ class BypassCaptchaException(Exception): class BypassCaptcha(Hook): __name__ = "BypassCaptcha" __type__ = "hook" - __version__ = "0.06" + __version__ = "0.08" + __status__ = "testing" - __config__ = [("force", "bool", "Force BC even if client is connected", False), - ("passkey", "password", "Passkey", "")] + __config__ = [("passkey" , "password", "Access key" , "" ), + ("check_client", "bool" , "Don't use if client is connected", True)] __description__ = """Send captchas to BypassCaptcha.com""" __license__ = "GPLv3" @@ -40,8 +41,6 @@ class BypassCaptcha(Hook): ("zoidberg" , "zoidberg@mujmail.cz" )] - interval = 0 #@TODO: Remove in 0.4.10 - PYLOAD_KEY = "4f771155b640970d5607f919a615bdefc67e7d32" SUBMIT_URL = "http://bypasscaptcha.com/upload.php" @@ -49,30 +48,26 @@ class BypassCaptcha(Hook): GETCREDITS_URL = "http://bypasscaptcha.com/ex_left.php" - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def getCredits(self): - res = getURL(self.GETCREDITS_URL, post={"key": self.getConfig('passkey')}) + def get_credits(self): + res = self.load(self.GETCREDITS_URL, post={'key': self.get_config('passkey')}) data = dict(x.split(' ', 1) for x in res.splitlines()) return int(data['Left']) def submit(self, captcha, captchaType="file", match=None): - req = getRequest() + req = get_request() - #raise timeout threshold + #: Raise timeout threshold req.c.setopt(pycurl.LOW_SPEED_TIME, 80) try: - res = req.load(self.SUBMIT_URL, - post={'vendor_key': self.PYLOAD_KEY, - 'key': self.getConfig('passkey'), - 'gen_task_id': "1", - 'file': (pycurl.FORM_FILE, captcha)}, - multipart=True) + res = self.load(self.SUBMIT_URL, + post={'vendor_key': self.PYLOAD_KEY, + 'key': self.get_config('passkey'), + 'gen_task_id': "1", + 'file': (pycurl.FORM_FILE, captcha)}, + req=req) finally: req.close() @@ -82,59 +77,59 @@ class BypassCaptcha(Hook): result = data['Value'] ticket = data['TaskId'] - self.logDebug("Result %s : %s" % (ticket, result)) + self.log_debug("Result %s : %s" % (ticket, result)) return ticket, result def respond(self, ticket, success): try: - res = getURL(self.RESPOND_URL, post={"task_id": ticket, "key": self.getConfig('passkey'), - "cv": 1 if success else 0}) + res = self.load(self.RESPOND_URL, post={'task_id': ticket, 'key': self.get_config('passkey'), + 'cv': 1 if success else 0}) except BadHeader, e: - self.logError(_("Could not send response"), e) + self.log_error(_("Could not send response"), e) - def newCaptchaTask(self, task): + def captcha_task(self, task): if "service" in task.data: return False if not task.isTextual(): return False - if not self.getConfig('passkey'): + if not self.get_config('passkey'): return False - if self.core.isClientConnected() and not self.getConfig('force'): + if self.pyload.isClientConnected() and self.get_config('check_client'): return False - if self.getCredits() > 0: + if self.get_credits() > 0: task.handler.append(self) task.data['service'] = self.__name__ task.setWaiting(100) - self._processCaptcha(task) + self._process_captcha(task) else: - self.logInfo(_("Your %s account has not enough credits") % self.__name__) + self.log_info(_("Your %s account has not enough credits") % self.__name__) - def captchaCorrect(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: + def captcha_correct(self, task): + if task.data['service'] is self.__name__ and "ticket" in task.data: self.respond(task.data['ticket'], True) - def captchaInvalid(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: + def captcha_invalid(self, task): + if task.data['service'] is self.__name__ and "ticket" in task.data: self.respond(task.data['ticket'], False) @threaded - def _processCaptcha(self, task): + def _process_captcha(self, task): c = task.captchaFile try: ticket, result = self.submit(c) except BypassCaptchaException, e: - task.error = e.getCode() + task.error = e.get_code() return task.data['ticket'] = ticket diff --git a/module/plugins/hooks/Captcha9Kw.py b/module/plugins/hooks/Captcha9Kw.py index 60482b8fc..2e2685978 100644 --- a/module/plugins/hooks/Captcha9Kw.py +++ b/module/plugins/hooks/Captcha9Kw.py @@ -8,18 +8,16 @@ import time from base64 import b64encode from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getURL - -from module.plugins.Hook import Hook, threaded +from module.plugins.internal.Hook import Hook, threaded class Captcha9Kw(Hook): __name__ = "Captcha9Kw" __type__ = "hook" - __version__ = "0.28" + __version__ = "0.30" + __status__ = "testing" - __config__ = [("ssl" , "bool" , "Use HTTPS" , True ), - ("force" , "bool" , "Force captcha resolving even if client is connected" , True ), + __config__ = [("check_client" , "bool" , "Don't use if client is connected" , True ), ("confirm" , "bool" , "Confirm Captcha (cost +6 credits)" , False ), ("captchaperhour", "int" , "Captcha per hour" , "9999" ), ("captchapermin" , "int" , "Captcha per minute" , "9999" ), @@ -36,62 +34,54 @@ class Captcha9Kw(Hook): ("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - API_URL = "http://www.9kw.eu/index.cgi" - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - if self.getConfig('ssl'): - self.API_URL = self.API_URL.replace("http://", "https://") + API_URL = "https://www.9kw.eu/index.cgi" - def getCredits(self): - res = getURL(self.API_URL, - get={'apikey': self.getConfig('passkey'), + def get_credits(self): + res = self.load(self.API_URL, + get={'apikey': self.get_config('passkey'), 'pyload': "1", 'source': "pyload", 'action': "usercaptchaguthaben"}) if res.isdigit(): - self.logInfo(_("%s credits left") % res) + self.log_info(_("%s credits left") % res) credits = self.info['credits'] = int(res) return credits else: - self.logError(res) + self.log_error(res) return 0 @threaded - def _processCaptcha(self, task): + def _process_captcha(self, task): try: with open(task.captchaFile, 'rb') as f: data = f.read() except IOError, e: - self.logError(e) + self.log_error(e) return - pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1) + pluginname = re.search(r'_(.+?)_\d+.\w+', task.captchaFile).group(1) option = {'min' : 2, 'max' : 50, 'phrase' : 0, 'numeric' : 0, 'case_sensitive': 0, 'math' : 0, - 'prio' : min(max(self.getConfig('prio'), 0), 10), - 'confirm' : self.getConfig('confirm'), - 'timeout' : min(max(self.getConfig('timeout'), 300), 3999), - 'selfsolve' : self.getConfig('selfsolve'), - 'cph' : self.getConfig('captchaperhour'), - 'cpm' : self.getConfig('captchapermin')} + 'prio' : min(max(self.get_config('prio'), 0), 10), + 'confirm' : self.get_config('confirm'), + 'timeout' : min(max(self.get_config('timeout'), 300), 3999), + 'selfsolve' : self.get_config('selfsolve'), + 'cph' : self.get_config('captchaperhour'), + 'cpm' : self.get_config('captchapermin')} - for opt in str(self.getConfig('hoster_options').split('|')): + for opt in str(self.get_config('hoster_options').split('|')): details = map(str.strip, opt.split(':')) - if not details or details[0].lower() != pluginname.lower(): + if not details or details[0].lower() is not pluginname.lower(): continue for d in details: @@ -106,7 +96,7 @@ class Captcha9Kw(Hook): break - post_data = {'apikey' : self.getConfig('passkey'), + post_data = {'apikey' : self.get_config('passkey'), 'prio' : option['prio'], 'confirm' : option['confirm'], 'maxtimeout' : option['timeout'], @@ -120,32 +110,35 @@ class Captcha9Kw(Hook): 'numeric' : option['numeric'], 'math' : option['math'], 'oldsource' : pluginname, - 'pyload' : "1", + 'pyload' : 1, 'source' : "pyload", - 'base64' : "1", + 'base64' : 1, 'mouse' : 1 if task.isPositional() else 0, 'file-upload-01': b64encode(data), 'action' : "usercaptchaupload"} for _i in xrange(5): try: - res = getURL(self.API_URL, post=post_data) + res = self.load(self.API_URL, post=post_data) + except BadHeader, e: time.sleep(3) + else: if res and res.isdigit(): break + else: - self.logError(_("Bad upload: %s") % res) + self.log_error(_("Bad upload: %s") % res) return - self.logDebug(_("NewCaptchaID ticket: %s") % res, task.captchaFile) + self.log_debug("NewCaptchaID ticket: %s" % res, task.captchaFile) - task.data["ticket"] = res + task.data['ticket'] = res - for _i in xrange(int(self.getConfig('timeout') / 5)): - result = getURL(self.API_URL, - get={'apikey': self.getConfig('passkey'), + for _i in xrange(int(self.get_config('timeout') / 5)): + result = self.load(self.API_URL, + get={'apikey': self.get_config('passkey'), 'id' : res, 'pyload': "1", 'info' : "1", @@ -157,36 +150,36 @@ class Captcha9Kw(Hook): else: break else: - self.logDebug("Could not send request: %s" % res) + self.log_debug("Could not send request: %s" % res) result = None - self.logInfo(_("Captcha result for ticket %s: %s") % (res, result)) + self.log_info(_("Captcha result for ticket %s: %s") % (res, result)) task.setResult(result) - def newCaptchaTask(self, task): + def captcha_task(self, task): if not task.isTextual() and not task.isPositional(): return - if not self.getConfig('passkey'): + if not self.get_config('passkey'): return - if self.core.isClientConnected() and not self.getConfig('force'): + if self.pyload.isClientConnected() and self.get_config('check_client'): return - credits = self.getCredits() + credits = self.get_credits() if not credits: - self.logError(_("Your captcha 9kw.eu account has not enough credits")) + self.log_error(_("Your captcha 9kw.eu account has not enough credits")) return - queue = min(self.getConfig('queue'), 999) - timeout = min(max(self.getConfig('timeout'), 300), 3999) - pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1) + queue = min(self.get_config('queue'), 999) + timeout = min(max(self.get_config('timeout'), 300), 3999) + pluginname = re.search(r'_(.+?)_\d+.\w+', task.captchaFile).group(1) for _i in xrange(5): - servercheck = getURL("http://www.9kw.eu/grafik/servercheck.txt") + servercheck = self.load("http://www.9kw.eu/grafik/servercheck.txt") if queue < re.search(r'queue=(\d+)', servercheck).group(1): break @@ -194,17 +187,17 @@ class Captcha9Kw(Hook): else: self.fail(_("Too many captchas in queue")) - for opt in str(self.getConfig('hoster_options').split('|')): + for opt in str(self.get_config('hoster_options').split('|')): details = map(str.strip, opt.split(':')) - if not details or details[0].lower() != pluginname.lower(): + if not details or details[0].lower() is not pluginname.lower(): continue for d in details: hosteroption = d.split("=") if len(hosteroption) > 1 \ - and hosteroption[0].lower() == 'timeout' \ + and hosteroption[0].lower() == "timeout" \ and hosteroption[1].isdigit(): timeout = int(hosteroption[1]) @@ -214,41 +207,41 @@ class Captcha9Kw(Hook): task.setWaiting(timeout) - self._processCaptcha(task) + self._process_captcha(task) - def _captchaResponse(self, task, correct): + def _captcha_response(self, task, correct): type = "correct" if correct else "refund" if 'ticket' not in task.data: - self.logDebug("No CaptchaID for %s request (task: %s)" % (type, task)) + self.log_debug("No CaptchaID for %s request (task: %s)" % (type, task)) return - passkey = self.getConfig('passkey') + passkey = self.get_config('passkey') for _i in xrange(3): - res = getURL(self.API_URL, + res = self.load(self.API_URL, get={'action' : "usercaptchacorrectback", 'apikey' : passkey, 'api_key': passkey, 'correct': "1" if correct else "2", 'pyload' : "1", 'source' : "pyload", - 'id' : task.data["ticket"]}) + 'id' : task.data['ticket']}) - self.logDebug("Request %s: %s" % (type, res)) + self.log_debug("Request %s: %s" % (type, res)) if res == "OK": break time.sleep(5) else: - self.logDebug("Could not send %s request: %s" % (type, res)) + self.log_debug("Could not send %s request: %s" % (type, res)) - def captchaCorrect(self, task): - self._captchaResponse(task, True) + def captcha_correct(self, task): + self._captcha_response(task, True) - def captchaInvalid(self, task): - self._captchaResponse(task, False) + def captcha_invalid(self, task): + self._captcha_response(task, False) diff --git a/module/plugins/hooks/CaptchaBrotherhood.py b/module/plugins/hooks/CaptchaBrotherhood.py index bda080037..0df1ab8a9 100644 --- a/module/plugins/hooks/CaptchaBrotherhood.py +++ b/module/plugins/hooks/CaptchaBrotherhood.py @@ -9,11 +9,12 @@ import urllib try: from PIL import Image + except ImportError: import Image -from module.network.RequestFactory import getURL, getRequest -from module.plugins.Hook import Hook, threaded +from module.network.RequestFactory import getRequest as get_request +from module.plugins.internal.Hook import Hook, threaded class CaptchaBrotherhoodException(Exception): @@ -22,7 +23,7 @@ class CaptchaBrotherhoodException(Exception): self.err = err - def getCode(self): + def get_code(self): return self.err @@ -37,11 +38,12 @@ class CaptchaBrotherhoodException(Exception): class CaptchaBrotherhood(Hook): __name__ = "CaptchaBrotherhood" __type__ = "hook" - __version__ = "0.08" + __version__ = "0.10" + __status__ = "testing" - __config__ = [("username", "str", "Username", ""), - ("force", "bool", "Force CT even if client is connected", False), - ("passkey", "password", "Password", "")] + __config__ = [("username" , "str" , "Username" , "" ), + ("password" , "password", "Password" , "" ), + ("check_client", "bool" , "Don't use if client is connected", True)] __description__ = """Send captchas to CaptchaBrotherhood.com""" __license__ = "GPLv3" @@ -49,23 +51,17 @@ class CaptchaBrotherhood(Hook): ("zoidberg", "zoidberg@mujmail.cz")] - interval = 0 #@TODO: Remove in 0.4.10 - API_URL = "http://www.captchabrotherhood.com/" - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def getCredits(self): - res = getURL(self.API_URL + "askCredits.aspx", - get={"username": self.getConfig('username'), "password": self.getConfig('passkey')}) + def get_credits(self): + res = self.load(self.API_URL + "askCredits.aspx", + get={'username': self.get_config('username'), 'password': self.get_config('password')}) if not res.startswith("OK"): raise CaptchaBrotherhoodException(res) else: credits = int(res[3:]) - self.logInfo(_("%d credits left") % credits) + self.log_info(_("%d credits left") % credits) self.info['credits'] = credits return credits @@ -74,7 +70,7 @@ class CaptchaBrotherhood(Hook): try: img = Image.open(captcha) output = StringIO.StringIO() - self.logDebug("CAPTCHA IMAGE", img, img.format, img.mode) + self.log_debug("CAPTCHA IMAGE", img, img.format, img.mode) if img.format in ("GIF", "JPEG"): img.save(output, img.format) else: @@ -86,11 +82,11 @@ class CaptchaBrotherhood(Hook): except Exception, e: raise CaptchaBrotherhoodException("Reading or converting captcha image failed: %s" % e) - req = getRequest() + req = get_request() url = "%ssendNewCaptcha.aspx?%s" % (self.API_URL, - urllib.urlencode({'username' : self.getConfig('username'), - 'password' : self.getConfig('passkey'), + urllib.urlencode({'username' : self.get_config('username'), + 'password' : self.get_config('password'), 'captchaSource': "pyLoad", 'timeout' : "80"})) @@ -122,50 +118,50 @@ class CaptchaBrotherhood(Hook): def api_response(self, api, ticket): - res = getURL("%s%s.aspx" % (self.API_URL, api), - get={"username": self.getConfig('username'), - "password": self.getConfig('passkey'), - "captchaID": ticket}) + res = self.load("%s%s.aspx" % (self.API_URL, api), + get={'username': self.get_config('username'), + 'password': self.get_config('password'), + 'captchaID': ticket}) if not res.startswith("OK"): raise CaptchaBrotherhoodException("Unknown response: %s" % res) return res - def newCaptchaTask(self, task): + def captcha_task(self, task): if "service" in task.data: return False if not task.isTextual(): return False - if not self.getConfig('username') or not self.getConfig('passkey'): + if not self.get_config('username') or not self.get_config('password'): return False - if self.core.isClientConnected() and not self.getConfig('force'): + if self.pyload.isClientConnected() and self.get_config('check_client'): return False - if self.getCredits() > 10: + if self.get_credits() > 10: task.handler.append(self) task.data['service'] = self.__name__ task.setWaiting(100) - self._processCaptcha(task) + self._process_captcha(task) else: - self.logInfo(_("Your CaptchaBrotherhood Account has not enough credits")) + self.log_info(_("Your CaptchaBrotherhood Account has not enough credits")) - def captchaInvalid(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: + def captcha_invalid(self, task): + if task.data['service'] is self.__name__ and "ticket" in task.data: res = self.api_response("complainCaptcha", task.data['ticket']) @threaded - def _processCaptcha(self, task): + def _process_captcha(self, task): c = task.captchaFile try: ticket, result = self.submit(c) except CaptchaBrotherhoodException, e: - task.error = e.getCode() + task.error = e.get_code() return task.data['ticket'] = ticket diff --git a/module/plugins/hooks/Checksum.py b/module/plugins/hooks/Checksum.py index ab7daf701..6ecbfcda2 100644 --- a/module/plugins/hooks/Checksum.py +++ b/module/plugins/hooks/Checksum.py @@ -7,11 +7,11 @@ import os import re import zlib -from module.plugins.Hook import Hook -from module.utils import save_join, fs_encode +from module.plugins.internal.Addon import Addon +from module.utils import save_join as fs_join, fs_encode -def computeChecksum(local_file, algorithm): +def compute_checksum(local_file, algorithm): if algorithm in getattr(hashlib, "algorithms", ("md5", "sha1", "sha224", "sha256", "sha384", "sha512")): h = getattr(hashlib, algorithm)() @@ -35,16 +35,17 @@ def computeChecksum(local_file, algorithm): return None -class Checksum(Hook): +class Checksum(Addon): __name__ = "Checksum" __type__ = "hook" - __version__ = "0.16" + __version__ = "0.19" + __status__ = "testing" - __config__ = [("check_checksum", "bool", "Check checksum? (If False only size will be verified)", True), - ("check_action", "fail;retry;nothing", "What to do if check fails?", "retry"), - ("max_tries", "int", "Number of retries", 2), - ("retry_action", "fail;nothing", "What to do if all retries fail?", "fail"), - ("wait_time", "int", "Time to wait before each retry (seconds)", 1)] + __config__ = [("check_checksum", "bool" , "Check checksum? (If False only size will be verified)", True ), + ("check_action" , "fail;retry;nothing", "What to do if check fails?" , "retry"), + ("max_tries" , "int" , "Number of retries" , 2 ), + ("retry_action" , "fail;nothing" , "What to do if all retries fail?" , "fail" ), + ("wait_time" , "int" , "Time to wait before each retry (seconds)" , 1 )] __description__ = """Verify downloaded file size and checksum""" __license__ = "GPLv3" @@ -53,7 +54,6 @@ class Checksum(Hook): ("stickell" , "l.stickell@yahoo.it")] - interval = 0 #@TODO: Remove in 0.4.10 methods = {'sfv' : 'crc32', 'crc' : 'crc32', 'hash': 'md5'} @@ -63,13 +63,12 @@ class Checksum(Hook): 'default': r'^(?P<HASH>[0-9A-Fa-f]+)\s+\*?(?P<NAME>.+)$'} - def coreReady(self): - if not self.getConfig('check_checksum'): - self.logInfo(_("Checksum validation is disabled in plugin configuration")) + def activate(self): + if not self.get_config('check_checksum'): + self.log_info(_("Checksum validation is disabled in plugin configuration")) - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 + def init(self): self.algorithms = sorted( getattr(hashlib, "algorithms", ("md5", "sha1", "sha224", "sha256", "sha384", "sha512")), reverse=True) @@ -78,12 +77,12 @@ class Checksum(Hook): self.formats = self.algorithms + ["sfv", "crc", "hash"] - def downloadFinished(self, pyfile): + def download_finished(self, pyfile): """ Compute checksum for the downloaded file and compare it with the hash provided by the hoster. pyfile.plugin.check_data should be a dictionary which can contain: - a) if known, the exact filesize in bytes (e.g. "size": 123456789) - b) hexadecimal hash string with algorithm name as key (e.g. "md5": "d76505d0869f9f928a17d42d66326307") + a) if known, the exact filesize in bytes (e.g. 'size': 123456789) + b) hexadecimal hash string with algorithm name as key (e.g. 'md5': "d76505d0869f9f928a17d42d66326307") """ if hasattr(pyfile.plugin, "check_data") and isinstance(pyfile.plugin.check_data, dict): data = pyfile.plugin.check_data.copy() @@ -98,31 +97,31 @@ class Checksum(Hook): else: return - self.logDebug(data) + self.log_debug(data) - if not pyfile.plugin.lastDownload: - self.checkFailed(pyfile, None, "No file downloaded") + if not pyfile.plugin.last_download: + self.check_failed(pyfile, None, "No file downloaded") - local_file = fs_encode(pyfile.plugin.lastDownload) - #download_folder = self.config['general']['download_folder'] - #local_file = fs_encode(save_join(download_folder, pyfile.package().folder, pyfile.name)) + local_file = fs_encode(pyfile.plugin.last_download) + # download_folder = self.pyload.config.get("general", "download_folder") + # local_file = fs_encode(fs_join(download_folder, pyfile.package().folder, pyfile.name)) if not os.path.isfile(local_file): - self.checkFailed(pyfile, None, "File does not exist") + self.check_failed(pyfile, None, "File does not exist") - # validate file size + #: Validate file size if "size" in data: api_size = int(data['size']) file_size = os.path.getsize(local_file) - if api_size != file_size: - self.logWarning(_("File %s has incorrect size: %d B (%d expected)") % (pyfile.name, file_size, api_size)) - self.checkFailed(pyfile, local_file, "Incorrect file size") + if api_size is not file_size: + self.log_warning(_("File %s has incorrect size: %d B (%d expected)") % (pyfile.name, file_size, api_size)) + self.check_failed(pyfile, local_file, "Incorrect file size") data.pop('size', None) - # validate checksum - if data and self.getConfig('check_checksum'): + #: Validate checksum + if data and self.get_config('check_checksum'): if not 'md5' in data: for type in ("checksum", "hashsum", "hash"): @@ -134,29 +133,29 @@ class Checksum(Hook): if key in data: checksum = computeChecksum(local_file, key.replace("-", "").lower()) if checksum: - if checksum == data[key].lower(): - self.logInfo(_('File integrity of "%s" verified by %s checksum (%s)') % + if checksum is data[key].lower(): + self.log_info(_('File integrity of "%s" verified by %s checksum (%s)') % (pyfile.name, key.upper(), checksum)) break else: - self.logWarning(_("%s checksum for file %s does not match (%s != %s)") % + self.log_warning(_("%s checksum for file %s does not match (%s != %s)") % (key.upper(), pyfile.name, checksum, data[key])) - self.checkFailed(pyfile, local_file, "Checksums do not match") + self.check_failed(pyfile, local_file, "Checksums do not match") else: - self.logWarning(_("Unsupported hashing algorithm"), key.upper()) + self.log_warning(_("Unsupported hashing algorithm"), key.upper()) else: - self.logWarning(_("Unable to validate checksum for file: ") + pyfile.name) + self.log_warning(_("Unable to validate checksum for file: ") + pyfile.name) - def checkFailed(self, pyfile, local_file, msg): - check_action = self.getConfig('check_action') + def check_failed(self, pyfile, local_file, msg): + check_action = self.get_config('check_action') if check_action == "retry": - max_tries = self.getConfig('max_tries') - retry_action = self.getConfig('retry_action') + max_tries = self.get_config('max_tries') + retry_action = self.get_config('retry_action') if pyfile.plugin.retries < max_tries: if local_file: os.remove(local_file) - pyfile.plugin.retry(max_tries, self.getConfig('wait_time'), msg) + pyfile.plugin.retry(max_tries, self.get_config('wait_time'), msg) elif retry_action == "nothing": return elif check_action == "nothing": @@ -164,18 +163,18 @@ class Checksum(Hook): pyfile.plugin.fail(reason=msg) - def packageFinished(self, pypack): - download_folder = save_join(self.config['general']['download_folder'], pypack.folder, "") + def package_finished(self, pypack): + download_folder = fs_join(self.pyload.config.get("general", "download_folder"), pypack.folder, "") - for link in pypack.getChildren().itervalues(): + for link in pypack.getChildren().values(): file_type = os.path.splitext(link['name'])[1][1:].lower() if file_type not in self.formats: continue - hash_file = fs_encode(save_join(download_folder, link['name'])) + hash_file = fs_encode(fs_join(download_folder, link['name'])) if not os.path.isfile(hash_file): - self.logWarning(_("File not found"), link['name']) + self.log_warning(_("File not found"), link['name']) continue with open(hash_file) as f: @@ -183,14 +182,14 @@ class Checksum(Hook): for m in re.finditer(self.regexps.get(file_type, self.regexps['default']), text): data = m.groupdict() - self.logDebug(link['name'], data) + self.log_debug(link['name'], data) - local_file = fs_encode(save_join(download_folder, data['NAME'])) + local_file = fs_encode(fs_join(download_folder, data['NAME'])) algorithm = self.methods.get(file_type, file_type) checksum = computeChecksum(local_file, algorithm) - if checksum == data['HASH']: - self.logInfo(_('File integrity of "%s" verified by %s checksum (%s)') % + if checksum is data['HASH']: + self.log_info(_('File integrity of "%s" verified by %s checksum (%s)') % (data['NAME'], algorithm, checksum)) else: - self.logWarning(_("%s checksum for file %s does not match (%s != %s)") % + self.log_warning(_("%s checksum for file %s does not match (%s != %s)") % (algorithm, data['NAME'], checksum, data['HASH'])) diff --git a/module/plugins/hooks/ClickAndLoad.py b/module/plugins/hooks/ClickAndLoad.py index a7862045e..ba03129e6 100644 --- a/module/plugins/hooks/ClickAndLoad.py +++ b/module/plugins/hooks/ClickAndLoad.py @@ -10,7 +10,7 @@ except ImportError: from threading import Lock -from module.plugins.Hook import Hook, threaded +from module.plugins.internal.Addon import Addon, threaded def forward(source, destination): @@ -22,14 +22,15 @@ def forward(source, destination): bufdata = source.recv(bufsize) finally: destination.shutdown(socket.SHUT_WR) - # destination.close() + #: destination.close() #@TODO: IPv6 support -class ClickAndLoad(Hook): +class ClickAndLoad(Addon): __name__ = "ClickAndLoad" __type__ = "hook" - __version__ = "0.43" + __version__ = "0.45" + __status__ = "testing" __config__ = [("activated", "bool", "Activated" , True), ("port" , "int" , "Port" , 9666), @@ -41,20 +42,13 @@ class ClickAndLoad(Hook): ("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def coreReady(self): - if not self.config['webinterface']['activated']: + def activate(self): + if not self.pyload.config.get("webinterface", "activated"): return - ip = "" if self.getConfig('extern') else "127.0.0.1" - webport = self.config['webinterface']['port'] - cnlport = self.getConfig('port') + ip = "" if self.get_config('extern') else "127.0.0.1" + webport = self.pyload.config.get("webinterface", "port") + cnlport = self.get_config('port') self.proxy(ip, webport, cnlport) @@ -63,7 +57,7 @@ class ClickAndLoad(Hook): def proxy(self, ip, webport, cnlport): time.sleep(10) #@TODO: Remove in 0.4.10 (implement addon delay on startup) - self.logInfo(_("Proxy listening on %s:%s") % (ip or "0.0.0.0", cnlport)) + self.log_info(_("Proxy listening on %s:%s") % (ip or "0.0.0.0", cnlport)) self._server(ip, webport, cnlport) @@ -81,22 +75,22 @@ class ClickAndLoad(Hook): while True: client_socket, client_addr = dock_socket.accept() - self.logDebug("Connection from %s:%s" % client_addr) + self.log_debug("Connection from %s:%s" % client_addr) server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if self.config['webinterface']['https']: + if self.pyload.config.get("webinterface", "https"): try: server_socket = ssl.wrap_socket(server_socket) except NameError: - self.logError(_("pyLoad's webinterface is configured to use HTTPS, Please install python's ssl lib or disable HTTPS")) - client_socket.close() #: reset the connection. + self.log_error(_("pyLoad's webinterface is configured to use HTTPS, Please install python's ssl lib or disable HTTPS")) + client_socket.close() #: Reset the connection. continue except Exception, e: - self.logError(_("SSL error: %s") % e.message) - client_socket.close() #: reset the connection. + self.log_error(_("SSL error: %s") % e.message) + client_socket.close() #: Reset the connection. continue server_socket.connect(("127.0.0.1", webport)) @@ -105,10 +99,10 @@ class ClickAndLoad(Hook): self.manager.startThread(forward, server_socket, client_socket) except socket.timeout: - self.logDebug("Connection timed out, retrying...") + self.log_debug("Connection timed out, retrying...") return self._server(ip, webport, cnlport) except socket.error, e: - self.logError(e) + self.log_error(e) time.sleep(240) return self._server(ip, webport, cnlport) diff --git a/module/plugins/hooks/DeathByCaptcha.py b/module/plugins/hooks/DeathByCaptcha.py index f9618f011..98572191e 100644 --- a/module/plugins/hooks/DeathByCaptcha.py +++ b/module/plugins/hooks/DeathByCaptcha.py @@ -10,8 +10,8 @@ from base64 import b64encode from module.common.json_layer import json_loads from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getRequest -from module.plugins.Hook import Hook, threaded +from module.network.RequestFactory import getRequest as get_request +from module.plugins.internal.Hook import Hook, threaded class DeathByCaptchaException(Exception): @@ -29,11 +29,11 @@ class DeathByCaptchaException(Exception): self.err = err - def getCode(self): + def get_code(self): return self.err - def getDesc(self): + def get_desc(self): if self.err in self.DBC_ERRORS.keys(): return self.DBC_ERRORS[self.err] else: @@ -51,11 +51,12 @@ class DeathByCaptchaException(Exception): class DeathByCaptcha(Hook): __name__ = "DeathByCaptcha" __type__ = "hook" - __version__ = "0.06" + __version__ = "0.08" + __status__ = "testing" - __config__ = [("username", "str", "Username", ""), - ("passkey", "password", "Password", ""), - ("force", "bool", "Force DBC even if client is connected", False)] + __config__ = [("username" , "str" , "Username" , "" ), + ("password" , "password", "Password" , "" ), + ("check_client", "bool" , "Don't use if client is connected", True)] __description__ = """Send captchas to DeathByCaptcha.com""" __license__ = "GPLv3" @@ -63,31 +64,27 @@ class DeathByCaptcha(Hook): ("zoidberg", "zoidberg@mujmail.cz")] - interval = 0 #@TODO: Remove in 0.4.10 - API_URL = "http://api.dbcapi.me/api/" - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - def api_response(self, api="captcha", post=False, multipart=False): - req = getRequest() - req.c.setopt(pycurl.HTTPHEADER, ["Accept: application/json", "User-Agent: pyLoad %s" % self.core.version]) + req = get_request() + req.c.setopt(pycurl.HTTPHEADER, ["Accept: application/json", "User-Agent: pyLoad %s" % self.pyload.version]) if post: if not isinstance(post, dict): post = {} - post.update({"username": self.getConfig('username'), - "password": self.getConfig('passkey')}) + post.update({'username': self.get_config('username'), + 'password': self.get_config('password')}) res = None try: - json = req.load("%s%s" % (self.API_URL, api), - post=post, - multipart=multipart) - self.logDebug(json) + json = self.load("%s%s" % (self.API_URL, api), + post=post, + multipart=multipart, + req=req) + + self.log_debug(json) res = json_loads(json) if "error" in res: @@ -96,11 +93,11 @@ class DeathByCaptcha(Hook): raise DeathByCaptchaException(str(res)) except BadHeader, e: - if 403 == e.code: + if 403 is e.code: raise DeathByCaptchaException('not-logged-in') - elif 413 == e.code: + elif 413 is e.code: raise DeathByCaptchaException('invalid-captcha') - elif 503 == e.code: + elif 503 is e.code: raise DeathByCaptchaException('service-overload') elif e.code in (400, 405): raise DeathByCaptchaException('invalid-request') @@ -113,7 +110,7 @@ class DeathByCaptcha(Hook): return res - def getCredits(self): + def get_credits(self): res = self.api_response("user", True) if 'is_banned' in res and res['is_banned']: @@ -124,7 +121,7 @@ class DeathByCaptcha(Hook): raise DeathByCaptchaException(res) - def getStatus(self): + def get_status(self): res = self.api_response("status", False) if 'is_service_overloaded' in res and res['is_service_overloaded']: @@ -133,7 +130,7 @@ class DeathByCaptcha(Hook): def submit(self, captcha, captchaType="file", match=None): #@NOTE: Workaround multipart-post bug in HTTPRequest.py - if re.match("^\w*$", self.getConfig('passkey')): + if re.match("^\w*$", self.get_config('password')): multipart = True data = (pycurl.FORM_FILE, captcha) else: @@ -142,7 +139,7 @@ class DeathByCaptcha(Hook): data = f.read() data = "base64:" + b64encode(data) - res = self.api_response("captcha", {"captchafile": data}, multipart) + res = self.api_response("captcha", {'captchafile': data}, multipart) if "captcha" not in res: raise DeathByCaptchaException(res) @@ -157,33 +154,33 @@ class DeathByCaptcha(Hook): raise DeathByCaptchaException('timed-out') result = res['text'] - self.logDebug("Result %s : %s" % (ticket, result)) + self.log_debug("Result %s : %s" % (ticket, result)) return ticket, result - def newCaptchaTask(self, task): + def captcha_task(self, task): if "service" in task.data: return False if not task.isTextual(): return False - if not self.getConfig('username') or not self.getConfig('passkey'): + if not self.get_config('username') or not self.get_config('password'): return False - if self.core.isClientConnected() and not self.getConfig('force'): + if self.pyload.isClientConnected() and self.get_config('check_client'): return False try: - self.getStatus() - self.getCredits() + self.get_status() + self.get_credits() except DeathByCaptchaException, e: - self.logError(e.getDesc()) + self.log_error(e.getDesc()) return False balance, rate = self.info['balance'], self.info['rate'] - self.logInfo(_("Account balance"), + self.log_info(_("Account balance"), _("US$%.3f (%d captchas left at %.2f cents each)") % (balance / 100, balance // rate, rate)) @@ -191,29 +188,29 @@ class DeathByCaptcha(Hook): task.handler.append(self) task.data['service'] = self.__name__ task.setWaiting(180) - self._processCaptcha(task) + self._process_captcha(task) - def captchaInvalid(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: + def captcha_invalid(self, task): + if task.data['service'] is self.__name__ and "ticket" in task.data: try: res = self.api_response("captcha/%d/report" % task.data['ticket'], True) except DeathByCaptchaException, e: - self.logError(e.getDesc()) + self.log_error(e.getDesc()) except Exception, e: - self.logError(e) + self.log_error(e) @threaded - def _processCaptcha(self, task): + def _process_captcha(self, task): c = task.captchaFile try: ticket, result = self.submit(c) except DeathByCaptchaException, e: - task.error = e.getCode() - self.logError(e.getDesc()) + task.error = e.get_code() + self.log_error(e.getDesc()) return task.data['ticket'] = ticket diff --git a/module/plugins/hooks/DebridItaliaComHook.py b/module/plugins/hooks/DebridItaliaComHook.py index 36b307696..1b000c665 100644 --- a/module/plugins/hooks/DebridItaliaComHook.py +++ b/module/plugins/hooks/DebridItaliaComHook.py @@ -8,13 +8,13 @@ from module.plugins.internal.MultiHook import MultiHook class DebridItaliaComHook(MultiHook): __name__ = "DebridItaliaComHook" __type__ = "hook" - __version__ = "0.12" + __version__ = "0.13" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Debriditalia.com hook plugin""" __license__ = "GPLv3" @@ -22,5 +22,5 @@ class DebridItaliaComHook(MultiHook): ("Walter Purcaro", "vuolter@gmail.com" )] - def getHosters(self): - return self.getURL("http://debriditalia.com/api.php", get={'hosts': ""}).replace('"', '').split(',') + def get_hosters(self): + return self.load("http://debriditalia.com/api.php", get={'hosts': ""}).replace('"', '').split(',') diff --git a/module/plugins/hooks/DeleteFinished.py b/module/plugins/hooks/DeleteFinished.py index be17c3c0f..75a282808 100644 --- a/module/plugins/hooks/DeleteFinished.py +++ b/module/plugins/hooks/DeleteFinished.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- from module.database import style -from module.plugins.Hook import Hook +from module.plugins.internal.Addon import Addon -class DeleteFinished(Hook): +class DeleteFinished(Addon): __name__ = "DeleteFinished" __type__ = "hook" - __version__ = "1.12" + __version__ = "1.14" + __status__ = "testing" __config__ = [("interval" , "int" , "Check interval in hours" , 72 ), ("deloffline", "bool", "Delete package with offline links", False)] @@ -21,59 +22,60 @@ class DeleteFinished(Hook): ## overwritten methods ## - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - # self.event_list = ["pluginConfigChanged"] + def init(self): + # self.event_map = {'pluginConfigChanged': "plugin_config_changed"} self.interval = self.MIN_CHECK_INTERVAL def periodical(self): if not self.info['sleep']: - deloffline = self.getConfig('deloffline') - mode = '0,1,4' if deloffline else '0,4' + deloffline = self.get_config('deloffline') + mode = "0,1,4" if deloffline else "0,4" msg = _('delete all finished packages in queue list (%s packages with offline links)') - self.logInfo(msg % (_('including') if deloffline else _('excluding'))) - self.deleteFinished(mode) + self.log_info(msg % (_('including') if deloffline else _('excluding'))) + self.delete_finished(mode) self.info['sleep'] = True - self.addEvent('packageFinished', self.wakeup) + self.add_event('package_finished', self.wakeup) - # def pluginConfigChanged(self, plugin, name, value): - # if name == "interval" and value != self.interval: + # def plugin_config_changed(self, plugin, name, value): + # if name == "interval" and value is not self.interval: # self.interval = value * 3600 - # self.initPeriodical() + # self.init_periodical() - def unload(self): - self.manager.removeEvent('packageFinished', self.wakeup) + def deactivate(self): + self.manager.removeEvent('package_finished', self.wakeup) - def coreReady(self): + def activate(self): self.info['sleep'] = True - # interval = self.getConfig('interval') - # self.pluginConfigChanged(self.__name__, 'interval', interval) - self.interval = max(self.MIN_CHECK_INTERVAL, self.getConfig('interval') * 60 * 60) - self.addEvent('packageFinished', self.wakeup) + # interval = self.get_config('interval') + # self.plugin_config_changed(self.__name__, 'interval', interval) + self.interval = max(self.MIN_CHECK_INTERVAL, self.get_config('interval') * 60 * 60) + self.add_event('package_finished', self.wakeup) ## own methods ## @style.queue - def deleteFinished(self, mode): + def delete_finished(self, mode): self.c.execute('DELETE FROM packages WHERE NOT EXISTS(SELECT 1 FROM links WHERE package=packages.id AND status NOT IN (%s))' % mode) self.c.execute('DELETE FROM links WHERE NOT EXISTS(SELECT 1 FROM packages WHERE id=links.package)') def wakeup(self, pypack): - self.manager.removeEvent('packageFinished', self.wakeup) + self.manager.removeEvent('package_finished', self.wakeup) self.info['sleep'] = False ## event managing ## - def addEvent(self, event, func): - """Adds an event listener for event name""" + def add_event(self, event, func): + """ + Adds an event listener for event name + """ if event in self.manager.events: if func in self.manager.events[event]: - self.logDebug("Function already registered", func) + self.log_debug("Function already registered", func) else: self.manager.events[event].append(func) else: diff --git a/module/plugins/hooks/DownloadScheduler.py b/module/plugins/hooks/DownloadScheduler.py index 9c74ac1d4..b2e804dce 100644 --- a/module/plugins/hooks/DownloadScheduler.py +++ b/module/plugins/hooks/DownloadScheduler.py @@ -3,17 +3,17 @@ import re import time -from module.plugins.Hook import Hook +from module.plugins.internal.Addon import Addon -class DownloadScheduler(Hook): +class DownloadScheduler(Addon): __name__ = "DownloadScheduler" __type__ = "hook" - __version__ = "0.22" + __version__ = "0.24" + __status__ = "testing" - __config__ = [("timetable", "str", "List time periods as hh:mm full or number(kB/s)", - "0:00 full, 7:00 250, 10:00 0, 17:00 150"), - ("abort", "bool", "Abort active downloads when start period with speed 0", False)] + __config__ = [("timetable", "str" , "List time periods as hh:mm full or number(kB/s)" , "0:00 full, 7:00 250, 10:00 0, 17:00 150"), + ("abort" , "bool", "Abort active downloads when start period with speed 0", False )] __description__ = """Download Scheduler""" __license__ = "GPLv3" @@ -21,61 +21,53 @@ class DownloadScheduler(Hook): ("stickell", "l.stickell@yahoo.it")] - interval = 0 #@TODO: Remove in 0.4.10 + def activate(self): + self.update_schedule() - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.cb = None # callback to scheduler job; will be by removed hookmanager when hook unloaded - - - def coreReady(self): - self.updateSchedule() - - - def updateSchedule(self, schedule=None): + def update_schedule(self, schedule=None): if schedule is None: - schedule = self.getConfig('timetable') + schedule = self.get_config('timetable') schedule = re.findall("(\d{1,2}):(\d{2})[\s]*(-?\d+)", schedule.lower().replace("full", "-1").replace("none", "0")) if not schedule: - self.logError(_("Invalid schedule")) + self.log_error(_("Invalid schedule")) return t0 = time.localtime() now = (t0.tm_hour, t0.tm_min, t0.tm_sec, "X") schedule = sorted([(int(x[0]), int(x[1]), 0, int(x[2])) for x in schedule] + [now]) - self.logDebug("Schedule", schedule) + self.log_debug("Schedule", schedule) for i, v in enumerate(schedule): if v[3] == "X": last, next = schedule[i - 1], schedule[(i + 1) % len(schedule)] - self.logDebug("Now/Last/Next", now, last, next) + self.log_debug("Now/Last/Next", now, last, next) - self.setDownloadSpeed(last[3]) + self.set_download_speed(last[3]) next_time = (((24 + next[0] - now[0]) * 60 + next[1] - now[1]) * 60 + next[2] - now[2]) % 86400 - self.core.scheduler.removeJob(self.cb) - self.cb = self.core.scheduler.addJob(next_time, self.updateSchedule, threaded=False) + self.pyload.scheduler.removeJob(self.cb) + self.cb = self.pyload.scheduler.addJob(next_time, self.update_schedule, threaded=False) - def setDownloadSpeed(self, speed): + def set_download_speed(self, speed): if speed == 0: - abort = self.getConfig('abort') - self.logInfo(_("Stopping download server. (Running downloads will %sbe aborted.)") % '' if abort else _('not ')) - self.core.api.pauseServer() + abort = self.get_config('abort') + self.log_info(_("Stopping download server. (Running downloads will %sbe aborted.)") % '' if abort else _('not ')) + self.pyload.api.pauseServer() if abort: - self.core.api.stopAllDownloads() + self.pyload.api.stopAllDownloads() else: - self.core.api.unpauseServer() + self.pyload.api.unpauseServer() if speed > 0: - self.logInfo(_("Setting download speed to %d kB/s") % speed) - self.core.api.setConfigValue("download", "limit_speed", 1) - self.core.api.setConfigValue("download", "max_speed", speed) + self.log_info(_("Setting download speed to %d kB/s") % speed) + self.pyload.config.set("download", "limit_speed", 1) + self.pyload.config.set("download", "max_speed", speed) else: - self.logInfo(_("Setting download speed to FULL")) - self.core.api.setConfigValue("download", "limit_speed", 0) - self.core.api.setConfigValue("download", "max_speed", -1) + self.log_info(_("Setting download speed to FULL")) + self.pyload.config.set("download", "limit_speed", 0) + self.pyload.config.set("download", "max_speed", -1) diff --git a/module/plugins/hooks/EasybytezComHook.py b/module/plugins/hooks/EasybytezComHook.py index 43efb5048..6f53619ac 100644 --- a/module/plugins/hooks/EasybytezComHook.py +++ b/module/plugins/hooks/EasybytezComHook.py @@ -8,23 +8,23 @@ from module.plugins.internal.MultiHook import MultiHook class EasybytezComHook(MultiHook): __name__ = "EasybytezComHook" __type__ = "hook" - __version__ = "0.07" + __version__ = "0.08" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """EasyBytez.com hook plugin""" __license__ = "GPLv3" __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] - def getHosters(self): - user, data = self.account.selectAccount() + def get_hosters(self): + user, info = self.account.select() - req = self.account.getAccountRequest(user) - html = req.load("http://www.easybytez.com") + html = self.load("http://www.easybytez.com", + req=self.account.get_request(user)) return re.search(r'</textarea>\s*Supported sites:(.*)', html).group(1).split(',') diff --git a/module/plugins/hooks/ExpertDecoders.py b/module/plugins/hooks/ExpertDecoders.py index ccd48f664..630382f2d 100644 --- a/module/plugins/hooks/ExpertDecoders.py +++ b/module/plugins/hooks/ExpertDecoders.py @@ -8,17 +8,18 @@ import uuid from base64 import b64encode from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getURL, getRequest -from module.plugins.Hook import Hook, threaded +from module.network.RequestFactory import getRequest as get_request +from module.plugins.internal.Hook import Hook, threaded class ExpertDecoders(Hook): __name__ = "ExpertDecoders" __type__ = "hook" - __version__ = "0.04" + __version__ = "0.06" + __status__ = "testing" - __config__ = [("force", "bool", "Force CT even if client is connected", False), - ("passkey", "password", "Access key", "")] + __config__ = [("passkey" , "password", "Access key" , "" ), + ("check_client", "bool" , "Don't use if client is connected", True)] __description__ = """Send captchas to expertdecoders.com""" __license__ = "GPLv3" @@ -26,78 +27,73 @@ class ExpertDecoders(Hook): ("zoidberg", "zoidberg@mujmail.cz")] - interval = 0 #@TODO: Remove in 0.4.10 - API_URL = "http://www.fasttypers.org/imagepost.ashx" - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def getCredits(self): - res = getURL(self.API_URL, post={"key": self.getConfig('passkey'), "action": "balance"}) + def get_credits(self): + res = self.load(self.API_URL, post={'key': self.get_config('passkey'), 'action': "balance"}) if res.isdigit(): - self.logInfo(_("%s credits left") % res) + self.log_info(_("%s credits left") % res) self.info['credits'] = credits = int(res) return credits else: - self.logError(res) + self.log_error(res) return 0 @threaded - def _processCaptcha(self, task): + def _process_captcha(self, task): task.data['ticket'] = ticket = uuid.uuid4() result = None with open(task.captchaFile, 'rb') as f: data = f.read() - req = getRequest() - #raise timeout threshold + req = get_request() + #: Raise timeout threshold req.c.setopt(pycurl.LOW_SPEED_TIME, 80) try: - result = req.load(self.API_URL, - post={'action' : "upload", - 'key' : self.getConfig('passkey'), + result = self.load(self.API_URL, + post={'action' : "upload", + 'key' : self.get_config('passkey'), 'file' : b64encode(data), - 'gen_task_id': ticket}) + 'gen_task_id': ticket}, + req=req) finally: req.close() - self.logDebug("Result %s : %s" % (ticket, result)) + self.log_debug("Result %s : %s" % (ticket, result)) task.setResult(result) - def newCaptchaTask(self, task): + def captcha_task(self, task): if not task.isTextual(): return False - if not self.getConfig('passkey'): + if not self.get_config('passkey'): return False - if self.core.isClientConnected() and not self.getConfig('force'): + if self.pyload.isClientConnected() and self.get_config('check_client'): return False - if self.getCredits() > 0: + if self.get_credits() > 0: task.handler.append(self) task.setWaiting(100) - self._processCaptcha(task) + self._process_captcha(task) else: - self.logInfo(_("Your ExpertDecoders Account has not enough credits")) + self.log_info(_("Your ExpertDecoders Account has not enough credits")) - def captchaInvalid(self, task): + def captcha_invalid(self, task): if "ticket" in task.data: try: - res = getURL(self.API_URL, - post={'action': "refund", 'key': self.getConfig('passkey'), 'gen_task_id': task.data['ticket']}) - self.logInfo(_("Request refund"), res) + res = self.load(self.API_URL, + post={'action': "refund", 'key': self.get_config('passkey'), 'gen_task_id': task.data['ticket']}) + self.log_info(_("Request refund"), res) except BadHeader, e: - self.logError(_("Could not send refund request"), e) + self.log_error(_("Could not send refund request"), e) diff --git a/module/plugins/hooks/ExternalScripts.py b/module/plugins/hooks/ExternalScripts.py index a0815499b..b7495136a 100644 --- a/module/plugins/hooks/ExternalScripts.py +++ b/module/plugins/hooks/ExternalScripts.py @@ -3,17 +3,18 @@ import os import subprocess -from module.plugins.Hook import Hook -from module.utils import fs_encode, save_join +from module.plugins.internal.Addon import Addon, Expose +from module.utils import fs_encode, save_join as fs_join -class ExternalScripts(Hook): +class ExternalScripts(Addon): __name__ = "ExternalScripts" __type__ = "hook" - __version__ = "0.39" + __version__ = "0.46" + __status__ = "testing" __config__ = [("activated", "bool", "Activated" , True ), - ("waitend" , "bool", "Wait script ending", False)] + ("lock" , "bool", "Wait script ending", False)] __description__ = """Run external scripts""" __license__ = "GPLv3" @@ -23,18 +24,16 @@ class ExternalScripts(Hook): ("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {'oldip': None} + def init(self): + self.info['oldip'] = None self.scripts = {} self.event_list = ["archive_extract_failed", "archive_extracted" , "package_extract_failed", "package_extracted" , - "all_archives_extracted", "all_archives_processed", - "allDownloadsFinished" , "allDownloadsProcessed" , - "packageDeleted"] + "all_archives_extracted", "all_archives_processed"] + self.event_map = {'allDownloadsFinished' : "all_downloads_finished" , + 'allDownloadsProcessed': "all_downloads_processed", + 'packageDeleted' : "package_deleted" } folders = ["pyload_start", "pyload_restart", "pyload_stop", "before_reconnect", "after_reconnect", @@ -45,174 +44,204 @@ class ExternalScripts(Hook): "all_archives_extracted", "all_archives_processed"] for folder in folders: - self.scripts[folder] = [] - for dir in (pypath, ''): - self.initPluginType(folder, os.path.join(dir, 'scripts', folder)) + path = os.path.join("scripts", folder) + self.init_folder(folder, path) - for script_type, names in self.scripts.iteritems(): - if names: - self.logInfo(_("Installed scripts for: ") + script_type, ", ".join(map(os.path.basename, names))) + for folder, scripts in self.scripts.items(): + if scripts: + self.log_info(_("Installed scripts in folder `%s`: %s") + % (folder, ", ".join(scripts))) self.pyload_start() - def initPluginType(self, name, dir): - if not os.path.isdir(dir): + def init_folder(self, name, path): + self.scripts[name] = [] + + if not os.path.isdir(path): try: - os.makedirs(dir) + os.makedirs(path) except OSError, e: - self.logDebug(e) + self.log_debug(e) return - for filename in os.listdir(dir): - file = save_join(dir, filename) - + for file in os.listdir(path): if not os.path.isfile(file): continue - if filename[0] in ("#", "_") or filename.endswith("~") or filename.endswith(".swp"): + if file[0] in ("#", "_") or file.endswith("~") or file.endswith(".swp"): continue if not os.access(file, os.X_OK): - self.logWarning(_("Script not executable:") + " %s/%s" % (name, filename)) + self.log_warning(_("Script not executable: [%s] %s") % (name, file)) self.scripts[name].append(file) - def callScript(self, script, *args): + @Expose + def call(self, script, args=[], lock=False): try: - cmd_args = [fs_encode(str(x) if not isinstance(x, basestring) else x) for x in args] - cmd = [script] + cmd_args - - self.logDebug("Executing: %s" % os.path.abspath(script), "Args: " + ' '.join(cmd_args)) + script = os.path.abspath(script) + args = [script] + map(encode, args) - p = subprocess.Popen(cmd, bufsize=-1) #@NOTE: output goes to pyload - if self.getConfig('waitend'): + self.log_info(_("EXECUTE [%s] %s") % (os.path.dirname(script), args)) + p = subprocess.Popen(args, bufsize=-1) #@NOTE: output goes to pyload + if lock: p.communicate() except Exception, e: - try: - self.logError(_("Runtime error: %s") % os.path.abspath(script), e) - except Exception: - self.logError(_("Runtime error: %s") % os.path.abspath(script), _("Unknown error")) + self.log_error(_("Runtime error: %s") % script, e or _("Unknown error")) def pyload_start(self): + lock = self.get_config('lock') for script in self.scripts['pyload_start']: - self.callScript(script) + self.call(script, lock=lock) - def coreExiting(self): - for script in self.scripts['pyload_restart' if self.core.do_restart else 'pyload_stop']: - self.callScript(script) + def exit(self): + lock = self.get_config('lock') + for script in self.scripts['pyload_restart' if self.pyload.do_restart else 'pyload_stop']: + self.call(script, lock=True) - def beforeReconnecting(self, ip): + def before_reconnect(self, ip): + lock = self.get_config('lock') for script in self.scripts['before_reconnect']: - self.callScript(script, ip) + args = [ip] + self.call(script, args, lock) self.info['oldip'] = ip - def afterReconnecting(self, ip): + def after_reconnect(self, ip): + lock = self.get_config('lock') for script in self.scripts['after_reconnect']: - self.callScript(script, ip, self.info['oldip']) #@TODO: Use built-in oldip in 0.4.10 + args = [ip, self.info['oldip']] #@TODO: Use built-in oldip in 0.4.10 + self.call(script, args, lock) - def downloadPreparing(self, pyfile): + def download_preparing(self, pyfile): + lock = self.get_config('lock') for script in self.scripts['download_preparing']: - self.callScript(script, pyfile.id, pyfile.name, None, pyfile.pluginname, pyfile.url) + args = [pyfile.id, pyfile.name, None, pyfile.pluginname, pyfile.url] + self.call(script, args, lock) - def downloadFailed(self, pyfile): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pyfile.package().folder) + def download_failed(self, pyfile): + lock = self.get_config('lock') + + if self.pyload.config.get("general", "folder_per_package"): + download_folder = fs_join(self.pyload.config.get("general", "download_folder"), pyfile.package().folder) else: - download_folder = self.config['general']['download_folder'] + download_folder = self.pyload.config.get("general", "download_folder") for script in self.scripts['download_failed']: - file = save_join(download_folder, pyfile.name) - self.callScript(script, pyfile.id, pyfile.name, file, pyfile.pluginname, pyfile.url) + file = fs_join(download_folder, pyfile.name) + args = [script, pyfile.id, pyfile.name, file, pyfile.pluginname, pyfile.url] + self.call(script, args, lock) + + def download_finished(self, pyfile): + lock = self.get_config('lock') - def downloadFinished(self, pyfile): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pyfile.package().folder) + if self.pyload.config.get("general", "folder_per_package"): + download_folder = fs_join(self.pyload.config.get("general", "download_folder"), pyfile.package().folder) else: - download_folder = self.config['general']['download_folder'] + download_folder = self.pyload.config.get("general", "download_folder") for script in self.scripts['download_finished']: - file = save_join(download_folder, pyfile.name) - self.callScript(script, pyfile.id, pyfile.name, file, pyfile.pluginname, pyfile.url) + file = fs_join(download_folder, pyfile.name) + args = [pyfile.id, pyfile.name, file, pyfile.pluginname, pyfile.url] + self.call(script, args, lock) def archive_extract_failed(self, pyfile, archive): + lock = self.get_config('lock') for script in self.scripts['archive_extract_failed']: - self.callScript(script, pyfile.id, pyfile.name, archive.filename, archive.out, archive.files) + args = [pyfile.id, pyfile.name, archive.filename, archive.out, archive.files] + self.call(script, args, lock) def archive_extracted(self, pyfile, archive): + lock = self.get_config('lock') for script in self.scripts['archive_extracted']: - self.callScript(script, pyfile.id, pyfile.name, archive.filename, archive.out, archive.files) + args = [script, pyfile.id, pyfile.name, archive.filename, archive.out, archive.files] + self.call(script, args, lock) + + def package_finished(self, pypack): + lock = self.get_config('lock') - def packageFinished(self, pypack): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pypack.folder) + if self.pyload.config.get("general", "folder_per_package"): + download_folder = fs_join(self.pyload.config.get("general", "download_folder"), pypack.folder) else: - download_folder = self.config['general']['download_folder'] + download_folder = self.pyload.config.get("general", "download_folder") for script in self.scripts['package_finished']: - self.callScript(script, pypack.id, pypack.name, download_folder, pypack.password) + args = [pypack.id, pypack.name, download_folder, pypack.password] + self.call(script, args, lock) - def packageDeleted(self, pid): - pack = self.core.api.getPackageInfo(pid) + def package_deleted(self, pid): + lock = self.get_config('lock') + pack = self.pyload.api.getPackageInfo(pid) - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pack.folder) + if self.pyload.config.get("general", "folder_per_package"): + download_folder = fs_join(self.pyload.config.get("general", "download_folder"), pack.folder) else: - download_folder = self.config['general']['download_folder'] + download_folder = self.pyload.config.get("general", "download_folder") for script in self.scripts['package_deleted']: - self.callScript(script, pack.id, pack.name, download_folder, pack.password) + args = [pack.id, pack.name, download_folder, pack.password] + self.call(script, args, lock) def package_extract_failed(self, pypack): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pypack.folder) + lock = self.get_config('lock') + + if self.pyload.config.get("general", "folder_per_package"): + download_folder = fs_join(self.pyload.config.get("general", "download_folder"), pypack.folder) else: - download_folder = self.config['general']['download_folder'] + download_folder = self.pyload.config.get("general", "download_folder") for script in self.scripts['package_extract_failed']: - self.callScript(script, pypack.id, pypack.name, download_folder, pypack.password) + args = [pypack.id, pypack.name, download_folder, pypack.password] + self.call(script, args, lock) def package_extracted(self, pypack): - if self.config['general']['folder_per_package']: - download_folder = save_join(self.config['general']['download_folder'], pypack.folder) + lock = self.get_config('lock') + + if self.pyload.config.get("general", "folder_per_package"): + download_folder = fs_join(self.pyload.config.get("general", "download_folder"), pypack.folder) else: - download_folder = self.config['general']['download_folder'] + download_folder = self.pyload.config.get("general", "download_folder") for script in self.scripts['package_extracted']: - self.callScript(script, pypack.id, pypack.name, download_folder) + args = [pypack.id, pypack.name, download_folder] + self.call(script, args, lock) - def allDownloadsFinished(self): + def all_downloads_finished(self): + lock = self.get_config('lock') for script in self.scripts['all_downloads_finished']: - self.callScript(script) + self.call(script, lock=lock) - def allDownloadsProcessed(self): + def all_downloads_processed(self): + lock = self.get_config('lock') for script in self.scripts['all_downloads_processed']: - self.callScript(script) + self.call(script, lock=lock) def all_archives_extracted(self): + lock = self.get_config('lock') for script in self.scripts['all_archives_extracted']: - self.callScript(script) + self.call(script, lock=lock) def all_archives_processed(self): + lock = self.get_config('lock') for script in self.scripts['all_archives_processed']: - self.callScript(script) + self.call(script, lock=lock) diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py index 3e371ec2b..eab196160 100644 --- a/module/plugins/hooks/ExtractArchive.py +++ b/module/plugins/hooks/ExtractArchive.py @@ -23,10 +23,12 @@ if sys.version_info < (2, 7) and os.name != "nt": raise - # unsued timeout option for older python version + #: Unsued timeout option for older python version def wait(self, timeout=0): - """Wait for child process to terminate. Returns returncode - attribute.""" + """ + Wait for child process to terminate. Returns returncode + attribute. + """ if self.returncode is None: try: pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0) @@ -34,9 +36,9 @@ if sys.version_info < (2, 7) and os.name != "nt": except OSError, e: if e.errno != errno.ECHILD: raise - # This happens if SIGCLD is set to be ignored or waiting - # for child processes has otherwise been disabled for our - # process. This child is dead, we can't get the status. + #: This happens if SIGCLD is set to be ignored or waiting + #: For child processes has otherwise been disabled for our + #: process. This child is dead, we can't get the status. sts = 0 self._handle_exitstatus(sts) return self.returncode @@ -48,15 +50,10 @@ try: except ImportError: pass -from copy import copy -if os.name != "nt": - from grp import getgrnam - from pwd import getpwnam - -from module.plugins.Hook import Hook, Expose, threaded +from module.plugins.internal.Addon import Addon, Expose, threaded +from module.plugins.internal.Plugin import replace_patterns from module.plugins.internal.Extractor import ArchiveError, CRCError, PasswordError -from module.plugins.internal.SimpleHoster import replace_patterns -from module.utils import fs_encode, save_join, uniqify +from module.utils import fs_encode, save_join as fs_join, uniqify class ArchiveQueue(object): @@ -68,7 +65,7 @@ class ArchiveQueue(object): def get(self): try: - return [int(pid) for pid in self.plugin.getStorage("ExtractArchive:%s" % self.storage, "").decode('base64').split()] + return [int(pid) for pid in self.plugin.retrieve("ExtractArchive:%s" % self.storage, "").decode('base64').split()] except Exception: return [] @@ -78,11 +75,11 @@ class ArchiveQueue(object): item = str(value)[1:-1].replace(' ', '').replace(',', ' ') else: item = str(value).strip() - return self.plugin.setStorage("ExtractArchive:%s" % self.storage, item.encode('base64')[:-1]) + return self.plugin.store("ExtractArchive:%s" % self.storage, item.encode('base64')[:-1]) def delete(self): - return self.plugin.delStorage("ExtractArchive:%s" % self.storage) + return self.plugin.delete("ExtractArchive:%s" % self.storage) def add(self, item): @@ -101,16 +98,17 @@ class ArchiveQueue(object): except ValueError: pass - if queue == []: + if queue is []: return self.delete() return self.set(queue) -class ExtractArchive(Hook): +class ExtractArchive(Addon): __name__ = "ExtractArchive" __type__ = "hook" - __version__ = "1.44" + __version__ = "1.49" + __status__ = "testing" __config__ = [("activated" , "bool" , "Activated" , True ), ("fullpath" , "bool" , "Extract with full paths" , True ), @@ -119,7 +117,7 @@ class ExtractArchive(Hook): ("repair" , "bool" , "Repair broken archives (RAR required)" , False ), ("test" , "bool" , "Test archive before extracting" , False ), ("usepasswordfile", "bool" , "Use password file" , True ), - ("passwordfile" , "file" , "Password file" , "archive_password.txt" ), + ("passwordfile" , "file" , "Password file" , "passwords.txt" ), ("delete" , "bool" , "Delete archive after extraction" , True ), ("deltotrash" , "bool" , "Move to trash (recycle bin) instead delete", True ), ("subfolder" , "bool" , "Create subfolder for each package" , False ), @@ -139,53 +137,53 @@ class ExtractArchive(Hook): NAME_REPLACEMENTS = [(r'\.part\d+\.rar$', ".part.rar")] - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.event_list = ["allDownloadsProcessed","packageDeleted"] + def init(self): + self.event_map = {'allDownloadsProcessed': "all_downloads_processed", + 'packageDeleted' : "package_deleted" } self.queue = ArchiveQueue(self, "Queue") self.failed = ArchiveQueue(self, "Failed") self.interval = 60 self.extracting = False - self.lastPackage = False + self.last_package = False self.extractors = [] self.passwords = [] self.repair = False - def coreReady(self): + def activate(self): for p in ("UnRar", "SevenZip", "UnZip"): try: - module = self.core.pluginManager.loadModule("internal", p) + module = self.pyload.pluginManager.loadModule("internal", p) klass = getattr(module, p) - if klass.isUsable(): + if klass.find(): self.extractors.append(klass) if klass.REPAIR: - self.repair = self.getConfig('repair') + self.repair = self.get_config('repair') except OSError, e: if e.errno == 2: - self.logWarning(_("No %s installed") % p) + self.log_warning(_("No %s installed") % p) else: - self.logWarning(_("Could not activate: %s") % p, e) - if self.core.debug: + self.log_warning(_("Could not activate: %s") % p, e) + if self.pyload.debug: traceback.print_exc() except Exception, e: - self.logWarning(_("Could not activate: %s") % p, e) - if self.core.debug: + self.log_warning(_("Could not activate: %s") % p, e) + if self.pyload.debug: traceback.print_exc() if self.extractors: - self.logDebug(*["Found %s %s" % (Extractor.__name__, Extractor.VERSION) for Extractor in self.extractors]) - self.extractQueued() #: Resume unfinished extractions + self.log_debug(*["Found %s %s" % (Extractor.__name__, Extractor.VERSION) for Extractor in self.extractors]) + self.extract_queued() #: Resume unfinished extractions else: - self.logInfo(_("No Extract plugins activated")) + self.log_info(_("No Extract plugins activated")) @threaded - def extractQueued(self, thread): + def extract_queued(self, thread): if self.extracting: #@NOTE: doing the check here for safty (called by coreReady) return @@ -193,8 +191,8 @@ class ExtractArchive(Hook): packages = self.queue.get() while packages: - if self.lastPackage: #: called from allDownloadsProcessed - self.lastPackage = False + if self.last_package: #: Called from allDownloadsProcessed + self.last_package = False if self.extract(packages, thread): #@NOTE: check only if all gone fine, no failed reporting for now self.manager.dispatchEvent("all_archives_extracted") self.manager.dispatchEvent("all_archives_processed") @@ -202,34 +200,45 @@ class ExtractArchive(Hook): if self.extract(packages, thread): #@NOTE: check only if all gone fine, no failed reporting for now pass - packages = self.queue.get() #: check for packages added during extraction + packages = self.queue.get() #: Check for packages added during extraction self.extracting = False + #: Deprecated method, use `extract_package` instead @Expose - def extractPackage(self, *ids): - """ Extract packages with given id""" + def extractPackage(self, *args, **kwargs): + """ + See `extract_package` + """ + return self.extract_package(*args, **kwargs) + + + @Expose + def extract_package(self, *ids): + """ + Extract packages with given id + """ for id in ids: self.queue.add(id) - if not self.getConfig('waitall') and not self.extracting: - self.extractQueued() + if not self.get_config('waitall') and not self.extracting: + self.extract_queued() - def packageDeleted(self, pid): + def package_deleted(self, pid): self.queue.remove(pid) - def packageFinished(self, pypack): + def package_finished(self, pypack): self.queue.add(pypack.id) - if not self.getConfig('waitall') and not self.extracting: - self.extractQueued() + if not self.get_config('waitall') and not self.extracting: + self.extract_queued() - def allDownloadsProcessed(self): - self.lastPackage = True - if self.getConfig('waitall') and not self.extracting: - self.extractQueued() + def all_downloads_processed(self): + self.last_package = True + if self.get_config('waitall') and not self.extracting: + self.extract_queued() @Expose @@ -243,51 +252,51 @@ class ExtractArchive(Hook): toList = lambda string: string.replace(' ', '').replace(',', '|').replace(';', '|').split('|') - destination = self.getConfig('destination') - subfolder = self.getConfig('subfolder') - fullpath = self.getConfig('fullpath') - overwrite = self.getConfig('overwrite') - renice = self.getConfig('renice') - recursive = self.getConfig('recursive') - delete = self.getConfig('delete') - keepbroken = self.getConfig('keepbroken') + destination = self.get_config('destination') + subfolder = self.get_config('subfolder') + fullpath = self.get_config('fullpath') + overwrite = self.get_config('overwrite') + renice = self.get_config('renice') + recursive = self.get_config('recursive') + delete = self.get_config('delete') + keepbroken = self.get_config('keepbroken') - extensions = [x.lstrip('.').lower() for x in toList(self.getConfig('extensions'))] - excludefiles = toList(self.getConfig('excludefiles')) + extensions = [x.lstrip('.').lower() for x in toList(self.get_config('extensions'))] + excludefiles = toList(self.get_config('excludefiles')) if extensions: - self.logDebug("Use for extensions: %s" % "|.".join(extensions)) + self.log_debug("Use for extensions: %s" % "|.".join(extensions)) - # reload from txt file - self.reloadPasswords() + #: Reload from txt file + self.reload_passwords() - download_folder = self.config['general']['download_folder'] + download_folder = self.pyload.config.get("general", "download_folder") - # iterate packages -> extractors -> targets + #: Iterate packages -> extractors -> targets for pid in ids: - pypack = self.core.files.getPackage(pid) + pypack = self.pyload.files.getPackage(pid) if not pypack: self.queue.remove(pid) continue - self.logInfo(_("Check package: %s") % pypack.name) + self.log_info(_("Check package: %s") % pypack.name) - # determine output folder - out = save_join(download_folder, pypack.folder, destination, "") #: force trailing slash + #: Determine output folder + out = fs_join(download_folder, pypack.folder, destination, "") #: Force trailing slash if subfolder: - out = save_join(out, pypack.folder) + out = fs_join(out, pypack.folder) if not os.path.exists(out): os.makedirs(out) matched = False success = True - files_ids = dict((pylink['name'],((save_join(download_folder, pypack.folder, pylink['name'])), pylink['id'], out)) for pylink \ - in sorted(pypack.getChildren().itervalues(), key=lambda k: k['name'])).values() #: remove duplicates + files_ids = dict((pylink['name'], ((fs_join(download_folder, pypack.folder, pylink['name'])), pylink['id'], out)) for pylink \ + in sorted(pypack.getChildren().values(), key=lambda k: k['name'])).values() #: Remove duplicates - # check as long there are unseen files + #: Check as long there are unseen files while files_ids: new_files_ids = [] @@ -296,21 +305,21 @@ class ExtractArchive(Hook): if filter(lambda ext: fname.lower().endswith(ext), extensions)] for Extractor in self.extractors: - targets = Extractor.getTargets(files_ids) + targets = Extractor.get_targets(files_ids) if targets: - self.logDebug("Targets for %s: %s" % (Extractor.__name__, targets)) + self.log_debug("Targets for %s: %s" % (Extractor.__name__, targets)) matched = True for fname, fid, fout in targets: name = os.path.basename(fname) if not os.path.exists(fname): - self.logDebug(name, "File not found") + self.log_debug(name, "File not found") continue - self.logInfo(name, _("Extract to: %s") % fout) + self.log_info(name, _("Extract to: %s") % fout) try: - pyfile = self.core.files.getFile(fid) + pyfile = self.pyload.files.getFile(fid) archive = Extractor(self, fname, fout, @@ -333,28 +342,30 @@ class ExtractArchive(Hook): thread.finishFile(pyfile) except Exception, e: - self.logError(name, e) + self.log_error(name, e) success = False continue - # remove processed file and related multiparts from list + #: Remove processed file and related multiparts from list files_ids = [(fname, fid, fout) for fname, fid, fout in files_ids \ - if fname not in archive.getDeleteFiles()] - self.logDebug("Extracted files: %s" % new_files) - self.setPermissions(new_files) + if fname not in archive.get_delete_files()] + self.log_debug("Extracted files: %s" % new_files) + + for file in new_files: + self.set_permissions(file) for filename in new_files: - file = fs_encode(save_join(os.path.dirname(archive.filename), filename)) + file = fs_encode(fs_join(os.path.dirname(archive.filename), filename)) if not os.path.exists(file): - self.logDebug("New file %s does not exists" % filename) + self.log_debug("New file %s does not exists" % filename) continue if recursive and os.path.isfile(file): - new_files_ids.append((filename, fid, os.path.dirname(filename))) #: append as new target + new_files_ids.append((filename, fid, os.path.dirname(filename))) #: Append as new target self.manager.dispatchEvent("archive_extracted", pyfile, archive) - files_ids = new_files_ids #: also check extracted files + files_ids = new_files_ids #: Also check extracted files if matched: if success: @@ -367,7 +378,7 @@ class ExtractArchive(Hook): self.failed.add(pid) else: - self.logInfo(_("No files found to extract")) + self.log_info(_("No files found to extract")) if not matched or not success and subfolder: try: @@ -388,44 +399,44 @@ class ExtractArchive(Hook): encrypted = False try: - self.logDebug("Password: %s" % (password or "None provided")) - passwords = uniqify([password] + self.getPasswords(False)) if self.getConfig('usepasswordfile') else [password] + self.log_debug("Password: %s" % (password or "None provided")) + passwords = uniqify([password] + self.get_passwords(False)) if self.get_config('usepasswordfile') else [password] for pw in passwords: try: - if self.getConfig('test') or self.repair: + if self.get_config('test') or self.repair: pyfile.setCustomStatus(_("archive testing")) if pw: - self.logDebug("Testing with password: %s" % pw) + self.log_debug("Testing with password: %s" % pw) pyfile.setProgress(0) archive.verify(pw) pyfile.setProgress(100) else: archive.check(pw) - self.addPassword(pw) + self.add_password(pw) break except PasswordError: if not encrypted: - self.logInfo(name, _("Password protected")) + self.log_info(name, _("Password protected")) encrypted = True except CRCError, e: - self.logDebug(name, e) - self.logInfo(name, _("CRC Error")) + self.log_debug(name, e) + self.log_info(name, _("CRC Error")) if self.repair: - self.logWarning(name, _("Repairing...")) + self.log_warning(name, _("Repairing...")) pyfile.setCustomStatus(_("archive repairing")) pyfile.setProgress(0) repaired = archive.repair() pyfile.setProgress(100) - if not repaired and not self.getConfig('keepbroken'): + if not repaired and not self.get_config('keepbroken'): raise CRCError("Archive damaged") - self.addPassword(pw) + self.add_password(pw) break raise CRCError("Archive damaged") @@ -436,33 +447,33 @@ class ExtractArchive(Hook): pyfile.setCustomStatus(_("extracting")) pyfile.setProgress(0) - if not encrypted or not self.getConfig('usepasswordfile'): - self.logDebug("Extracting using password: %s" % (password or "None")) + if not encrypted or not self.get_config('usepasswordfile'): + self.log_debug("Extracting using password: %s" % (password or "None")) archive.extract(password) else: - for pw in filter(None, uniqify([password] + self.getPasswords(False))): + for pw in filter(None, uniqify([password] + self.get_passwords(False))): try: - self.logDebug("Extracting using password: %s" % pw) + self.log_debug("Extracting using password: %s" % pw) archive.extract(pw) - self.addPassword(pw) + self.add_password(pw) break except PasswordError: - self.logDebug("Password was wrong") + self.log_debug("Password was wrong") else: raise PasswordError pyfile.setProgress(100) pyfile.setStatus("processing") - delfiles = archive.getDeleteFiles() - self.logDebug("Would delete: " + ", ".join(delfiles)) + delfiles = archive.get_delete_files() + self.log_debug("Would delete: " + ", ".join(delfiles)) - if self.getConfig('delete'): - self.logInfo(_("Deleting %s files") % len(delfiles)) + if self.get_config('delete'): + self.log_info(_("Deleting %s files") % len(delfiles)) - deltotrash = self.getConfig('deltotrash') + deltotrash = self.get_config('deltotrash') for f in delfiles: file = fs_encode(f) if not os.path.exists(file): @@ -476,31 +487,33 @@ class ExtractArchive(Hook): send2trash.send2trash(file) except NameError: - self.logWarning(_("Unable to move %s to trash: Send2Trash lib not found") % os.path.basename(f)) + self.log_warning(_("Unable to move %s to trash") % os.path.basename(f), + _("Send2Trash lib not found")) except Exception, e: - self.logWarning(_("Unable to move %s to trash: %s") % (os.path.basename(f), e.message)) + self.log_warning(_("Unable to move %s to trash") % os.path.basename(f), + e.message) else: - self.logDebug(_("Successfully moved %s to trash") % os.path.basename(f)) + self.log_info(_("Moved %s to trash") % os.path.basename(f)) - self.logInfo(name, _("Extracting finished")) + self.log_info(name, _("Extracting finished")) extracted_files = archive.files or archive.list() return extracted_files except PasswordError: - self.logError(name, _("Wrong password" if password else "No password found")) + self.log_error(name, _("Wrong password" if password else "No password found")) except CRCError, e: - self.logError(name, _("CRC mismatch"), e) + self.log_error(name, _("CRC mismatch"), e) except ArchiveError, e: - self.logError(name, _("Archive error"), e) + self.log_error(name, _("Archive error"), e) except Exception, e: - self.logError(name, _("Unknown error"), e) - if self.core.debug: + self.log_error(name, _("Unknown error"), e) + if self.pyload.debug: traceback.print_exc() self.manager.dispatchEvent("archive_extract_failed", pyfile, archive) @@ -508,63 +521,63 @@ class ExtractArchive(Hook): raise Exception(_("Extract failed")) + #: Deprecated method, use `get_passwords` instead @Expose - def getPasswords(self, reload=True): - """ List of saved passwords """ + def getPasswords(self, *args, **kwargs): + """ + See `get_passwords` + """ + return self.get_passwords(*args, **kwargs) + + + @Expose + def get_passwords(self, reload=True): + """ + List of saved passwords + """ if reload: - self.reloadPasswords() + self.reload_passwords() return self.passwords - def reloadPasswords(self): + def reload_passwords(self): try: passwords = [] - file = fs_encode(self.getConfig('passwordfile')) + file = fs_encode(self.get_config('passwordfile')) with open(file) as f: for pw in f.read().splitlines(): passwords.append(pw) except IOError, e: - self.logError(e) + self.log_error(e) else: self.passwords = passwords + #: Deprecated method, use `add_password` instead + @Expose + def addPassword(self, *args, **kwargs): + """ + See `add_password` + """ + return self.add_password(*args, **kwargs) + + @Expose - def addPassword(self, password): - """ Adds a password to saved list""" + def add_password(self, password): + """ + Adds a password to saved list + """ try: self.passwords = uniqify([password] + self.passwords) - file = fs_encode(self.getConfig('passwordfile')) + file = fs_encode(self.get_config('passwordfile')) with open(file, "wb") as f: for pw in self.passwords: f.write(pw + '\n') except IOError, e: - self.logError(e) - - - def setPermissions(self, files): - for f in files: - if not os.path.exists(f): - continue - - try: - if self.config['permission']['change_file']: - if os.path.isfile(f): - os.chmod(f, int(self.config['permission']['file'], 8)) - - elif os.path.isdir(f): - os.chmod(f, int(self.config['permission']['folder'], 8)) - - if self.config['permission']['change_dl'] and os.name != "nt": - uid = getpwnam(self.config['permission']['user'])[2] - gid = getgrnam(self.config['permission']['group'])[2] - os.chown(f, uid, gid) - - except Exception, e: - self.logWarning(_("Setting User and Group failed"), e) + self.log_error(e) diff --git a/module/plugins/hooks/FastixRuHook.py b/module/plugins/hooks/FastixRuHook.py index 16e30e93a..3fdb29409 100644 --- a/module/plugins/hooks/FastixRuHook.py +++ b/module/plugins/hooks/FastixRuHook.py @@ -7,21 +7,21 @@ from module.plugins.internal.MultiHook import MultiHook class FastixRuHook(MultiHook): __name__ = "FastixRuHook" __type__ = "hook" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Fastix.ru hook plugin""" __license__ = "GPLv3" __authors__ = [("Massimo Rosamilia", "max@spiritix.eu")] - def getHosters(self): - html = self.getURL("http://fastix.ru/api_v2", + def get_hosters(self): + html = self.load("http://fastix.ru/api_v2", get={'apikey': "5182964c3f8f9a7f0b00000a_kelmFB4n1IrnCDYuIFn2y", 'sub' : "allowed_sources"}) host_list = json_loads(html) diff --git a/module/plugins/hooks/FreeWayMeHook.py b/module/plugins/hooks/FreeWayMeHook.py index baea44540..1380433bf 100644 --- a/module/plugins/hooks/FreeWayMeHook.py +++ b/module/plugins/hooks/FreeWayMeHook.py @@ -6,27 +6,23 @@ from module.plugins.internal.MultiHook import MultiHook class FreeWayMeHook(MultiHook): __name__ = "FreeWayMeHook" __type__ = "hook" - __version__ = "0.15" + __version__ = "0.18" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """FreeWay.me hook plugin""" __license__ = "GPLv3" __authors__ = [("Nicolas Giese", "james@free-way.me")] - def getHosters(self): - # Get account data - if not self.account or not self.account.canUse(): - hostis = self.getURL("https://www.free-way.me/ajax/jd.php", get={"id": 3}).replace("\"", "").strip() - else: - self.logDebug("AccountInfo available - Get HosterList with User Pass") - (user, data) = self.account.selectAccount() - hostis = self.getURL("https://www.free-way.me/ajax/jd.php", get={"id": 3, "user": user, "pass": data['password']}).replace("\"", "").strip() - - self.logDebug("hosters: %s" % hostis) + def get_hosters(self): + user, info = self.account.select() + hostis = self.load("http://www.free-way.bz/ajax/jd.php", + get={'id' : 3, + 'user': user, + 'pass': info['login']['password']}).replace("\"", "") #@TODO: Revert to `https` in 0.4.10 return [x.strip() for x in hostis.split(",") if x.strip()] diff --git a/module/plugins/hooks/HighWayMeHook.py b/module/plugins/hooks/HighWayMeHook.py new file mode 100644 index 000000000..e9e62525d --- /dev/null +++ b/module/plugins/hooks/HighWayMeHook.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +from module.common.json_layer import json_loads +from module.plugins.internal.MultiHook import MultiHook + + +class HighWayMeHook(MultiHook): + __name__ = "HighWayMeHook" + __type__ = "hook" + __version__ = "0.04" + __status__ = "testing" + + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + + __description__ = """High-Way.me hook plugin""" + __license__ = "GPLv3" + __authors__ = [("EvolutionClip", "evolutionclip@live.de")] + + + def get_hosters(self): + json_data = json_loads(self.load("https://high-way.me/api.php", + get={'hoster': 1})) + return [element['name'] for element in json_data['hoster']] diff --git a/module/plugins/hooks/HotFolder.py b/module/plugins/hooks/HotFolder.py index f771cf232..84db4db17 100644 --- a/module/plugins/hooks/HotFolder.py +++ b/module/plugins/hooks/HotFolder.py @@ -7,14 +7,15 @@ import time from shutil import move -from module.plugins.Hook import Hook -from module.utils import fs_encode, save_join +from module.plugins.internal.Addon import Addon +from module.utils import fs_encode, save_join as fs_join -class HotFolder(Hook): +class HotFolder(Addon): __name__ = "HotFolder" __type__ = "hook" - __version__ = "0.14" + __version__ = "0.16" + __status__ = "testing" __config__ = [("folder" , "str" , "Folder to observe" , "container"), ("watch_file", "bool", "Observe link file" , False ), @@ -26,20 +27,19 @@ class HotFolder(Hook): __authors__ = [("RaNaN", "RaNaN@pyload.de")] - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 + def init(self): self.interval = 30 def periodical(self): - folder = fs_encode(self.getConfig('folder')) - file = fs_encode(self.getConfig('file')) + folder = fs_encode(self.get_config('folder')) + file = fs_encode(self.get_config('file')) try: if not os.path.isdir(os.path.join(folder, "finished")): os.makedirs(os.path.join(folder, "finished")) - if self.getConfig('watch_file'): + if self.get_config('watch_file'): with open(file, "a+") as f: f.seek(0) content = f.read().strip() @@ -50,10 +50,10 @@ class HotFolder(Hook): name = "%s_%s.txt" % (file, time.strftime("%H-%M-%S_%d%b%Y")) - with open(save_join(folder, "finished", name), "wb") as f: + with open(fs_join(folder, "finished", name), "wb") as f: f.write(content) - self.core.api.addPackage(f.name, [f.name], 1) + self.pyload.api.addPackage(f.name, [f.name], 1) for f in os.listdir(folder): path = os.path.join(folder, f) @@ -61,11 +61,11 @@ class HotFolder(Hook): if not os.path.isfile(path) or f.endswith("~") or f.startswith("#") or f.startswith("."): continue - newpath = os.path.join(folder, "finished", f if self.getConfig('keep') else "tmp_" + f) + newpath = os.path.join(folder, "finished", f if self.get_config('keep') else "tmp_" + f) move(path, newpath) - self.logInfo(_("Added %s from HotFolder") % f) - self.core.api.addPackage(f, [newpath], 1) + self.log_info(_("Added %s from HotFolder") % f) + self.pyload.api.addPackage(f, [newpath], 1) except (IOError, OSError), e: - self.logError(e) + self.log_error(e) diff --git a/module/plugins/hooks/IRCInterface.py b/module/plugins/hooks/IRCInterface.py index 33fde3d20..08b1bad0c 100644 --- a/module/plugins/hooks/IRCInterface.py +++ b/module/plugins/hooks/IRCInterface.py @@ -11,42 +11,39 @@ from select import select from threading import Thread from module.Api import PackageDoesNotExists, FileDoesNotExists -from module.network.RequestFactory import getURL -from module.plugins.Hook import Hook +from module.plugins.internal.Addon import Addon from module.utils import formatSize -class IRCInterface(Thread, Hook): +class IRCInterface(Thread, Addon): __name__ = "IRCInterface" __type__ = "hook" - __version__ = "0.13" - - __config__ = [("host", "str", "IRC-Server Address", "Enter your server here!"), - ("port", "int", "IRC-Server Port", 6667), - ("ident", "str", "Clients ident", "pyload-irc"), - ("realname", "str", "Realname", "pyload-irc"), - ("ssl", "bool", "Use SSL", False), - ("nick", "str", "Nickname the Client will take", "pyLoad-IRC"), - ("owner", "str", "Nickname the Client will accept commands from", "Enter your nick here!"), - ("info_file", "bool", "Inform about every file finished", False), - ("info_pack", "bool", "Inform about every package finished", True), - ("captcha", "bool", "Send captcha requests", True)] + __version__ = "0.15" + __status__ = "testing" + + __config__ = [("host" , "str" , "IRC-Server Address" , "Enter your server here!"), + ("port" , "int" , "IRC-Server Port" , 6667 ), + ("ident" , "str" , "Clients ident" , "pyload-irc" ), + ("realname" , "str" , "Realname" , "pyload-irc" ), + ("ssl" , "bool", "Use SSL" , False ), + ("nick" , "str" , "Nickname the Client will take" , "pyLoad-IRC" ), + ("owner" , "str" , "Nickname the Client will accept commands from", "Enter your nick here!" ), + ("info_file", "bool", "Inform about every file finished" , False ), + ("info_pack", "bool", "Inform about every package finished" , True ), + ("captcha" , "bool", "Send captcha requests" , True )] __description__ = """Connect to irc and let owner perform different tasks""" __license__ = "GPLv3" __authors__ = [("Jeix", "Jeix@hasnomail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - def __init__(self, core, manager): Thread.__init__(self) - Hook.__init__(self, core, manager) - self.setDaemon(True) + Addon.__init__(self, core, manager) + self.set_daemon(True) - def coreReady(self): + def activate(self): self.abort = False self.more = [] self.new_package = {} @@ -54,30 +51,30 @@ class IRCInterface(Thread, Hook): self.start() - def packageFinished(self, pypack): + def package_finished(self, pypack): try: - if self.getConfig('info_pack'): + if self.get_config('info_pack'): self.response(_("Package finished: %s") % pypack.name) except Exception: pass - def downloadFinished(self, pyfile): + def download_finished(self, pyfile): try: - if self.getConfig('info_file'): + if self.get_config('info_file'): self.response( - _("Download finished: %(name)s @ %(plugin)s ") % {"name": pyfile.name, "plugin": pyfile.pluginname}) + _("Download finished: %(name)s @ %(plugin)s ") % {'name': pyfile.name, 'plugin': pyfile.pluginname}) except Exception: pass - def newCaptchaTask(self, task): - if self.getConfig('captcha') and task.isTextual(): + def captcha_task(self, task): + if self.get_config('captcha') and task.isTextual(): task.handler.append(self) task.setWaiting(60) - html = getURL("http://www.freeimagehosting.net/upload.php", - post={"attached": (pycurl.FORM_FILE, task.captchaFile)}, multipart=True) + html = self.load("http://www.freeimagehosting.net/upload.php", + post={'attached': (pycurl.FORM_FILE, task.captchaFile)}) url = re.search(r"\[img\]([^\[]+)\[/img\]\[/url\]", html).group(1) self.response(_("New Captcha Request: %s") % url) @@ -85,22 +82,22 @@ class IRCInterface(Thread, Hook): def run(self): - # connect to IRC etc. + #: Connect to IRC etc. self.sock = socket.socket() - host = self.getConfig('host') - self.sock.connect((host, self.getConfig('port'))) + host = self.get_config('host') + self.sock.connect((host, self.get_config('port'))) - if self.getConfig('ssl'): + if self.get_config('ssl'): self.sock = ssl.wrap_socket(self.sock, cert_reqs=ssl.CERT_NONE) #@TODO: support certificate - nick = self.getConfig('nick') + nick = self.get_config('nick') self.sock.send("NICK %s\r\n" % nick) self.sock.send("USER %s %s bla :%s\r\n" % (nick, host, nick)) - for t in self.getConfig('owner').split(): + for t in self.get_config('owner').split(): if t.strip().startswith("#"): self.sock.send("JOIN %s\r\n" % t.strip()) - self.logInfo(_("Connected to"), host) - self.logInfo(_("Switching to listening mode!")) + self.log_info(_("Connected to"), host) + self.log_info(_("Switching to listening mode!")) try: self.main_loop() @@ -140,36 +137,36 @@ class IRCInterface(Thread, Hook): continue msg = { - "origin": msg[0][1:], - "action": msg[1], - "target": msg[2], - "text": msg[3][1:] + 'origin': msg[0][1:], + 'action': msg[1], + 'target': msg[2], + 'text': msg[3][1:] } self.handle_events(msg) def handle_events(self, msg): - if not msg['origin'].split("!", 1)[0] in self.getConfig('owner').split(): + if not msg['origin'].split("!", 1)[0] in self.get_config('owner').split(): return - if msg['target'].split("!", 1)[0] != self.getConfig('nick'): + if msg['target'].split("!", 1)[0] is not self.get_config('nick'): return if msg['action'] != "PRIVMSG": return - # HANDLE CTCP ANTI FLOOD/BOT PROTECTION + #: HANDLE CTCP ANTI FLOOD/BOT PROTECTION if msg['text'] == "\x01VERSION\x01": - self.logDebug("Sending CTCP VERSION") + self.log_debug("Sending CTCP VERSION") self.sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) return elif msg['text'] == "\x01TIME\x01": - self.logDebug("Sending CTCP TIME") + self.log_debug("Sending CTCP TIME") self.sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time())) return elif msg['text'] == "\x01LAG\x01": - self.logDebug("Received CTCP LAG") #: don't know how to answer + self.log_debug("Received CTCP LAG") #: don't know how to answer return trigger = "pass" @@ -189,12 +186,12 @@ class IRCInterface(Thread, Hook): for line in res: self.response(line, msg['origin']) except Exception, e: - self.logError(e) + self.log_error(e) def response(self, msg, origin=""): if origin == "": - for t in self.getConfig('owner').split(): + for t in self.get_config('owner').split(): self.sock.send("PRIVMSG %s :%s\r\n" % (t.strip(), msg)) else: self.sock.send("PRIVMSG %s :%s\r\n" % (origin.split("!", 1)[0], msg)) @@ -207,7 +204,7 @@ class IRCInterface(Thread, Hook): def event_status(self, args): - downloads = self.core.api.statusDownloads() + downloads = self.pyload.api.statusDownloads() if not downloads: return ["INFO: There are no active downloads currently."] @@ -233,7 +230,7 @@ class IRCInterface(Thread, Hook): def event_queue(self, args): - ps = self.core.api.getQueueData() + ps = self.pyload.api.getQueueData() if not ps: return ["INFO: There are no packages in queue."] @@ -246,7 +243,7 @@ class IRCInterface(Thread, Hook): def event_collector(self, args): - ps = self.core.api.getCollectorData() + ps = self.pyload.api.getCollectorData() if not ps: return ["INFO: No packages in collector!"] @@ -263,7 +260,7 @@ class IRCInterface(Thread, Hook): info = None try: - info = self.core.api.getFileData(int(args[0])) + info = self.pyload.api.getFileData(int(args[0])) except FileDoesNotExists: return ["ERROR: Link doesn't exists."] @@ -278,7 +275,7 @@ class IRCInterface(Thread, Hook): lines = [] pack = None try: - pack = self.core.api.getPackageData(int(args[0])) + pack = self.pyload.api.getPackageData(int(args[0])) except PackageDoesNotExists: return ["ERROR: Package doesn't exists."] @@ -315,12 +312,12 @@ class IRCInterface(Thread, Hook): def event_start(self, args): - self.core.api.unpauseServer() + self.pyload.api.unpauseServer() return ["INFO: Starting downloads."] def event_stop(self, args): - self.core.api.pauseServer() + self.pyload.api.pauseServer() return ["INFO: No new downloads will be started."] @@ -336,17 +333,17 @@ class IRCInterface(Thread, Hook): count_failed = 0 try: id = int(pack) - pack = self.core.api.getPackageData(id) + pack = self.pyload.api.getPackageData(id) if not pack: return ["ERROR: Package doesn't exists."] - #TODO add links + #@TODO: add links return ["INFO: Added %d links to Package %s [#%d]" % (len(links), pack['name'], id)] except Exception: - # create new package - id = self.core.api.addPackage(pack, links, 1) + #: Create new package + id = self.pyload.api.addPackage(pack, links, 1) return ["INFO: Created new Package %s [#%d] with %d links." % (pack, id, len(links))] @@ -355,11 +352,11 @@ class IRCInterface(Thread, Hook): return ["ERROR: Use del command like this: del -p|-l <id> [...] (-p indicates that the ids are from packages, -l indicates that the ids are from links)"] if args[0] == "-p": - ret = self.core.api.deletePackages(map(int, args[1:])) + ret = self.pyload.api.deletePackages(map(int, args[1:])) return ["INFO: Deleted %d packages!" % len(args[1:])] elif args[0] == "-l": - ret = self.core.api.delLinks(map(int, args[1:])) + ret = self.pyload.api.delLinks(map(int, args[1:])) return ["INFO: Deleted %d links!" % len(args[1:])] else: @@ -372,11 +369,11 @@ class IRCInterface(Thread, Hook): id = int(args[0]) try: - info = self.core.api.getPackageInfo(id) + info = self.pyload.api.getPackageInfo(id) except PackageDoesNotExists: return ["ERROR: Package #%d does not exist." % id] - self.core.api.pushToQueue(id) + self.pyload.api.pushToQueue(id) return ["INFO: Pushed package #%d to queue." % id] @@ -385,19 +382,21 @@ class IRCInterface(Thread, Hook): return ["ERROR: Pull package from queue like this: pull <package id>."] id = int(args[0]) - if not self.core.api.getPackageData(id): + if not self.pyload.api.getPackageData(id): return ["ERROR: Package #%d does not exist." % id] - self.core.api.pullFromQueue(id) + self.pyload.api.pullFromQueue(id) return ["INFO: Pulled package #%d from queue to collector." % id] def event_c(self, args): - """ captcha answer """ + """ + Captcha answer + """ if not args: return ["ERROR: Captcha ID missing."] - task = self.core.captchaManager.getTaskByID(args[0]) + task = self.pyload.captchaManager.getTaskByID(args[0]) if not task: return ["ERROR: Captcha Task with ID %s does not exists." % args[0]] diff --git a/module/plugins/hooks/ImageTyperz.py b/module/plugins/hooks/ImageTyperz.py index f1fcacb71..42ab99027 100644 --- a/module/plugins/hooks/ImageTyperz.py +++ b/module/plugins/hooks/ImageTyperz.py @@ -7,8 +7,8 @@ import re from base64 import b64encode -from module.network.RequestFactory import getURL, getRequest -from module.plugins.Hook import Hook, threaded +from module.network.RequestFactory import getRequest as get_request +from module.plugins.internal.Hook import Hook, threaded class ImageTyperzException(Exception): @@ -17,7 +17,7 @@ class ImageTyperzException(Exception): self.err = err - def getCode(self): + def get_code(self): return self.err @@ -32,11 +32,12 @@ class ImageTyperzException(Exception): class ImageTyperz(Hook): __name__ = "ImageTyperz" __type__ = "hook" - __version__ = "0.06" + __version__ = "0.08" + __status__ = "testing" - __config__ = [("username", "str", "Username", ""), - ("passkey", "password", "Password", ""), - ("force", "bool", "Force IT even if client is connected", False)] + __config__ = [("username" , "str" , "Username" , "" ), + ("password" , "password", "Password" , "" ), + ("check_client", "bool" , "Don't use if client is connected", True)] __description__ = """Send captchas to ImageTyperz.com""" __license__ = "GPLv3" @@ -44,22 +45,16 @@ class ImageTyperz(Hook): ("zoidberg", "zoidberg@mujmail.cz")] - interval = 0 #@TODO: Remove in 0.4.10 - SUBMIT_URL = "http://captchatypers.com/Forms/UploadFileAndGetTextNEW.ashx" RESPOND_URL = "http://captchatypers.com/Forms/SetBadImage.ashx" GETCREDITS_URL = "http://captchatypers.com/Forms/RequestBalance.ashx" - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def getCredits(self): - res = getURL(self.GETCREDITS_URL, + def get_credits(self): + res = self.load(self.GETCREDITS_URL, post={'action': "REQUESTBALANCE", - 'username': self.getConfig('username'), - 'password': self.getConfig('passkey')}) + 'username': self.get_config('username'), + 'password': self.get_config('password')}) if res.startswith('ERROR'): raise ImageTyperzException(res) @@ -69,18 +64,18 @@ class ImageTyperz(Hook): except Exception: raise ImageTyperzException("Invalid response") - self.logInfo(_("Account balance: $%s left") % res) + self.log_info(_("Account balance: $%s left") % res) return balance def submit(self, captcha, captchaType="file", match=None): - req = getRequest() - #raise timeout threshold + req = get_request() + #: Raise timeout threshold req.c.setopt(pycurl.LOW_SPEED_TIME, 80) try: #@NOTE: Workaround multipart-post bug in HTTPRequest.py - if re.match("^\w*$", self.getConfig('passkey')): + if re.match("^\w*$", self.get_config('password')): multipart = True data = (pycurl.FORM_FILE, captcha) else: @@ -89,11 +84,12 @@ class ImageTyperz(Hook): data = f.read() data = b64encode(data) - res = req.load(self.SUBMIT_URL, - post={'action': "UPLOADCAPTCHA", - 'username': self.getConfig('username'), - 'password': self.getConfig('passkey'), "file": data}, - multipart=multipart) + res = self.load(self.SUBMIT_URL, + post={'action': "UPLOADCAPTCHA", + 'username': self.get_config('username'), + 'password': self.get_config('password'), 'file': data}, + multipart=multipart, + req=req) finally: req.close() @@ -109,50 +105,50 @@ class ImageTyperz(Hook): return ticket, result - def newCaptchaTask(self, task): + def captcha_task(self, task): if "service" in task.data: return False if not task.isTextual(): return False - if not self.getConfig('username') or not self.getConfig('passkey'): + if not self.get_config('username') or not self.get_config('password'): return False - if self.core.isClientConnected() and not self.getConfig('force'): + if self.pyload.isClientConnected() and self.get_config('check_client'): return False - if self.getCredits() > 0: + if self.get_credits() > 0: task.handler.append(self) task.data['service'] = self.__name__ task.setWaiting(100) - self._processCaptcha(task) + self._process_captcha(task) else: - self.logInfo(_("Your %s account has not enough credits") % self.__name__) + self.log_info(_("Your %s account has not enough credits") % self.__name__) - def captchaInvalid(self, task): - if task.data['service'] == self.__name__ and "ticket" in task.data: - res = getURL(self.RESPOND_URL, + def captcha_invalid(self, task): + if task.data['service'] is self.__name__ and "ticket" in task.data: + res = self.load(self.RESPOND_URL, post={'action': "SETBADIMAGE", - 'username': self.getConfig('username'), - 'password': self.getConfig('passkey'), + 'username': self.get_config('username'), + 'password': self.get_config('password'), 'imageid': task.data['ticket']}) if res == "SUCCESS": - self.logInfo(_("Bad captcha solution received, requested refund")) + self.log_info(_("Bad captcha solution received, requested refund")) else: - self.logError(_("Bad captcha solution received, refund request failed"), res) + self.log_error(_("Bad captcha solution received, refund request failed"), res) @threaded - def _processCaptcha(self, task): + def _process_captcha(self, task): c = task.captchaFile try: ticket, result = self.submit(c) except ImageTyperzException, e: - task.error = e.getCode() + task.error = e.get_code() return task.data['ticket'] = ticket diff --git a/module/plugins/hooks/JustPremium.py b/module/plugins/hooks/JustPremium.py index f66747f82..69a6a851b 100644 --- a/module/plugins/hooks/JustPremium.py +++ b/module/plugins/hooks/JustPremium.py @@ -2,13 +2,14 @@ import re -from module.plugins.Hook import Hook +from module.plugins.internal.Addon import Addon -class JustPremium(Hook): +class JustPremium(Addon): __name__ = "JustPremium" __type__ = "hook" - __version__ = "0.22" + __version__ = "0.24" + __status__ = "testing" __config__ = [("excluded", "str", "Exclude hosters (comma separated)", ""), ("included", "str", "Include hosters (comma separated)", "")] @@ -20,28 +21,24 @@ class JustPremium(Hook): ("immenz" , "immenz@gmx.net" )] - interval = 0 #@TODO: Remove in 0.4.10 + def init(self): + self.event_map = {'linksAdded': "links_added"} - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - self.event_list = ["linksAdded"] + def links_added(self, links, pid): + hosterdict = self.pyload.pluginManager.hosterPlugins + linkdict = self.pyload.api.checkURLs(links) - - def linksAdded(self, links, pid): - hosterdict = self.core.pluginManager.hosterPlugins - linkdict = self.core.api.checkURLs(links) - - premiumplugins = set(account.type for account in self.core.api.getAccounts(False) \ + premiumplugins = set(account.type for account in self.pyload.api.getAccounts(False) \ if account.valid and account.premium) - multihosters = set(hoster for hoster in self.core.pluginManager.hosterPlugins \ + multihosters = set(hoster for hoster in self.pyload.pluginManager.hosterPlugins \ if 'new_name' in hosterdict[hoster] \ and hosterdict[hoster]['new_name'] in premiumplugins) excluded = map(lambda domain: "".join(part.capitalize() for part in re.split(r'(\.|\d+)', domain) if part != '.'), - self.getConfig('excluded').replace(' ', '').replace(',', '|').replace(';', '|').split('|')) + self.get_config('excluded').replace(' ', '').replace(',', '|').replace(';', '|').split('|')) included = map(lambda domain: "".join(part.capitalize() for part in re.split(r'(\.|\d+)', domain) if part != '.'), - self.getConfig('included').replace(' ', '').replace(',', '|').replace(';', '|').split('|')) + self.get_config('included').replace(' ', '').replace(',', '|').replace(';', '|').split('|')) hosterlist = (premiumplugins | multihosters).union(excluded).difference(included) @@ -50,7 +47,7 @@ class JustPremium(Hook): return for pluginname in set(linkdict.keys()) - hosterlist: - self.logInfo(_("Remove links of plugin: %s") % pluginname) + self.log_info(_("Remove links of plugin: %s") % pluginname) for link in linkdict[pluginname]: - self.logDebug("Remove link: %s" % link) + self.log_debug("Remove link: %s" % link) links.remove(link) diff --git a/module/plugins/hooks/LinkdecrypterComHook.py b/module/plugins/hooks/LinkdecrypterComHook.py index b2eaece62..6930afdb5 100644 --- a/module/plugins/hooks/LinkdecrypterComHook.py +++ b/module/plugins/hooks/LinkdecrypterComHook.py @@ -8,7 +8,8 @@ from module.plugins.internal.MultiHook import MultiHook class LinkdecrypterComHook(MultiHook): __name__ = "LinkdecrypterComHook" __type__ = "hook" - __version__ = "1.06" + __version__ = "1.07" + __status__ = "testing" __config__ = [("activated" , "bool" , "Activated" , True ), ("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), @@ -21,9 +22,9 @@ class LinkdecrypterComHook(MultiHook): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - def getHosters(self): + def get_hosters(self): list = re.search(r'>Supported\(\d+\)</b>: <i>(.[\w.\-, ]+)', - self.getURL("http://linkdecrypter.com/", decode=True).replace("(g)", "")).group(1).split(', ') + self.load("http://linkdecrypter.com/").replace("(g)", "")).group(1).split(', ') try: list.remove("download.serienjunkies.org") except ValueError: diff --git a/module/plugins/hooks/LinksnappyComHook.py b/module/plugins/hooks/LinksnappyComHook.py index 72282575b..e46e480d6 100644 --- a/module/plugins/hooks/LinksnappyComHook.py +++ b/module/plugins/hooks/LinksnappyComHook.py @@ -7,21 +7,21 @@ from module.plugins.internal.MultiHook import MultiHook class LinksnappyComHook(MultiHook): __name__ = "LinksnappyComHook" __type__ = "hook" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Linksnappy.com hook plugin""" __license__ = "GPLv3" __authors__ = [("stickell", "l.stickell@yahoo.it")] - def getHosters(self): - json_data = self.getURL("http://gen.linksnappy.com/lseAPI.php", get={'act': "FILEHOSTS"}) + def get_hosters(self): + json_data = self.load("http://gen.linksnappy.com/lseAPI.php", get={'act': "FILEHOSTS"}) json_data = json_loads(json_data) return json_data['return'].keys() diff --git a/module/plugins/hooks/MegaDebridEuHook.py b/module/plugins/hooks/MegaDebridEuHook.py index 0de7b4dcf..04f0be86f 100644 --- a/module/plugins/hooks/MegaDebridEuHook.py +++ b/module/plugins/hooks/MegaDebridEuHook.py @@ -7,27 +7,27 @@ from module.plugins.internal.MultiHook import MultiHook class MegaDebridEuHook(MultiHook): __name__ = "MegaDebridEuHook" __type__ = "hook" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Mega-debrid.eu hook plugin""" __license__ = "GPLv3" __authors__ = [("D.Ducatel", "dducatel@je-geek.fr")] - def getHosters(self): - reponse = self.getURL("http://www.mega-debrid.eu/api.php", get={'action': "getHosters"}) + def get_hosters(self): + reponse = self.load("http://www.mega-debrid.eu/api.php", get={'action': "getHosters"}) json_data = json_loads(reponse) if json_data['response_code'] == "ok": host_list = [element[0] for element in json_data['hosters']] else: - self.logError(_("Unable to retrieve hoster list")) - host_list = list() + self.log_error(_("Unable to retrieve hoster list")) + host_list = [] return host_list diff --git a/module/plugins/hooks/MegaRapidoNetHook.py b/module/plugins/hooks/MegaRapidoNetHook.py index e113b305e..4956427ff 100644 --- a/module/plugins/hooks/MegaRapidoNetHook.py +++ b/module/plugins/hooks/MegaRapidoNetHook.py @@ -8,7 +8,8 @@ from module.plugins.internal.MultiHook import MultiHook class MegaRapidoNetHook(MultiHook): __name__ = "MegaRapidoNetHook" __type__ = "hook" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), @@ -20,15 +21,15 @@ class MegaRapidoNetHook(MultiHook): __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")] - def getHosters(self): - hosters = {'1fichier' : [],#leave it there are so many possible addresses? + def get_hosters(self): + hosters = {'1fichier' : [], # leave it there are so many possible addresses? '1st-files' : ['1st-files.com'], '2shared' : ['2shared.com'], '4shared' : ['4shared.com', '4shared-china.com'], 'asfile' : ['http://asfile.com/'], 'bitshare' : ['bitshare.com'], 'brupload' : ['brupload.net'], - 'crocko' : ['crocko.com','easy-share.com'], + 'crocko' : ['crocko.com', 'easy-share.com'], 'dailymotion' : ['dailymotion.com'], 'depfile' : ['depfile.com'], 'depositfiles': ['depositfiles.com', 'dfiles.eu'], @@ -38,12 +39,12 @@ class MegaRapidoNetHook(MultiHook): 'extmatrix' : ['extmatrix.com'], 'facebook' : [], 'file4go' : ['file4go.com'], - 'filecloud' : ['filecloud.io','ifile.it','mihd.net'], + 'filecloud' : ['filecloud.io', 'ifile.it', 'mihd.net'], 'filefactory' : ['filefactory.com'], 'fileom' : ['fileom.com'], 'fileparadox' : ['fileparadox.in'], 'filepost' : ['filepost.com', 'fp.io'], - 'filerio' : ['filerio.in','filerio.com','filekeen.com'], + 'filerio' : ['filerio.in', 'filerio.com', 'filekeen.com'], 'filesflash' : ['filesflash.com'], 'firedrive' : ['firedrive.com', 'putlocker.com'], 'flashx' : [], @@ -51,7 +52,7 @@ class MegaRapidoNetHook(MultiHook): 'gigasize' : ['gigasize.com'], 'hipfile' : ['hipfile.com'], 'junocloud' : ['junocloud.me'], - 'letitbit' : ['letitbit.net','shareflare.net'], + 'letitbit' : ['letitbit.net', 'shareflare.net'], 'mediafire' : ['mediafire.com'], 'mega' : ['mega.co.nz'], 'megashares' : ['megashares.com'], @@ -75,7 +76,7 @@ class MegaRapidoNetHook(MultiHook): hoster_list = [] - for item in hosters.itervalues(): + for item in hosters.values(): hoster_list.extend(item) return hoster_list diff --git a/module/plugins/hooks/MergeFiles.py b/module/plugins/hooks/MergeFiles.py index 941938920..a76a578bf 100644 --- a/module/plugins/hooks/MergeFiles.py +++ b/module/plugins/hooks/MergeFiles.py @@ -6,14 +6,15 @@ import os import re import traceback -from module.plugins.Hook import Hook, threaded -from module.utils import save_join +from module.plugins.internal.Addon import Addon, threaded +from module.utils import save_join as fs_join -class MergeFiles(Hook): +class MergeFiles(Addon): __name__ = "MergeFiles" __type__ = "hook" - __version__ = "0.14" + __version__ = "0.16" + __status__ = "testing" __config__ = [("activated", "bool", "Activated", True)] @@ -22,20 +23,14 @@ class MergeFiles(Hook): __authors__ = [("and9000", "me@has-no-mail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - BUFFER_SIZE = 4096 - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - @threaded - def packageFinished(self, pack): + def package_finished(self, pack): files = {} fid_dict = {} - for fid, data in pack.getChildren().iteritems(): + for fid, data in pack.getChildren().items(): if re.search("\.\d{3}$", data['name']): if data['name'][:-4] not in files: files[data['name'][:-4]] = [] @@ -43,24 +38,24 @@ class MergeFiles(Hook): files[data['name'][:-4]].sort() fid_dict[data['name']] = fid - download_folder = self.config['general']['download_folder'] + download_folder = self.pyload.config.get("general", "download_folder") - if self.config['general']['folder_per_package']: - download_folder = save_join(download_folder, pack.folder) + if self.pyload.config.get("general", "folder_per_package"): + download_folder = fs_join(download_folder, pack.folder) - for name, file_list in files.iteritems(): - self.logInfo(_("Starting merging of"), name) + for name, file_list in files.items(): + self.log_info(_("Starting merging of"), name) - with open(save_join(download_folder, name), "wb") as final_file: + with open(fs_join(download_folder, name), "wb") as final_file: for splitted_file in file_list: - self.logDebug("Merging part", splitted_file) + self.log_debug("Merging part", splitted_file) - pyfile = self.core.files.getFile(fid_dict[splitted_file]) + pyfile = self.pyload.files.getFile(fid_dict[splitted_file]) pyfile.setStatus("processing") try: - with open(save_join(download_folder, splitted_file), "rb") as s_file: + with open(fs_join(download_folder, splitted_file), "rb") as s_file: size_written = 0 s_file_size = int(os.path.getsize(os.path.join(download_folder, splitted_file))) while True: @@ -71,7 +66,7 @@ class MergeFiles(Hook): pyfile.setProgress((size_written * 100) / s_file_size) else: break - self.logDebug("Finished merging part", splitted_file) + self.log_debug("Finished merging part", splitted_file) except Exception, e: traceback.print_exc() @@ -81,4 +76,4 @@ class MergeFiles(Hook): pyfile.setStatus("finished") pyfile.release() - self.logInfo(_("Finished merging of"), name) + self.log_info(_("Finished merging of"), name) diff --git a/module/plugins/hooks/MultiHome.py b/module/plugins/hooks/MultiHome.py index a26d139c0..929ab9a25 100644 --- a/module/plugins/hooks/MultiHome.py +++ b/module/plugins/hooks/MultiHome.py @@ -2,64 +2,61 @@ import time -from module.plugins.Hook import Hook +from module.plugins.internal.Addon import Addon -class MultiHome(Hook): +class MultiHome(Addon): __name__ = "MultiHome" __type__ = "hook" - __version__ = "0.12" + __version__ = "0.14" + __status__ = "testing" __config__ = [("interfaces", "str", "Interfaces", "None")] - __description__ = """Ip address changer""" + __description__ = """IP address changer""" __license__ = "GPLv3" __authors__ = [("mkaay", "mkaay@mkaay.de")] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 + def init(self): self.register = {} self.interfaces = [] - self.parseInterfaces(self.getConfig('interfaces').split(";")) + self.parse_interfaces(self.get_config('interfaces').split(";")) if not self.interfaces: - self.parseInterfaces([self.config['download']['interface']]) - self.setConfig("interfaces", self.toConfig()) + self.parse_interfaces([self.pyload.config.get("download", "interface")]) + self.set_config("interfaces", self.to_config()) - def toConfig(self): + def to_config(self): return ";".join(i.adress for i in self.interfaces) - def parseInterfaces(self, interfaces): + def parse_interfaces(self, interfaces): for interface in interfaces: if not interface or str(interface).lower() == "none": continue self.interfaces.append(Interface(interface)) - def coreReady(self): - requestFactory = self.core.requestFactory + def activate(self): + requestFactory = self.pyload.requestFactory oldGetRequest = requestFactory.getRequest - def getRequest(pluginName, account=None): - iface = self.bestInterface(pluginName, account) + def get_request(pluginName, account=None): + iface = self.best_interface(pluginName, account) if iface: iface.useFor(pluginName, account) requestFactory.iface = lambda: iface.adress - self.logDebug("Using address", iface.adress) + self.log_debug("Using address", iface.adress) return oldGetRequest(pluginName, account) - requestFactory.getRequest = getRequest + requestFactory.getRequest = get_request - def bestInterface(self, pluginName, account): + def best_interface(self, pluginName, account): best = None for interface in self.interfaces: if not best or interface.lastPluginAccess(pluginName, account) < best.lastPluginAccess(pluginName, account): @@ -74,13 +71,13 @@ class Interface(object): self.history = {} - def lastPluginAccess(self, pluginName, account): + def last_plugin_access(self, pluginName, account): if (pluginName, account) in self.history: return self.history[(pluginName, account)] return 0 - def useFor(self, pluginName, account): + def use_for(self, pluginName, account): self.history[(pluginName, account)] = time.time() diff --git a/module/plugins/hooks/MultihostersComHook.py b/module/plugins/hooks/MultihostersComHook.py index 7b5e49c49..ec1cf9c85 100644 --- a/module/plugins/hooks/MultihostersComHook.py +++ b/module/plugins/hooks/MultihostersComHook.py @@ -6,12 +6,13 @@ from module.plugins.hooks.ZeveraComHook import ZeveraComHook class MultihostersComHook(ZeveraComHook): __name__ = "MultihostersComHook" __type__ = "hook" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" - __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed", "bool" , "Revert to standard download if download fails", False), - ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Multihosters.com hook plugin""" __license__ = "GPLv3" diff --git a/module/plugins/hooks/MultishareCzHook.py b/module/plugins/hooks/MultishareCzHook.py index 6052b7673..30f1e21b5 100644 --- a/module/plugins/hooks/MultishareCzHook.py +++ b/module/plugins/hooks/MultishareCzHook.py @@ -8,13 +8,13 @@ from module.plugins.internal.MultiHook import MultiHook class MultishareCzHook(MultiHook): __name__ = "MultishareCzHook" __type__ = "hook" - __version__ = "0.07" + __version__ = "0.08" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """MultiShare.cz hook plugin""" __license__ = "GPLv3" @@ -24,6 +24,6 @@ class MultishareCzHook(MultiHook): HOSTER_PATTERN = r'<img class="logo-shareserveru"[^>]*?alt="(.+?)"></td>\s*<td class="stav">[^>]*?alt="OK"' - def getHosters(self): - html = self.getURL("http://www.multishare.cz/monitoring/") + def get_hosters(self): + html = self.load("http://www.multishare.cz/monitoring/") return re.findall(self.HOSTER_PATTERN, html) diff --git a/module/plugins/hooks/MyfastfileComHook.py b/module/plugins/hooks/MyfastfileComHook.py index 20a1cfac2..1eedd9238 100644 --- a/module/plugins/hooks/MyfastfileComHook.py +++ b/module/plugins/hooks/MyfastfileComHook.py @@ -7,22 +7,22 @@ from module.plugins.internal.MultiHook import MultiHook class MyfastfileComHook(MultiHook): __name__ = "MyfastfileComHook" __type__ = "hook" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Myfastfile.com hook plugin""" __license__ = "GPLv3" __authors__ = [("stickell", "l.stickell@yahoo.it")] - def getHosters(self): - json_data = self.getURL("http://myfastfile.com/api.php", get={'hosts': ""}, decode=True) - self.logDebug("JSON data", json_data) + def get_hosters(self): + json_data = self.load("http://myfastfile.com/api.php", get={'hosts': ""}) + self.log_debug("JSON data", json_data) json_data = json_loads(json_data) return json_data['hosts'] diff --git a/module/plugins/hooks/NoPremiumPlHook.py b/module/plugins/hooks/NoPremiumPlHook.py index b5a007ff9..7dbdf6a68 100644 --- a/module/plugins/hooks/NoPremiumPlHook.py +++ b/module/plugins/hooks/NoPremiumPlHook.py @@ -7,23 +7,23 @@ from module.plugins.internal.MultiHook import MultiHook class NoPremiumPlHook(MultiHook): __name__ = "NoPremiumPlHook" __type__ = "hook" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """NoPremium.pl hook plugin""" __license__ = "GPLv3" __authors__ = [("goddie", "dev@nopremium.pl")] - def getHosters(self): - hostings = json_loads(self.getURL("https://www.nopremium.pl/clipboard.php?json=3").strip()) - hostings_domains = [domain for row in hostings for domain in row["domains"] if row["sdownload"] == "0"] + def get_hosters(self): + hostings = json_loads(self.load("https://www.nopremium.pl/clipboard.php?json=3").strip()) + hostings_domains = [domain for row in hostings for domain in row['domains'] if row['sdownload'] == "0"] - self.logDebug(hostings_domains) + self.log_debug(hostings_domains) return hostings_domains diff --git a/module/plugins/hooks/OverLoadMeHook.py b/module/plugins/hooks/OverLoadMeHook.py index d608a2ecd..5398fc17d 100644 --- a/module/plugins/hooks/OverLoadMeHook.py +++ b/module/plugins/hooks/OverLoadMeHook.py @@ -6,24 +6,20 @@ from module.plugins.internal.MultiHook import MultiHook class OverLoadMeHook(MultiHook): __name__ = "OverLoadMeHook" __type__ = "hook" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 ), - ("ssl" , "bool" , "Use HTTPS" , True )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Over-Load.me hook plugin""" __license__ = "GPLv3" __authors__ = [("marley", "marley@over-load.me")] - def getHosters(self): - https = "https" if self.getConfig('ssl') else "http" - html = self.getURL(https + "://api.over-load.me/hoster.php", - get={'auth': "0001-cb1f24dadb3aa487bda5afd3b76298935329be7700cd7-5329be77-00cf-1ca0135f"}).replace("\"", "").strip() - self.logDebug("Hosterlist", html) - + def get_hosters(self): + html = self.load("https://api.over-load.me/hoster.php", + get={'auth': "0001-cb1f24dadb3aa487bda5afd3b76298935329be7700cd7-5329be77-00cf-1ca0135f"}).replace("\"", "").strip() return [x.strip() for x in html.split(",") if x.strip()] diff --git a/module/plugins/hooks/PremiumToHook.py b/module/plugins/hooks/PremiumToHook.py index ef2a84223..bcd7a7aab 100644 --- a/module/plugins/hooks/PremiumToHook.py +++ b/module/plugins/hooks/PremiumToHook.py @@ -6,13 +6,13 @@ from module.plugins.internal.MultiHook import MultiHook class PremiumToHook(MultiHook): __name__ = "PremiumToHook" __type__ = "hook" - __version__ = "0.08" + __version__ = "0.11" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Premium.to hook plugin""" __license__ = "GPLv3" @@ -21,7 +21,9 @@ class PremiumToHook(MultiHook): ("stickell", "l.stickell@yahoo.it")] - def getHosters(self): - html = self.getURL("http://premium.to/api/hosters.php", - get={'username': self.account.username, 'password': self.account.password}) + def get_hosters(self): + user, info = self.account.select() + html = self.load("http://premium.to/api/hosters.php", + get={'username': user, + 'password': info['login']['password']}) return [x.strip() for x in html.replace("\"", "").split(";")] diff --git a/module/plugins/hooks/PremiumizeMeHook.py b/module/plugins/hooks/PremiumizeMeHook.py index e081fb389..9a9a380af 100644 --- a/module/plugins/hooks/PremiumizeMeHook.py +++ b/module/plugins/hooks/PremiumizeMeHook.py @@ -7,32 +7,34 @@ from module.plugins.internal.MultiHook import MultiHook class PremiumizeMeHook(MultiHook): __name__ = "PremiumizeMeHook" __type__ = "hook" - __version__ = "0.17" + __version__ = "0.20" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Premiumize.me hook plugin""" __license__ = "GPLv3" __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com")] - def getHosters(self): - # Get account data - user, data = self.account.selectAccount() + def get_hosters(self): + #: Get account data + user, info = self.account.select() - # Get supported hosters list from premiumize.me using the - # json API v1 (see https://secure.premiumize.me/?show=api) - answer = self.getURL("https://api.premiumize.me/pm-api/v1.php", - get={'method': "hosterlist", 'params[login]': user, 'params[pass]': data['password']}) + #: Get supported hosters list from premiumize.me using the + #: json API v1 (see https://secure.premiumize.me/?show=api) + answer = self.load("http://api.premiumize.me/pm-api/v1.php", #@TODO: Revert to `https` in 0.4.10 + get={'method' : "hosterlist", + 'params[login]': user, + 'params[pass]' : info['login']['password']}) data = json_loads(answer) - # If account is not valid thera are no hosters available + #: If account is not valid thera are no hosters available if data['status'] != 200: return [] - # Extract hosters from json file + #: Extract hosters from json file return data['result']['hosterlist'] diff --git a/module/plugins/hooks/PutdriveComHook.py b/module/plugins/hooks/PutdriveComHook.py index c3ebf4ff3..d206aaf88 100644 --- a/module/plugins/hooks/PutdriveComHook.py +++ b/module/plugins/hooks/PutdriveComHook.py @@ -6,12 +6,13 @@ from module.plugins.hooks.ZeveraComHook import ZeveraComHook class PutdriveComHook(ZeveraComHook): __name__ = "PutdriveComHook" __type__ = "hook" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" - __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed", "bool" , "Revert to standard download if download fails", False), - ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Putdrive.com hook plugin""" __license__ = "GPLv3" diff --git a/module/plugins/hooks/RPNetBizHook.py b/module/plugins/hooks/RPNetBizHook.py index 10332948d..5d26b7f09 100644 --- a/module/plugins/hooks/RPNetBizHook.py +++ b/module/plugins/hooks/RPNetBizHook.py @@ -7,30 +7,32 @@ from module.plugins.internal.MultiHook import MultiHook class RPNetBizHook(MultiHook): __name__ = "RPNetBizHook" __type__ = "hook" - __version__ = "0.14" + __version__ = "0.16" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """RPNet.biz hook plugin""" __license__ = "GPLv3" __authors__ = [("Dman", "dmanugm@gmail.com")] - def getHosters(self): - # Get account data - user, data = self.account.selectAccount() + def get_hosters(self): + #: Get account data + user, info = self.account.select() - res = self.getURL("https://premium.rpnet.biz/client_api.php", - get={'username': user, 'password': data['password'], 'action': "showHosterList"}) + res = self.load("https://premium.rpnet.biz/client_api.php", + get={'username': user, + 'password': info['login']['password'], + 'action' : "showHosterList"}) hoster_list = json_loads(res) - # If account is not valid thera are no hosters available + #: If account is not valid thera are no hosters available if 'error' in hoster_list: return [] - # Extract hosters from json file + #: Extract hosters from json file return hoster_list['hosters'] diff --git a/module/plugins/hooks/RapideoPlHook.py b/module/plugins/hooks/RapideoPlHook.py index 0400f07ba..130f73851 100644 --- a/module/plugins/hooks/RapideoPlHook.py +++ b/module/plugins/hooks/RapideoPlHook.py @@ -7,23 +7,23 @@ from module.plugins.internal.MultiHook import MultiHook class RapideoPlHook(MultiHook): __name__ = "RapideoPlHook" __type__ = "hook" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Rapideo.pl hook plugin""" __license__ = "GPLv3" __authors__ = [("goddie", "dev@rapideo.pl")] - def getHosters(self): - hostings = json_loads(self.getURL("https://www.rapideo.pl/clipboard.php?json=3").strip()) - hostings_domains = [domain for row in hostings for domain in row["domains"] if row["sdownload"] == "0"] + def get_hosters(self): + hostings = json_loads(self.load("https://www.rapideo.pl/clipboard.php?json=3").strip()) + hostings_domains = [domain for row in hostings for domain in row['domains'] if row['sdownload'] == "0"] - self.logDebug(hostings_domains) + self.log_debug(hostings_domains) return hostings_domains diff --git a/module/plugins/hooks/RealdebridComHook.py b/module/plugins/hooks/RealdebridComHook.py index aa0c9f640..01b9d165e 100644 --- a/module/plugins/hooks/RealdebridComHook.py +++ b/module/plugins/hooks/RealdebridComHook.py @@ -6,22 +6,19 @@ from module.plugins.internal.MultiHook import MultiHook class RealdebridComHook(MultiHook): __name__ = "RealdebridComHook" __type__ = "hook" - __version__ = "0.46" + __version__ = "0.47" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 ), - ("ssl" , "bool" , "Use HTTPS" , True )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Real-Debrid.com hook plugin""" __license__ = "GPLv3" __authors__ = [("Devirex Hazzard", "naibaf_11@yahoo.de")] - def getHosters(self): - https = "https" if self.getConfig('ssl') else "http" - html = self.getURL(https + "://real-debrid.com/api/hosters.php").replace("\"", "").strip() - + def get_hosters(self): + html = self.load("https://real-debrid.com/api/hosters.php").replace("\"", "").strip() return [x.strip() for x in html.split(",") if x.strip()] diff --git a/module/plugins/hooks/RehostToHook.py b/module/plugins/hooks/RehostToHook.py index a2415129a..7bb27e820 100644 --- a/module/plugins/hooks/RehostToHook.py +++ b/module/plugins/hooks/RehostToHook.py @@ -6,22 +6,22 @@ from module.plugins.internal.MultiHook import MultiHook class RehostToHook(MultiHook): __name__ = "RehostToHook" __type__ = "hook" - __version__ = "0.50" + __version__ = "0.51" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Rehost.to hook plugin""" __license__ = "GPLv3" __authors__ = [("RaNaN", "RaNaN@pyload.org")] - def getHosters(self): - user, data = self.account.selectAccount() - html = self.getURL("http://rehost.to/api.php", + def get_hosters(self): + user, info = self.account.select() + html = self.load("http://rehost.to/api.php", get={'cmd' : "get_supported_och_dl", - 'long_ses': self.account.getAccountInfo(user)['session']}) + 'long_ses': self.account.get_data(user)['session']}) return [x.strip() for x in html.replace("\"", "").split(",")] diff --git a/module/plugins/hooks/RestartFailed.py b/module/plugins/hooks/RestartFailed.py index 865af2a6b..6c3388e3a 100644 --- a/module/plugins/hooks/RestartFailed.py +++ b/module/plugins/hooks/RestartFailed.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- -from module.plugins.Hook import Hook +from module.plugins.internal.Addon import Addon -class RestartFailed(Hook): +class RestartFailed(Addon): __name__ = "RestartFailed" __type__ = "hook" - __version__ = "1.58" + __version__ = "1.60" + __status__ = "testing" __config__ = [("interval", "int", "Check interval in minutes", 90)] @@ -18,28 +19,27 @@ class RestartFailed(Hook): MIN_CHECK_INTERVAL = 15 * 60 #: 15 minutes - # def pluginConfigChanged(self, plugin, name, value): + # def plugin_config_changed(self, plugin, name, value): # if name == "interval": # interval = value * 60 - # if self.MIN_CHECK_INTERVAL <= interval != self.interval: - # self.core.scheduler.removeJob(self.cb) + # if self.MIN_CHECK_INTERVAL <= interval is not self.interval: + # self.pyload.scheduler.removeJob(self.cb) # self.interval = interval - # self.initPeriodical() + # self.init_periodical() # else: - # self.logDebug("Invalid interval value, kept current") + # self.log_debug("Invalid interval value, kept current") def periodical(self): - self.logDebug(_("Restart failed downloads")) - self.core.api.restartFailed() + self.log_debug("Restart failed downloads") + self.pyload.api.restartFailed() - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - # self.event_list = ["pluginConfigChanged"] + def init(self): + # self.event_map = {'pluginConfigChanged': "plugin_config_changed"} self.interval = self.MIN_CHECK_INTERVAL - def coreReady(self): - # self.pluginConfigChanged(self.__name__, "interval", self.getConfig('interval')) - self.interval = max(self.MIN_CHECK_INTERVAL, self.getConfig('interval') * 60) + def activate(self): + # self.plugin_config_changed(self.__name__, "interval", self.get_config('interval')) + self.interval = max(self.MIN_CHECK_INTERVAL, self.get_config('interval') * 60) diff --git a/module/plugins/hooks/SimplyPremiumComHook.py b/module/plugins/hooks/SimplyPremiumComHook.py index 116e3a76e..6fbd75c8a 100644 --- a/module/plugins/hooks/SimplyPremiumComHook.py +++ b/module/plugins/hooks/SimplyPremiumComHook.py @@ -7,21 +7,21 @@ from module.plugins.internal.MultiHook import MultiHook class SimplyPremiumComHook(MultiHook): __name__ = "SimplyPremiumComHook" __type__ = "hook" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Simply-Premium.com hook plugin""" __license__ = "GPLv3" __authors__ = [("EvolutionClip", "evolutionclip@live.de")] - def getHosters(self): - json_data = self.getURL("http://www.simply-premium.com/api/hosts.php", get={'format': "json", 'online': 1}) + def get_hosters(self): + json_data = self.load("http://www.simply-premium.com/api/hosts.php", get={'format': "json", 'online': 1}) json_data = json_loads(json_data) host_list = [element['regex'] for element in json_data['result']] diff --git a/module/plugins/hooks/SimplydebridComHook.py b/module/plugins/hooks/SimplydebridComHook.py index 01629df99..0da7ec719 100644 --- a/module/plugins/hooks/SimplydebridComHook.py +++ b/module/plugins/hooks/SimplydebridComHook.py @@ -6,19 +6,19 @@ from module.plugins.internal.MultiHook import MultiHook class SimplydebridComHook(MultiHook): __name__ = "SimplydebridComHook" __type__ = "hook" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Simply-Debrid.com hook plugin""" __license__ = "GPLv3" __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")] - def getHosters(self): - html = self.getURL("http://simply-debrid.com/api.php", get={'list': 1}) + def get_hosters(self): + html = self.load("http://simply-debrid.com/api.php", get={'list': 1}) return [x.strip() for x in html.rstrip(';').replace("\"", "").split(";")] diff --git a/module/plugins/hooks/SkipRev.py b/module/plugins/hooks/SkipRev.py index 7901ca540..a1ddc3094 100644 --- a/module/plugins/hooks/SkipRev.py +++ b/module/plugins/hooks/SkipRev.py @@ -7,14 +7,14 @@ import urlparse from types import MethodType from module.PyFile import PyFile -from module.plugins.Hook import Hook -from module.plugins.Plugin import SkipDownload +from module.plugins.internal.Addon import Addon -class SkipRev(Hook): +class SkipRev(Addon): __name__ = "SkipRev" __type__ = "hook" - __version__ = "0.29" + __version__ = "0.33" + __status__ = "testing" __config__ = [("mode" , "Auto;Manual", "Choose recovery archives to skip" , "Auto"), ("revtokeep", "int" , "Number of recovery archives to keep for package", 0 )] @@ -24,30 +24,19 @@ class SkipRev(Hook): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - @staticmethod - def _setup(self): - self.pyfile.plugin._setup() + def _init(self): + self.pyfile.plugin._init() if self.pyfile.hasStatus("skipped"): - raise SkipDownload(self.pyfile.statusname or self.pyfile.pluginname) + self.skip(self.pyfile.statusname or self.pyfile.pluginname) def _name(self, pyfile): - if hasattr(pyfile.pluginmodule, "getInfo"): #@NOTE: getInfo is deprecated in 0.4.10 - return pyfile.pluginmodule.getInfo([pyfile.url]).next()[0] - else: - self.logWarning("Unable to grab file name") - return urlparse.urlparse(urllib.unquote(pyfile.url)).path.split('/')[-1] + return pyfile.pluginclass.get_info(pyfile.url)['name'] def _pyfile(self, link): - return PyFile(self.core.files, + return PyFile(self.pyload.files, link.fid, link.url, link.name, @@ -59,47 +48,46 @@ class SkipRev(Hook): link.order) - def downloadPreparing(self, pyfile): + def download_preparing(self, pyfile): name = self._name(pyfile) if pyfile.statusname is _("unskipped") or not name.endswith(".rev") or not ".part" in name: return - revtokeep = -1 if self.getConfig('mode') == "Auto" else self.getConfig('revtokeep') + revtokeep = -1 if self.get_config('mode') == "Auto" else self.get_config('revtokeep') if revtokeep: status_list = (1, 4, 8, 9, 14) if revtokeep < 0 else (1, 3, 4, 8, 9, 14) pyname = re.compile(r'%s\.part\d+\.rev$' % name.rsplit('.', 2)[0].replace('.', '\.')) - queued = [True for link in self.core.api.getPackageData(pyfile.package().id).links \ + queued = [True for link in self.pyload.api.getPackageData(pyfile.package().id).links \ if link.status not in status_list and pyname.match(link.name)].count(True) - if not queued or queued < revtokeep: #: keep one rev at least in auto mode + if not queued or queued < revtokeep: #: Keep one rev at least in auto mode return pyfile.setCustomStatus("SkipRev", "skipped") - if not hasattr(pyfile.plugin, "_setup"): - # Work-around: inject status checker inside the preprocessing routine of the plugin - pyfile.plugin._setup = pyfile.plugin.setup - pyfile.plugin.setup = MethodType(self._setup, pyfile.plugin) + if not hasattr(pyfile.plugin, "_init"): + #: Work-around: inject status checker inside the preprocessing routine of the plugin + pyfile.plugin._init = pyfile.plugin.init + pyfile.plugin.init = MethodType(self._init, pyfile.plugin) - def downloadFailed(self, pyfile): - #: Check if pyfile is still "failed", - # maybe might has been restarted in meantime + def download_failed(self, pyfile): + #: Check if pyfile is still "failed", maybe might has been restarted in meantime if pyfile.status != 8 or pyfile.name.rsplit('.', 1)[-1].strip() not in ("rar", "rev"): return - revtokeep = -1 if self.getConfig('mode') == "Auto" else self.getConfig('revtokeep') + revtokeep = -1 if self.get_config('mode') == "Auto" else self.get_config('revtokeep') if not revtokeep: return pyname = re.compile(r'%s\.part\d+\.rev$' % pyfile.name.rsplit('.', 2)[0].replace('.', '\.')) - for link in self.core.api.getPackageData(pyfile.package().id).links: - if link.status is 4 and pyname.match(link.name): + for link in self.pyload.api.getPackageData(pyfile.package().id).links: + if link.status == 4 and pyname.match(link.name): pylink = self._pyfile(link) if revtokeep > -1 or pyfile.name.endswith(".rev"): @@ -107,6 +95,6 @@ class SkipRev(Hook): else: pylink.setCustomStatus(_("unskipped"), "queued") - self.core.files.save() + self.pyload.files.save() pylink.release() return diff --git a/module/plugins/hooks/SmoozedComHook.py b/module/plugins/hooks/SmoozedComHook.py index 24b7c8df0..b9825b223 100644 --- a/module/plugins/hooks/SmoozedComHook.py +++ b/module/plugins/hooks/SmoozedComHook.py @@ -6,19 +6,19 @@ from module.plugins.internal.MultiHook import MultiHook class SmoozedComHook(MultiHook): __name__ = "SmoozedComHook" __type__ = "hook" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Smoozed.com hook plugin""" __license__ = "GPLv3" __authors__ = [("", "")] - def getHosters(self): - user, data = self.account.selectAccount() - return self.account.getAccountInfo(user)["hosters"] + def get_hosters(self): + user, info = self.account.select() + return self.account.get_data(user)['hosters'] diff --git a/module/plugins/hooks/UnSkipOnFail.py b/module/plugins/hooks/UnSkipOnFail.py index 9059d0350..d467b8a01 100644 --- a/module/plugins/hooks/UnSkipOnFail.py +++ b/module/plugins/hooks/UnSkipOnFail.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- from module.PyFile import PyFile -from module.plugins.Hook import Hook +from module.plugins.internal.Addon import Addon -class UnSkipOnFail(Hook): +class UnSkipOnFail(Addon): __name__ = "UnSkipOnFail" __type__ = "hook" - __version__ = "0.07" + __version__ = "0.09" + __status__ = "testing" __config__ = [("activated", "bool", "Activated", True)] @@ -16,46 +17,38 @@ class UnSkipOnFail(Hook): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - - def downloadFailed(self, pyfile): - #: Check if pyfile is still "failed", - # maybe might has been restarted in meantime + def download_failed(self, pyfile): + #: Check if pyfile is still "failed", maybe might has been restarted in meantime if pyfile.status != 8: return msg = _("Looking for skipped duplicates of: %s (pid:%s)") - self.logInfo(msg % (pyfile.name, pyfile.package().id)) + self.log_info(msg % (pyfile.name, pyfile.package().id)) - link = self.findDuplicate(pyfile) + link = self.find_duplicate(pyfile) if link: - self.logInfo(_("Queue found duplicate: %s (pid:%s)") % (link.name, link.packageID)) + self.log_info(_("Queue found duplicate: %s (pid:%s)") % (link.name, link.packageID)) #: Change status of "link" to "new_status". - # "link" has to be a valid FileData object, - # "new_status" has to be a valid status name - # (i.e. "queued" for this Plugin) - # It creates a temporary PyFile object using - # "link" data, changes its status, and tells - # the core.files-manager to save its data. + #: "link" has to be a valid FileData object, + #: "new_status" has to be a valid status name + #: (i.e. "queued" for this Plugin) + #: It creates a temporary PyFile object using + #: "link" data, changes its status, and tells + #: The pyload.files-manager to save its data. pylink = self._pyfile(link) pylink.setCustomStatus(_("unskipped"), "queued") - self.core.files.save() + self.pyload.files.save() pylink.release() else: - self.logInfo(_("No duplicates found")) + self.log_info(_("No duplicates found")) - def findDuplicate(self, pyfile): - """ Search all packages for duplicate links to "pyfile". + def find_duplicate(self, pyfile): + """Search all packages for duplicate links to "pyfile". Duplicates are links that would overwrite "pyfile". To test on duplicity the package-folder and link-name of twolinks are compared (link.name). @@ -64,28 +57,28 @@ class UnSkipOnFail(Hook): the data for "pyfile" iotselöf. It does MOT check the link's status. """ - queue = self.core.api.getQueue() #: get packages (w/o files, as most file data is useless here) + queue = self.pyload.api.getQueue() #: Get packages (w/o files, as most file data is useless here) for package in queue: - #: check if package-folder equals pyfile's package folder - if package.folder != pyfile.package().folder: + #: Check if package-folder equals pyfile's package folder + if package.folder is not pyfile.package().folder: continue - #: now get packaged data w/ files/links - pdata = self.core.api.getPackageData(package.pid) + #: Now get packaged data w/ files/links + pdata = self.pyload.api.getPackageData(package.pid) for link in pdata.links: - #: check if link is "skipped" + #: Check if link == "skipped" if link.status != 4: continue - #: check if link name collides with pdata's name - #: AND at last check if it is not pyfile itself - if link.name == pyfile.name and link.fid != pyfile.id: + #: Check if link name collides with pdata's name + #: and at last check if it is not pyfile itself + if link.name is pyfile.name and link.fid is not pyfile.id: return link def _pyfile(self, link): - return PyFile(self.core.files, + return PyFile(self.pyload.files, link.fid, link.url, link.name, diff --git a/module/plugins/hooks/UpdateManager.py b/module/plugins/hooks/UpdateManager.py index 98d602226..117da0633 100644 --- a/module/plugins/hooks/UpdateManager.py +++ b/module/plugins/hooks/UpdateManager.py @@ -2,34 +2,23 @@ from __future__ import with_statement +import operator import os import re import sys import time +import traceback -from operator import itemgetter +from module.plugins.internal.Addon import Expose, Addon, threaded +from module.plugins.internal.Plugin import exists +from module.utils import fs_encode, save_join as fs_join -from module.network.RequestFactory import getURL -from module.plugins.Hook import Expose, Hook, threaded -from module.utils import save_join - -# Case-sensitive os.path.exists -def exists(path): - if os.path.exists(path): - if os.name == 'nt': - dir, name = os.path.split(path) - return name in os.listdir(dir) - else: - return True - else: - return False - - -class UpdateManager(Hook): +class UpdateManager(Addon): __name__ = "UpdateManager" __type__ = "hook" - __version__ = "0.52" + __version__ = "0.55" + __status__ = "testing" __config__ = [("activated" , "bool", "Activated" , True ), ("checkinterval", "int" , "Check interval in hours" , 8 ), @@ -39,7 +28,7 @@ class UpdateManager(Hook): ("reloadplugins", "bool", "Monitor plugin code changes in debug mode", True ), ("nodebugupdate", "bool", "Don't update plugins in debug mode" , False)] - __description__ = """ Check for updates """ + __description__ = """Check for updates""" __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] @@ -50,26 +39,26 @@ class UpdateManager(Hook): MIN_CHECK_INTERVAL = 3 * 60 * 60 #: 3 hours - def coreReady(self): + def activate(self): if self.checkonstart: - self.core.api.pauseServer() + self.pyload.api.pauseServer() self.update() if self.do_restart is False: - self.core.api.unpauseServer() + self.pyload.api.unpauseServer() - self.initPeriodical() + self.init_periodical() - def setup(self): + def init(self): self.info = {'pyload': False, 'version': None, 'plugins': False, 'last_check': time.time()} - self.mtimes = {} #: store modification time for each plugin + self.mtimes = {} #: Store modification time for each plugin - self.event_list = ["allDownloadsProcessed"] + self.event_map = {'allDownloadsProcessed': "all_downloads_processed"} self.interval = 10 - if self.getConfig('checkonstart'): - self.core.api.pauseServer() + if self.get_config('checkonstart'): + self.pyload.api.pauseServer() self.checkonstart = True else: self.checkonstart = False @@ -77,32 +66,43 @@ class UpdateManager(Hook): self.do_restart = False - def allDownloadsProcessed(self): + def all_downloads_processed(self): if self.do_restart is True: - self.logWarning(_("Downloads are done, restarting pyLoad to reload the updated plugins")) - self.core.api.restart() + self.log_warning(_("Downloads are done, restarting pyLoad to reload the updated plugins")) + self.pyload.api.restart() def periodical(self): - if self.core.debug: - if self.getConfig('reloadplugins'): - self.autoreloadPlugins() + if self.pyload.debug: + if self.get_config('reloadplugins'): + self.autoreload_plugins() - if self.getConfig('nodebugupdate'): + if self.get_config('nodebugupdate'): return - if self.getConfig('checkperiod') \ - and time.time() - max(self.MIN_CHECK_INTERVAL, self.getConfig('checkinterval') * 60 * 60) > self.info['last_check']: + if self.get_config('checkperiod') \ + and time.time() - max(self.MIN_CHECK_INTERVAL, self.get_config('checkinterval') * 60 * 60) > self.info['last_check']: self.update() + #: Deprecated method, use `autoreload_plugins` instead @Expose - def autoreloadPlugins(self): - """ reload and reindex all modified plugins """ + def autoreloadPlugins(self, *args, **kwargs): + """ + See `autoreload_plugins` + """ + return self.autoreload_plugins(*args, **kwargs) + + + @Expose + def autoreload_plugins(self): + """ + Reload and reindex all modified plugins + """ modules = filter( lambda m: m and (m.__name__.startswith("module.plugins.") or m.__name__.startswith("userplugins.")) and - m.__name__.count(".") >= 2, sys.modules.itervalues() + m.__name__.count(".") >= 2, sys.modules.values() ) reloads = [] @@ -110,12 +110,12 @@ class UpdateManager(Hook): for m in modules: root, type, name = m.__name__.rsplit(".", 2) id = (type, name) - if type in self.core.pluginManager.plugins: + if type in self.pyload.pluginManager.plugins: f = m.__file__.replace(".pyc", ".py") if not os.path.isfile(f): continue - mtime = os.stat(f).st_mtime + mtime = os.path.getmtime(f) if id not in self.mtimes: self.mtimes[id] = mtime @@ -123,29 +123,31 @@ class UpdateManager(Hook): reloads.append(id) self.mtimes[id] = mtime - return True if self.core.pluginManager.reloadPlugins(reloads) else False + return True if self.pyload.pluginManager.reloadPlugins(reloads) else False def server_response(self): try: - return getURL(self.SERVER_URL, get={'v': self.core.api.getServerVersion()}).splitlines() + return self.load(self.SERVER_URL, + get={'v': self.pyload.api.getServerVersion()}).splitlines() except Exception: - self.logWarning(_("Unable to retrieve server to get updates")) + self.log_warning(_("Unable to retrieve server to get updates")) @Expose @threaded def update(self): - """ check for updates """ - - if self._update() is 2 and self.getConfig('autorestart'): - if not self.core.api.statusDownloads(): - self.core.api.restart() + """ + Check for updates + """ + if self._update() == 2 and self.get_config('autorestart'): + if not self.pyload.api.statusDownloads(): + self.pyload.api.restart() else: self.do_restart = True - self.logWarning(_("Downloads are active, will restart once the download is done")) - self.core.api.pauseServer() + self.log_warning(_("Downloads are active, will restart once the download is done")) + self.pyload.api.pauseServer() def _update(self): @@ -157,30 +159,31 @@ class UpdateManager(Hook): exitcode = 0 elif data[0] == "None": - self.logInfo(_("No new pyLoad version available")) - exitcode = self._updatePlugins(data[1:]) + self.log_info(_("No new pyLoad version available")) + exitcode = self._update_plugins(data[1:]) elif onlyplugin: exitcode = 0 else: - self.logInfo(_("*** New pyLoad Version %s available ***") % data[0]) - self.logInfo(_("*** Get it here: https://github.com/pyload/pyload/releases ***")) + self.log_info(_("*** New pyLoad Version %s available ***") % data[0]) + self.log_info(_("*** Get it here: https://github.com/pyload/pyload/releases ***")) self.info['pyload'] = True self.info['version'] = data[0] exitcode = 3 - # Exit codes: - # -1 = No plugin updated, new pyLoad version available - # 0 = No plugin updated - # 1 = Plugins updated - # 2 = Plugins updated, but restart required + #: Exit codes: + #: -1 = No plugin updated, new pyLoad version available + #: 0 = No plugin updated + #: 1 = Plugins updated + #: 2 = Plugins updated, but restart required return exitcode - def _updatePlugins(self, data): - """ check for plugin updates """ - + def _update_plugins(self, data): + """ + Check for plugin updates + """ exitcode = 0 updated = [] @@ -202,7 +205,7 @@ class UpdateManager(Hook): if blacklist: type_plugins = [(plugin['type'], plugin['name'].rsplit('.', 1)[0]) for plugin in blacklist] - # Protect UpdateManager from self-removing + #: Protect UpdateManager from self-removing try: type_plugins.remove(("hook", "UpdateManager")) except ValueError: @@ -210,17 +213,17 @@ class UpdateManager(Hook): for t, n in type_plugins: for idx, plugin in enumerate(updatelist): - if n == plugin['name'] and t == plugin['type']: + if n is plugin['name'] and t is plugin['type']: updatelist.pop(idx) break - for t, n in self.removePlugins(sorted(type_plugins)): - self.logInfo(_("Removed blacklisted plugin: [%(type)s] %(name)s") % { + for t, n in self.remove_plugins(sorted(type_plugins)): + self.log_info(_("Removed blacklisted plugin: [%(type)s] %(name)s") % { 'type': t, 'name': n, }) - for plugin in sorted(updatelist, key=itemgetter("type", "name")): + for plugin in sorted(updatelist, key=operator.itemgetter("type", "name")): filename = plugin['name'] prefix = plugin['type'] version = plugin['version'] @@ -236,7 +239,7 @@ class UpdateManager(Hook): else: type = prefix - plugins = getattr(self.core.pluginManager, "%sPlugins" % type) + plugins = getattr(self.pyload.pluginManager, "%sPlugins" % type) oldver = float(plugins[name]['v']) if name in plugins else None newver = float(version) @@ -248,62 +251,74 @@ class UpdateManager(Hook): else: continue - self.logInfo(_(msg) % {'type' : type, + self.log_info(_(msg) % {'type' : type, 'name' : name, 'oldver': oldver, 'newver': newver}) try: - content = getURL(url % plugin) + content = self.load(url % plugin, decode=False) m = VERSION.search(content) if m and m.group(2) == version: - with open(save_join("userplugins", prefix, filename), "wb") as f: - f.write(content) + with open(fs_join("userplugins", prefix, filename), "wb") as f: + f.write(fs_encode(content)) updated.append((prefix, name)) else: - raise Exception, _("Version mismatch") + raise Exception(_("Version mismatch")) except Exception, e: - self.logError(_("Error updating plugin: %s") % filename, e) + self.log_error(_("Error updating plugin: %s") % filename, e) + if self.pyload.debug: + traceback.print_exc() if updated: - self.logInfo(_("*** Plugins updated ***")) + self.log_info(_("*** Plugins updated ***")) - if self.core.pluginManager.reloadPlugins(updated): + if self.pyload.pluginManager.reloadPlugins(updated): exitcode = 1 else: - self.logWarning(_("pyLoad restart required to reload the updated plugins")) + self.log_warning(_("pyLoad restart required to reload the updated plugins")) self.info['plugins'] = True exitcode = 2 self.manager.dispatchEvent("plugin_updated", updated) else: - self.logInfo(_("No plugin updates available")) + self.log_info(_("No plugin updates available")) - # Exit codes: - # 0 = No plugin updated - # 1 = Plugins updated - # 2 = Plugins updated, but restart required + #: Exit codes: + #: 0 = No plugin updated + #: 1 = Plugins updated + #: 2 = Plugins updated, but restart required return exitcode + #: Deprecated method, use `remove_plugins` instead @Expose - def removePlugins(self, type_plugins): - """ delete plugins from disk """ + def removePlugins(self, *args, **kwargs): + """ + See `remove_plugins` + """ + return self.remove_plugins(*args, **kwargs) + + @Expose + def remove_plugins(self, type_plugins): + """ + Delete plugins from disk + """ if not type_plugins: return removed = set() - self.logDebug("Requested deletion of plugins: %s" % type_plugins) + self.log_debug("Requested deletion of plugins: %s" % type_plugins) for type, name in type_plugins: rootplugins = os.path.join(pypath, "module", "plugins") for dir in ("userplugins", rootplugins): - py_filename = save_join(dir, type, name + ".py") + py_filename = fs_join(dir, type, name + ".py") pyc_filename = py_filename + "c" if type == "hook": @@ -311,7 +326,7 @@ class UpdateManager(Hook): self.manager.deactivateHook(name) except Exception, e: - self.logDebug(e) + self.log_debug(e) for filename in (py_filename, pyc_filename): if not exists(filename): @@ -321,10 +336,12 @@ class UpdateManager(Hook): os.remove(filename) except OSError, e: - self.logError(_("Error removing: %s") % filename, e) + self.log_warning(_("Error removing: %s") % filename, e) + if self.pyload.debug: + traceback.print_exc() else: id = (type, name) removed.add(id) - return list(removed) #: return a list of the plugins successfully removed + return list(removed) #: Return a list of the plugins successfully removed diff --git a/module/plugins/hooks/UserAgentSwitcher.py b/module/plugins/hooks/UserAgentSwitcher.py index 5f9fd5212..52f542268 100644 --- a/module/plugins/hooks/UserAgentSwitcher.py +++ b/module/plugins/hooks/UserAgentSwitcher.py @@ -2,31 +2,37 @@ import pycurl -from module.plugins.Hook import Hook +from module.plugins.internal.Addon import Addon +from module.plugins.internal.Plugin import encode -class UserAgentSwitcher(Hook): +class UserAgentSwitcher(Addon): __name__ = "UserAgentSwitcher" __type__ = "hook" - __version__ = "0.07" + __version__ = "0.11" + __status__ = "testing" - __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" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 + def download_preparing(self, pyfile): + connecttimeout = self.get_config('connecttimeout') + maxredirs = self.get_config('maxredirs') + useragent = self.get_config('useragent') + if connecttimeout: + pyfile.plugin.req.http.c.setopt(pycurl.CONNECTTIMEOUT, connecttimeout) - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 + if maxredirs: + pyfile.plugin.req.http.c.setopt(pycurl.MAXREDIRS, maxredirs) - - def downloadPreparing(self, pyfile): - useragent = self.getConfig('useragent').encode("utf8", "replace") #@TODO: Remove `encode` in 0.4.10 if useragent: - self.logDebug("Use custom user-agent string: " + useragent) - pyfile.plugin.req.http.c.setopt(pycurl.USERAGENT, useragent) + self.log_debug("Use custom user-agent string: " + useragent) + pyfile.plugin.req.http.c.setopt(pycurl.USERAGENT, encode(useragent)) diff --git a/module/plugins/hooks/WindowsPhoneNotify.py b/module/plugins/hooks/WindowsPhoneNotify.py index 8f66761f6..900d94a04 100644 --- a/module/plugins/hooks/WindowsPhoneNotify.py +++ b/module/plugins/hooks/WindowsPhoneNotify.py @@ -3,13 +3,14 @@ import httplib import time -from module.plugins.Hook import Hook, Expose +from module.plugins.internal.Addon import Addon, Expose -class WindowsPhoneNotify(Hook): +class WindowsPhoneNotify(Addon): __name__ = "WindowsPhoneNotify" __type__ = "hook" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __config__ = [("push-id" , "str" , "Push ID" , "" ), ("push-url" , "str" , "Push url" , "" ), @@ -28,62 +29,58 @@ class WindowsPhoneNotify(Hook): ("Walter Purcaro", "vuolter@gmail.com" )] - interval = 0 #@TODO: Remove in 0.4.10 - - - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - - self.event_list = ["allDownloadsProcessed", "plugin_updated"] + def init(self): + self.event_list = ["plugin_updated"] + self.event_map = {'allDownloadsProcessed': "all_downloads_processed"} self.last_notify = 0 self.notifications = 0 def plugin_updated(self, type_plugins): - if not self.getConfig('notifyupdate'): + if not self.get_config('notifyupdate'): return self.notify(_("Plugins updated"), str(type_plugins)) - def coreReady(self): - self.key = (self.getConfig('push-id'), self.getConfig('push-url')) + def activate(self): + self.key = (self.get_config('push-id'), self.get_config('push-url')) - def coreExiting(self): - if not self.getConfig('notifyexit'): + def exit(self): + if not self.get_config('notifyexit'): return - if self.core.do_restart: + if self.pyload.do_restart: self.notify(_("Restarting pyLoad")) else: self.notify(_("Exiting pyLoad")) - def newCaptchaTask(self, task): - if not self.getConfig('notifycaptcha'): + def captcha_task(self, task): + if not self.get_config('notifycaptcha'): return self.notify(_("Captcha"), _("New request waiting user input")) - def packageFinished(self, pypack): - if self.getConfig('notifypackage'): + def package_finished(self, pypack): + if self.get_config('notifypackage'): self.notify(_("Package finished"), pypack.name) - def allDownloadsProcessed(self): - if not self.getConfig('notifyprocessed'): + def all_downloads_processed(self): + if not self.get_config('notifyprocessed'): return - if any(True for pdata in self.core.api.getQueue() if pdata.linksdone < pdata.linkstotal): + if any(True for pdata in self.pyload.api.getQueue() if pdata.linksdone < pdata.linkstotal): self.notify(_("Package failed"), _("One or more packages was not completed successfully")) else: self.notify(_("All packages finished")) - def getXmlData(self, msg): + def get_xml_data(self, msg): return ("<?xml version='1.0' encoding='utf-8'?> <wp:Notification xmlns:wp='WPNotification'> " "<wp:Toast> <wp:Text1>pyLoad</wp:Text1> <wp:Text2>%s</wp:Text2> " "</wp:Toast> </wp:Notification>" % msg) @@ -99,21 +96,21 @@ class WindowsPhoneNotify(Hook): if not id or not url: return - if self.core.isClientConnected() and not self.getConfig('ignoreclient'): + if self.pyload.isClientConnected() and not self.get_config('ignoreclient'): return elapsed_time = time.time() - self.last_notify - if elapsed_time < self.getConf("sendtimewait"): + if elapsed_time < self.get_config("sendtimewait"): return if elapsed_time > 60: self.notifications = 0 - elif self.notifications >= self.getConf("sendpermin"): + elif self.notifications >= self.get_config("sendpermin"): return - request = self.getXmlData("%s: %s" % (event, msg) if msg else event) + request = self.get_xml_data("%s: %s" % (event, msg) if msg else event) webservice = httplib.HTTP(url) webservice.putrequest("POST", id) diff --git a/module/plugins/hooks/XFileSharingPro.py b/module/plugins/hooks/XFileSharingPro.py index 92d89dc01..7567a31a3 100644 --- a/module/plugins/hooks/XFileSharingPro.py +++ b/module/plugins/hooks/XFileSharingPro.py @@ -2,13 +2,14 @@ import re -from module.plugins.Hook import Hook +from module.plugins.internal.Hook import Hook class XFileSharingPro(Hook): __name__ = "XFileSharingPro" __type__ = "hook" - __version__ = "0.38" + __version__ = "0.42" + __status__ = "testing" __config__ = [("activated" , "bool", "Activated" , True ), ("use_hoster_list" , "bool", "Load listed hosters only" , False), @@ -22,50 +23,51 @@ class XFileSharingPro(Hook): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 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\.)?(?:\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", - #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", - #NOT WORKING: + "ani-stream.com", "backin.net", "cloudsix.me", "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", "sharebeast.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", "sharerepo.com", + "shareswift.com", "uploadbaz.com", "uploadc.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"] - # def pluginConfigChanged(self, plugin, name, value): - # self.loadPattern() + # def plugin_config_changed(self, plugin, name, value): + # self.load_pattern() - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - # self.event_list = ["pluginConfigChanged"] + # def init(self): + # self.event_map = {'pluginConfigChanged': "plugin_config_changed"} - def coreReady(self): - self.loadPattern() + def activate(self): + self.load_pattern() - def loadPattern(self): - use_builtin_list = self.getConfig('use_builtin_list') + def load_pattern(self): + use_builtin_list = self.get_config('use_builtin_list') for type, plugin in (("hoster", "XFileSharingPro"), ("crypter", "XFileSharingProFolder")): - every_plugin = not self.getConfig("use_%s_list" % type) + every_plugin = not self.get_config("use_%s_list" % type) if every_plugin: - self.logInfo(_("Handling any %s I can!") % type) + self.log_info(_("Handling any %s I can!") % type) pattern = self.regexp[type][0] else: - plugins = self.getConfig('%s_list' % type) + plugins = self.get_config('%s_list' % type) plugin_set = set(plugins.replace(' ', '').replace('\\', '').replace('|', ',').replace(';', ',').lower().split(',')) if use_builtin_list: @@ -74,42 +76,42 @@ class XFileSharingPro(Hook): plugin_set -= set(('', u'')) if not plugin_set: - self.logInfo(_("No %s to handle") % type) + self.log_info(_("No %s to handle") % type) self._unload(type, plugin) return match_list = '|'.join(sorted(plugin_set)) len_match_list = len(plugin_set) - self.logInfo(_("Handling %d %s%s: %s") % (len_match_list, + self.log_info(_("Handling %d %s%s: %s") % (len_match_list, type, "" if len_match_list == 1 else "s", match_list.replace('|', ', '))) pattern = self.regexp[type][1] % match_list.replace('.', '\.') - dict = self.core.pluginManager.plugins[type][plugin] + dict = self.pyload.pluginManager.plugins[type][plugin] dict['pattern'] = pattern dict['re'] = re.compile(pattern) - self.logDebug("Loaded %s pattern: %s" % (type, pattern)) + self.log_debug("Loaded %s pattern: %s" % (type, pattern)) def _unload(self, type, plugin): - dict = self.core.pluginManager.plugins[type][plugin] + dict = self.pyload.pluginManager.plugins[type][plugin] dict['pattern'] = r'^unmatchable$' dict['re'] = re.compile(dict['pattern']) - def unload(self): - # self.unloadHoster("BasePlugin") + def deactivate(self): + # self.unload_hoster("BasePlugin") for type, plugin in (("hoster", "XFileSharingPro"), ("crypter", "XFileSharingProFolder")): self._unload(type, plugin) - def unloadHoster(self, hoster): - hdict = self.core.pluginManager.hosterPlugins[hoster] + def unload_hoster(self, hoster): + hdict = self.pyload.pluginManager.hosterPlugins[hoster] if "new_name" in hdict and hdict['new_name'] == "XFileSharingPro": if "module" in hdict: hdict.pop('module', None) @@ -123,10 +125,10 @@ class XFileSharingPro(Hook): return False - # def downloadFailed(self, pyfile): + # def download_failed(self, pyfile): # if pyfile.pluginname == "BasePlugin" \ # and pyfile.hasStatus("failed") \ - # and not self.getConfig('use_hoster_list') \ - # and self.unloadHoster("BasePlugin"): - # self.logDebug("Unloaded XFileSharingPro from BasePlugin") + # and not self.get_config('use_hoster_list') \ + # and self.unload_hoster("BasePlugin"): + # self.log_debug("Unloaded XFileSharingPro from BasePlugin") # pyfile.setStatus("queued") diff --git a/module/plugins/hooks/XMPPInterface.py b/module/plugins/hooks/XMPPInterface.py index b61428392..50dd40774 100644 --- a/module/plugins/hooks/XMPPInterface.py +++ b/module/plugins/hooks/XMPPInterface.py @@ -12,15 +12,16 @@ from module.plugins.hooks.IRCInterface import IRCInterface class XMPPInterface(IRCInterface, JabberClient): __name__ = "XMPPInterface" __type__ = "hook" - __version__ = "0.11" + __version__ = "0.12" + __status__ = "testing" - __config__ = [("jid", "str", "Jabber ID", "user@exmaple-jabber-server.org"), - ("pw", "str", "Password", ""), - ("tls", "bool", "Use TLS", False), - ("owners", "str", "List of JIDs accepting commands from", "me@icq-gateway.org;some@msn-gateway.org"), - ("info_file", "bool", "Inform about every file finished", False), - ("info_pack", "bool", "Inform about every package finished", True), - ("captcha", "bool", "Send captcha requests", True)] + __config__ = [("jid" , "str" , "Jabber ID" , "user@exmaple-jabber-server.org" ), + ("pw" , "str" , "Password" , "" ), + ("tls" , "bool", "Use TLS" , False ), + ("owners" , "str" , "List of JIDs accepting commands from", "me@icq-gateway.org;some@msn-gateway.org"), + ("info_file", "bool", "Inform about every file finished" , False ), + ("info_pack", "bool", "Inform about every package finished" , True ), + ("captcha" , "bool", "Send captcha requests" , True )] __description__ = """Connect to jabber and let owner perform different tasks""" __license__ = "GPLv3" @@ -33,22 +34,22 @@ class XMPPInterface(IRCInterface, JabberClient): def __init__(self, core, manager): IRCInterface.__init__(self, core, manager) - self.jid = JID(self.getConfig('jid')) - password = self.getConfig('pw') + self.jid = JID(self.get_config('jid')) + password = self.get_config('pw') - # if bare JID is provided add a resource -- it is required + #: If bare JID is provided add a resource -- it is required if not self.jid.resource: self.jid = JID(self.jid.node, self.jid.domain, "pyLoad") - if self.getConfig('tls'): + if self.get_config('tls'): tls_settings = streamtls.TLSSettings(require=True, verify_peer=False) auth = ("sasl:PLAIN", "sasl:DIGEST-MD5") else: tls_settings = None auth = ("sasl:DIGEST-MD5", "digest") - # setup client with provided connection information - # and identity data + #: Setup client with provided connection information + #: And identity data JabberClient.__init__(self, self.jid, password, disco_name="pyLoad XMPP Client", disco_type="bot", tls_settings=tls_settings, auth_methods=auth) @@ -59,75 +60,81 @@ class XMPPInterface(IRCInterface, JabberClient): ] - def coreReady(self): + def activate(self): self.new_package = {} self.start() - def packageFinished(self, pypack): + def package_finished(self, pypack): try: - if self.getConfig('info_pack'): + if self.get_config('info_pack'): self.announce(_("Package finished: %s") % pypack.name) except Exception: pass - def downloadFinished(self, pyfile): + def download_finished(self, pyfile): try: - if self.getConfig('info_file'): + if self.get_config('info_file'): self.announce( - _("Download finished: %(name)s @ %(plugin)s") % {"name": pyfile.name, "plugin": pyfile.pluginname}) + _("Download finished: %(name)s @ %(plugin)s") % {'name': pyfile.name, 'plugin': pyfile.pluginname}) except Exception: pass def run(self): - # connect to IRC etc. + #: Connect to IRC etc. self.connect() try: self.loop() except Exception, ex: - self.logError(ex) + self.log_error(ex) def stream_state_changed(self, state, arg): - """This one is called when the state of stream connecting the component + """ + This one is called when the state of stream connecting the component to a server changes. This will usually be used to let the user - know what is going on.""" - self.logDebug("*** State changed: %s %r ***" % (state, arg)) + know what is going on. + """ + self.log_debug("*** State changed: %s %r ***" % (state, arg)) def disconnected(self): - self.logDebug("Client was disconnected") + self.log_debug("Client was disconnected") def stream_closed(self, stream): - self.logDebug("Stream was closed", stream) + self.log_debug("Stream was closed", stream) def stream_error(self, err): - self.logDebug("Stream Error", err) + self.log_debug("Stream Error", err) def get_message_handlers(self): - """Return list of (message_type, message_handler) tuples. + """ + Return list of (message_type, message_handler) tuples. The handlers returned will be called when matching message is received - in a client session.""" + in a client session. + """ return [("normal", self.message)] def message(self, stanza): - """Message handler for the component.""" + """ + Message handler for the component. + """ subject = stanza.get_subject() body = stanza.get_body() t = stanza.get_type() - self.logDebug("Message from %s received." % unicode(stanza.get_from())) - self.logDebug("Body: %s Subject: %s Type: %s" % (body, subject, t)) + self.log_debug("Message from %s received." % stanza.get_from()) + self.log_debug("Body: %s Subject: %s Type: %s" % (body, subject, t)) if t == "headline": - # 'headline' messages should never be replied to + #: 'headline' messages should never be replied to return True if subject: subject = u"Re: " + subject @@ -135,11 +142,11 @@ class XMPPInterface(IRCInterface, JabberClient): to_jid = stanza.get_from() from_jid = stanza.get_to() - #j = JID() + # j = JID() to_name = to_jid.as_utf8() from_name = from_jid.as_utf8() - names = self.getConfig('owners').split(";") + names = self.get_config('owners').split(";") if to_name in names or to_jid.node + "@" + to_jid.domain in names: messages = [] @@ -168,7 +175,7 @@ class XMPPInterface(IRCInterface, JabberClient): messages.append(m) except Exception, e: - self.logError(e) + self.log_error(e) return messages @@ -181,9 +188,11 @@ class XMPPInterface(IRCInterface, JabberClient): def announce(self, message): - """ send message to all owners""" - for user in self.getConfig('owners').split(";"): - self.logDebug("Send message to", user) + """ + Send message to all owners + """ + for user in self.get_config('owners').split(";"): + self.log_debug("Send message to", user) to_jid = JID(user) @@ -200,51 +209,62 @@ class XMPPInterface(IRCInterface, JabberClient): stream.send(m) - def beforeReconnecting(self, ip): + def before_reconnect(self, ip): self.disconnect() - def afterReconnecting(self, ip): + def after_reconnect(self, ip): self.connect() class VersionHandler(object): - """Provides handler for a version query. + """ + Provides handler for a version query. This class will answer version query and announce 'jabber:iq:version' namespace - in the client's disco#info results.""" - + in the client's disco#info results. + """ implements(IIqHandlersProvider, IFeaturesProvider) def __init__(self, client): - """Just remember who created this.""" + """ + Just remember who created this. + """ self.client = client def get_features(self): - """Return namespace which should the client include in its reply to a - disco#info query.""" + """ + Return namespace which should the client include in its reply to a + disco#info query. + """ return ["jabber:iq:version"] def get_iq_get_handlers(self): - """Return list of tuples (element_name, namespace, handler) describing - handlers of <iq type='get'/> stanzas""" + """ + Return list of tuples (element_name, namespace, handler) describing + handlers of <iq type='get'/> stanzas + """ return [("query", "jabber:iq:version", self.get_version)] def get_iq_set_handlers(self): - """Return empty list, as this class provides no <iq type='set'/> stanza handler.""" + """ + Return empty list, as this class provides no <iq type='set'/> stanza handler. + """ return [] def get_version(self, iq): - """Handler for jabber:iq:version queries. + """ + Handler for jabber:iq:version queries. jabber:iq:version queries are not supported directly by PyXMPP, so the XML node is accessed directly through the libxml2 API. This should be - used very carefully!""" + used very carefully! + """ iq = iq.make_result_response() q = iq.new_query("jabber:iq:version") q.newTextChild(q.ns(), "name", "Echo component") diff --git a/module/plugins/hooks/ZeveraComHook.py b/module/plugins/hooks/ZeveraComHook.py index 21c1741d2..395c67802 100644 --- a/module/plugins/hooks/ZeveraComHook.py +++ b/module/plugins/hooks/ZeveraComHook.py @@ -6,13 +6,13 @@ from module.plugins.internal.MultiHook import MultiHook class ZeveraComHook(MultiHook): __name__ = "ZeveraComHook" __type__ = "hook" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" - __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), - ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ), - ("revertfailed" , "bool" , "Revert to standard download if fails", True ), - ("reload" , "bool" , "Reload plugin list" , True ), - ("reloadinterval", "int" , "Reload interval in hours" , 12 )] + __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), + ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), + ("reload" , "bool" , "Reload plugin list" , True ), + ("reloadinterval", "int" , "Reload interval in hours" , 12 )] __description__ = """Zevera.com hook plugin""" __license__ = "GPLv3" @@ -20,6 +20,6 @@ class ZeveraComHook(MultiHook): ("Walter Purcaro", "vuolter@gmail.com" )] - def getHosters(self): + def get_hosters(self): html = self.account.api_response(pyreq.getHTTPRequest(timeout=120), cmd="gethosters") return [x.strip() for x in html.split(",")] diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py index 2ed09f58c..753712d5c 100644 --- a/module/plugins/hoster/AlldebridCom.py +++ b/module/plugins/hoster/AlldebridCom.py @@ -5,16 +5,18 @@ import urllib from module.common.json_layer import json_loads from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo -from module.utils import parseFileSize +from module.utils import parseFileSize as parse_size class AlldebridCom(MultiHoster): __name__ = "AlldebridCom" __type__ = "hoster" - __version__ = "0.46" + __version__ = "0.48" + __status__ = "testing" __pattern__ = r'https?://(?:www\.|s\d+\.)?alldebrid\.com/dl/[\w^_]+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Alldebrid.com multi-hoster plugin""" __license__ = "GPLv3" @@ -22,33 +24,28 @@ class AlldebridCom(MultiHoster): def setup(self): - self.chunkLimit = 16 + self.chunk_limit = 16 - def handlePremium(self, pyfile): - password = self.getPassword() + def handle_premium(self, pyfile): + password = self.get_password() data = json_loads(self.load("http://www.alldebrid.com/service.php", get={'link': pyfile.url, 'json': "true", 'pw': password})) - self.logDebug("Json data", data) + self.log_debug("Json data", data) if data['error']: if data['error'] == "This link isn't available on the hoster website.": self.offline() else: - self.logWarning(data['error']) - self.tempOffline() + self.log_warning(data['error']) + self.temp_offline() else: if pyfile.name and not pyfile.name.endswith('.tmp'): pyfile.name = data['filename'] - pyfile.size = parseFileSize(data['filesize']) + pyfile.size = parse_size(data['filesize']) self.link = data['link'] - if self.getConfig('ssl'): - self.link = self.link.replace("http://", "https://") - else: - self.link = self.link.replace("https://", "http://") - getInfo = create_getInfo(AlldebridCom) diff --git a/module/plugins/hoster/AndroidfilehostCom.py b/module/plugins/hoster/AndroidfilehostCom.py index 08005de0f..3fb77f83e 100644 --- a/module/plugins/hoster/AndroidfilehostCom.py +++ b/module/plugins/hoster/AndroidfilehostCom.py @@ -11,7 +11,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class AndroidfilehostCom(SimpleHoster): __name__ = "AndroidfilehostCom" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?androidfilehost\.com/\?fid=\d+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -32,33 +33,31 @@ class AndroidfilehostCom(SimpleHoster): def setup(self): self.multiDL = True - self.resumeDownload = True - self.chunkLimit = 1 + self.resume_download = True + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): wait = re.search(self.WAIT_PATTERN, self.html) - self.logDebug("Waiting time: %s seconds" % wait.group(1)) + self.log_debug("Waiting time: %s seconds" % wait.group(1)) fid = re.search(r'id="fid" value="(\d+)" />', self.html).group(1) - self.logDebug("fid: %s" % fid) + self.log_debug("fid: %s" % fid) html = self.load("https://www.androidfilehost.com/libs/otf/mirrors.otf.php", post={'submit': 'submit', 'action': 'getdownloadmirrors', - 'fid' : fid}, - decode=True) + 'fid' : fid}) self.link = re.findall('"url":"(.*?)"', html)[0].replace("\\", "") mirror_host = self.link.split("/")[2] - self.logDebug("Mirror Host: %s" % mirror_host) + self.log_debug("Mirror Host: %s" % mirror_host) html = self.load("https://www.androidfilehost.com/libs/otf/stats.otf.php", get={'fid' : fid, 'w' : 'download', - 'mirror': mirror_host}, - decode=True) + 'mirror': mirror_host}) getInfo = create_getInfo(AndroidfilehostCom) diff --git a/module/plugins/hoster/BasePlugin.py b/module/plugins/hoster/BasePlugin.py index 2228516aa..2e9ae4e48 100644 --- a/module/plugins/hoster/BasePlugin.py +++ b/module/plugins/hoster/BasePlugin.py @@ -5,14 +5,15 @@ import urllib import urlparse from module.network.HTTPRequest import BadHeader -from module.plugins.internal.SimpleHoster import create_getInfo, getFileURL -from module.plugins.Hoster import Hoster +from module.plugins.internal.SimpleHoster import create_getInfo +from module.plugins.internal.Hoster import Hoster class BasePlugin(Hoster): __name__ = "BasePlugin" __type__ = "hoster" - __version__ = "0.43" + __version__ = "0.45" + __status__ = "testing" __pattern__ = r'^unmatchable$' @@ -23,7 +24,7 @@ class BasePlugin(Hoster): @classmethod - def getInfo(cls, url="", html=""): #@TODO: Move to hoster class in 0.4.10 + def get_info(cls, url="", html=""): #@TODO: Move to hoster class in 0.4.10 url = urllib.unquote(url) url_p = urlparse.urlparse(url) return {'name' : (url_p.path.split('/')[-1] @@ -35,22 +36,23 @@ class BasePlugin(Hoster): def setup(self): - self.chunkLimit = -1 + self.chunk_limit = -1 self.multiDL = True - self.resumeDownload = True + self.resume_download = True def process(self, pyfile): - """main function""" - - pyfile.name = self.getInfo(pyfile.url)['name'] + """ + Main function + """ + pyfile.name = self.get_info(pyfile.url)['name'] if not pyfile.url.startswith("http"): self.fail(_("No plugin matched")) for _i in xrange(5): try: - link = getFileURL(self, urllib.unquote(pyfile.url)) + link = self.direct_link(urllib.unquote(pyfile.url)) if link: self.download(link, ref=False, disposition=True) @@ -58,21 +60,21 @@ class BasePlugin(Hoster): self.fail(_("File not found")) except BadHeader, e: - if e.code is 404: + if e.code == 404: self.offline() elif e.code in (401, 403): - self.logDebug("Auth required", "Received HTTP status code: %d" % e.code) + self.log_debug("Auth required", "Received HTTP status code: %d" % e.code) - account = self.core.accountManager.getAccountPlugin('Http') - servers = [x['login'] for x in account.getAllAccounts()] + account = self.pyload.accountManager.getAccountPlugin('Http') + servers = [x['login'] for x in account.getAllAccounts()] #@TODO: Recheck in 0.4.10 server = urlparse.urlparse(pyfile.url).netloc if server in servers: - self.logDebug("Logging on to %s" % server) - self.req.addAuth(account.getAccountData(server)['password']) + self.log_debug("Logging on to %s" % server) + self.req.addAuth(account.get_info(server)['login']['password']) else: - pwd = self.getPassword() + pwd = self.get_password() if ':' in pwd: self.req.addAuth(pwd) else: @@ -84,7 +86,7 @@ class BasePlugin(Hoster): else: self.fail(_("No file downloaded")) #@TODO: Move to hoster class in 0.4.10 - errmsg = self.checkDownload({'Empty file' : re.compile(r'\A\s*\Z'), + errmsg = self.check_download({'Empty file' : re.compile(r'\A\s*\Z'), 'Html error' : re.compile(r'\A(?:\s*<.+>)?((?:[\w\s]*(?:[Ee]rror|ERROR)\s*\:?)?\s*\d{3})(?:\Z|\s+)'), 'Html file' : re.compile(r'\A\s*<!DOCTYPE html'), 'Request error': re.compile(r'([Aa]n error occured while processing your request)')}) @@ -92,11 +94,11 @@ class BasePlugin(Hoster): return try: - errmsg += " | " + self.lastCheck.group(1).strip() + errmsg += " | " + self.last_check.group(1).strip() except Exception: pass - self.logWarning("Check result: " + errmsg, "Waiting 1 minute and retry") + self.log_warning(_("Check result: ") + errmsg, _("Waiting 1 minute and retry")) self.retry(3, 60, errmsg) diff --git a/module/plugins/hoster/BasketbuildCom.py b/module/plugins/hoster/BasketbuildCom.py index 89e4d39f9..9bbd0ea60 100644 --- a/module/plugins/hoster/BasketbuildCom.py +++ b/module/plugins/hoster/BasketbuildCom.py @@ -12,12 +12,13 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class BasketbuildCom(SimpleHoster): __name__ = "BasketbuildCom" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(?:\w\.)?basketbuild\.com/filedl/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] - __description__ = """basketbuild.com hoster plugin""" + __description__ = """Basketbuild.com hoster plugin""" __license__ = "GPLv3" __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")] @@ -29,11 +30,11 @@ class BasketbuildCom(SimpleHoster): def setup(self): self.multiDL = True - self.resumeDownload = True - self.chunkLimit = 1 + self.resume_download = True + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): try: link1 = re.search(r'href="(.+dlgate/.+)"', self.html).group(1) self.html = self.load(link1) @@ -42,15 +43,15 @@ class BasketbuildCom(SimpleHoster): self.error(_("Hop #1 not found")) else: - self.logDebug("Next hop: %s" % link1) + self.log_debug("Next hop: %s" % link1) try: wait = re.search(r'var sec = (\d+)', self.html).group(1) - self.logDebug("Wait %s seconds" % wait) + self.log_debug("Wait %s seconds" % wait) self.wait(wait) except AttributeError: - self.logDebug("No wait time found") + self.log_debug("No wait time found") try: self.link = re.search(r'id="dlLink">\s*<a href="(.+?)"', self.html).group(1) diff --git a/module/plugins/hoster/BayfilesCom.py b/module/plugins/hoster/BayfilesCom.py index cccd4acc7..6e9397d4f 100644 --- a/module/plugins/hoster/BayfilesCom.py +++ b/module/plugins/hoster/BayfilesCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class BayfilesCom(DeadHoster): __name__ = "BayfilesCom" __type__ = "hoster" - __version__ = "0.09" + __version__ = "0.10" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?bayfiles\.(com|net)/file/(?P<ID>\w+/\w+/[^/]+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/BezvadataCz.py b/module/plugins/hoster/BezvadataCz.py index b47c2902d..d2af8272a 100644 --- a/module/plugins/hoster/BezvadataCz.py +++ b/module/plugins/hoster/BezvadataCz.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class BezvadataCz(SimpleHoster): __name__ = "BezvadataCz" __type__ = "hoster" - __version__ = "0.27" + __version__ = "0.29" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?bezvadata\.cz/stahnout/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -24,22 +25,22 @@ class BezvadataCz(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - def handleFree(self, pyfile): - #download button + def handle_free(self, pyfile): + #: Download button m = re.search(r'<a class="stahnoutSoubor".*?href="(.*?)"', self.html) if m is None: self.error(_("Page 1 URL not found")) url = "http://bezvadata.cz%s" % m.group(1) - #captcha form + #: Captcha form self.html = self.load(url) - self.checkErrors() + self.check_errors() for _i in xrange(5): - action, inputs = self.parseHtmlForm('frm-stahnoutFreeForm') + action, inputs = self.parse_html_form('frm-stahnoutFreeForm') if not inputs: self.error(_("FreeForm")) @@ -47,31 +48,26 @@ class BezvadataCz(SimpleHoster): if m is None: self.error(_("Wrong captcha image")) - #captcha image is contained in html page as base64encoded data but decryptCaptcha() expects image url - self.load, proper_load = self.loadcaptcha, self.load - try: - inputs['captcha'] = self.decryptCaptcha(m.group(1), imgtype='png') - finally: - self.load = proper_load + inputs['captcha'] = self.captcha._decrypt(m.group(1).decode('base64'), input_type='png') if '<img src="data:image/png;base64' in self.html: - self.invalidCaptcha() + self.captcha.invalid() else: - self.correctCaptcha() + self.captcha.correct() break else: self.fail(_("No valid captcha code entered")) - #download url + #: Download url self.html = self.load("http://bezvadata.cz%s" % action, post=inputs) - self.checkErrors() + self.check_errors() m = re.search(r'<a class="stahnoutSoubor2" href="(.*?)">', self.html) if m is None: self.error(_("Page 2 URL not found")) url = "http://bezvadata.cz%s" % m.group(1) - self.logDebug("DL URL %s" % url) + self.log_debug("DL URL %s" % url) - #countdown + #: countdown m = re.search(r'id="countdown">(\d\d):(\d\d)<', self.html) wait_time = (int(m.group(1)) * 60 + int(m.group(2))) if m else 120 self.wait(wait_time, False) @@ -79,17 +75,13 @@ class BezvadataCz(SimpleHoster): self.link = url - def checkErrors(self): + def check_errors(self): if 'images/button-download-disable.png' in self.html: - self.longWait(5 * 60, 24) #: parallel dl limit + self.wait(5 * 60, 24, _("Download limit reached")) #: Parallel dl limit elif '<div class="infobox' in self.html: - self.tempOffline() + self.temp_offline() else: - return super(BezvadataCz, self).checkErrors() - - - def loadcaptcha(self, data, *args, **kwargs): - return data.decode('base64') + return super(BezvadataCz, self).check_errors() getInfo = create_getInfo(BezvadataCz) diff --git a/module/plugins/hoster/BillionuploadsCom.py b/module/plugins/hoster/BillionuploadsCom.py index d0fbd7a8b..a142f4ab3 100644 --- a/module/plugins/hoster/BillionuploadsCom.py +++ b/module/plugins/hoster/BillionuploadsCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class BillionuploadsCom(DeadHoster): __name__ = "BillionuploadsCom" __type__ = "hoster" - __version__ = "0.06" + __version__ = "0.07" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?billionuploads\.com/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/BitshareCom.py b/module/plugins/hoster/BitshareCom.py index 5c709e4f7..b975a8ab0 100644 --- a/module/plugins/hoster/BitshareCom.py +++ b/module/plugins/hoster/BitshareCom.py @@ -4,14 +4,15 @@ from __future__ import with_statement import re -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class BitshareCom(SimpleHoster): __name__ = "BitshareCom" __type__ = "hoster" - __version__ = "0.54" + __version__ = "0.55" + __status__ = "testing" __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)] @@ -33,32 +34,32 @@ class BitshareCom(SimpleHoster): def setup(self): self.multiDL = self.premium - self.chunkLimit = 1 + self.chunk_limit = 1 def process(self, pyfile): if self.premium: self.account.relogin(self.user) - # File id + #: File id m = re.match(self.__pattern__, pyfile.url) self.file_id = max(m.group('ID1'), m.group('ID2')) - self.logDebug("File id is [%s]" % self.file_id) + self.log_debug("File id is [%s]" % self.file_id) - # Load main page - self.html = self.load(pyfile.url, ref=False, decode=True) + #: Load main page + self.html = self.load(pyfile.url, ref=False) - # Check offline + #: Check offline if re.search(self.OFFLINE_PATTERN, self.html): self.offline() - # Check Traffic used up + #: Check Traffic used up if re.search(self.TRAFFIC_USED_UP, self.html): - self.logInfo(_("Your Traffic is used up for today")) + self.log_info(_("Your Traffic is used up for today")) self.wait(30 * 60, True) self.retry() - # File name + #: File name m = re.match(self.__pattern__, pyfile.url) name1 = m.group('NAME') if m else None @@ -67,77 +68,77 @@ class BitshareCom(SimpleHoster): pyfile.name = max(name1, name2) - # Ajax file id + #: Ajax file id self.ajaxid = re.search(self.AJAXID_PATTERN, self.html).group(1) - self.logDebug("File ajax id is [%s]" % self.ajaxid) + self.log_debug("File ajax id is [%s]" % self.ajaxid) - # This may either download our file or forward us to an error page - self.link = self.getDownloadUrl() + #: This may either download our file or forward us to an error page + self.link = self.get_download_url() - if self.checkDownload({"error": ">Error occured<"}): + if self.check_download({'error': ">Error occured<"}): self.retry(5, 5 * 60, "Bitshare host : Error occured") - def getDownloadUrl(self): - # Return location if direct download is active + def get_download_url(self): + #: Return location if direct download is active if self.premium: header = self.load(self.pyfile.url, just_header=True) if 'location' in header: return header['location'] - # Get download info - self.logDebug("Getting download info") + #: Get download info + self.log_debug("Getting download info") res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html", - post={"request": "generateID", "ajaxid": self.ajaxid}) + post={'request': "generateID", 'ajaxid': self.ajaxid}) - self.handleErrors(res, ':') + self.handle_errors(res, ':') parts = res.split(":") filetype = parts[0] wait = int(parts[1]) captcha = int(parts[2]) - self.logDebug("Download info [type: '%s', waiting: %d, captcha: %d]" % (filetype, wait, captcha)) + self.log_debug("Download info [type: '%s', waiting: %d, captcha: %d]" % (filetype, wait, captcha)) - # Waiting + #: Waiting if wait > 0: - self.logDebug("Waiting %d seconds." % wait) + self.log_debug("Waiting %d seconds." % wait) if wait < 120: self.wait(wait, False) else: self.wait(wait - 55, True) self.retry() - # Resolve captcha + #: Resolve captcha if captcha == 1: - self.logDebug("File is captcha protected") + self.log_debug("File is captcha protected") recaptcha = ReCaptcha(self) - # Try up to 3 times + #: Try up to 3 times for i in xrange(3): response, challenge = recaptcha.challenge() res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html", - post={"request" : "validateCaptcha", - "ajaxid" : self.ajaxid, - "recaptcha_challenge_field": challenge, - "recaptcha_response_field" : response}) - if self.handleCaptchaErrors(res): + post={'request' : "validateCaptcha", + 'ajaxid' : self.ajaxid, + 'recaptcha_challenge_field': challenge, + 'recaptcha_response_field' : response}) + if self.handle_captcha_errors(res): break - # Get download URL - self.logDebug("Getting download url") + #: Get download URL + self.log_debug("Getting download url") res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html", - post={"request": "getDownloadURL", "ajaxid": self.ajaxid}) + post={'request': "getDownloadURL", 'ajaxid': self.ajaxid}) - self.handleErrors(res, '#') + self.handle_errors(res, '#') url = res.split("#")[-1] return url - def handleErrors(self, res, separator): - self.logDebug("Checking response [%s]" % res) + def handle_errors(self, res, separator): + self.log_debug("Checking response [%s]" % res) if "ERROR:Session timed out" in res: self.retry() elif "ERROR" in res: @@ -145,15 +146,15 @@ class BitshareCom(SimpleHoster): self.fail(msg) - def handleCaptchaErrors(self, res): - self.logDebug("Result of captcha resolving [%s]" % res) + def handle_captcha_errors(self, res): + self.log_debug("Result of captcha resolving [%s]" % res) if "SUCCESS" in res: - self.correctCaptcha() + self.captcha.correct() return True elif "ERROR:SESSION ERROR" in res: self.retry() - self.invalidCaptcha() + self.captcha.invalid() getInfo = create_getInfo(BitshareCom) diff --git a/module/plugins/hoster/BoltsharingCom.py b/module/plugins/hoster/BoltsharingCom.py index db813ba2e..c33049e01 100644 --- a/module/plugins/hoster/BoltsharingCom.py +++ b/module/plugins/hoster/BoltsharingCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class BoltsharingCom(DeadHoster): __name__ = "BoltsharingCom" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?boltsharing\.com/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/CatShareNet.py b/module/plugins/hoster/CatShareNet.py index c966dbe1a..5b7d61e05 100644 --- a/module/plugins/hoster/CatShareNet.py +++ b/module/plugins/hoster/CatShareNet.py @@ -3,13 +3,14 @@ import re from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha class CatShareNet(SimpleHoster): __name__ = "CatShareNet" __type__ = "hoster" - __version__ = "0.15" + __version__ = "0.16" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?catshare\.net/\w{16}' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -21,8 +22,6 @@ class CatShareNet(SimpleHoster): ("Walter Purcaro", "vuolter@gmail.com")] - TEXT_ENCODING = True - INFO_PATTERN = r'<title>(?P<N>.+) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)<' OFFLINE_PATTERN = r'<div class="alert alert-error"' @@ -35,10 +34,10 @@ class CatShareNet(SimpleHoster): def setup(self): self.multiDL = self.premium - self.resumeDownload = True + self.resume_download = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): recaptcha = ReCaptcha(self) response, challenge = recaptcha.challenge() diff --git a/module/plugins/hoster/CloudzerNet.py b/module/plugins/hoster/CloudzerNet.py index af40b8d5f..fa0bccba3 100644 --- a/module/plugins/hoster/CloudzerNet.py +++ b/module/plugins/hoster/CloudzerNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class CloudzerNet(DeadHoster): __name__ = "CloudzerNet" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(cloudzer\.net/file/|clz\.to/(file/)?)\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/CloudzillaTo.py b/module/plugins/hoster/CloudzillaTo.py index 09453137d..60c66960d 100644 --- a/module/plugins/hoster/CloudzillaTo.py +++ b/module/plugins/hoster/CloudzillaTo.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class CloudzillaTo(SimpleHoster): __name__ = "CloudzillaTo" __type__ = "hoster" - __version__ = "0.07" + __version__ = "0.08" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?cloudzilla\.to/share/file/(?P<ID>[\w^_]+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -24,9 +25,9 @@ class CloudzillaTo(SimpleHoster): PASSWORD_PATTERN = r'<div id="pwd_protected">' - def checkErrors(self): + def check_errors(self): if re.search(self.PASSWORD_PATTERN, self.html): - pw = self.getPassword() + pw = self.get_password() if pw: self.html = self.load(self.pyfile.url, get={'key': pw}) else: @@ -35,16 +36,16 @@ class CloudzillaTo(SimpleHoster): if re.search(self.PASSWORD_PATTERN, self.html): self.retry(reason="Wrong password") else: - return super(CloudzillaTo, self).checkErrors() + return super(CloudzillaTo, self).check_errors() - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.html = self.load("http://www.cloudzilla.to/generateticket/", - post={'file_id': self.info['pattern']['ID'], 'key': self.getPassword()}) + post={'file_id': self.info['pattern']['ID'], 'key': self.get_password()}) ticket = dict(re.findall(r'<(.+?)>([^<>]+?)</', self.html)) - self.logDebug(ticket) + self.log_debug(ticket) if 'error' in ticket: if "File is password protected" in ticket['error']: @@ -60,8 +61,8 @@ class CloudzillaTo(SimpleHoster): 'ticket_id': ticket['ticket_id']} - def handlePremium(self, pyfile): - return self.handleFree(pyfile) + def handle_premium(self, pyfile): + return self.handle_free(pyfile) getInfo = create_getInfo(CloudzillaTo) diff --git a/module/plugins/hoster/CramitIn.py b/module/plugins/hoster/CramitIn.py index 44dac958d..f14ae0c71 100644 --- a/module/plugins/hoster/CramitIn.py +++ b/module/plugins/hoster/CramitIn.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class CramitIn(XFSHoster): __name__ = "CramitIn" __type__ = "hoster" - __version__ = "0.07" + __version__ = "0.08" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?cramit\.in/\w{12}' diff --git a/module/plugins/hoster/CrockoCom.py b/module/plugins/hoster/CrockoCom.py index 098ba5fab..8f092ad0c 100644 --- a/module/plugins/hoster/CrockoCom.py +++ b/module/plugins/hoster/CrockoCom.py @@ -3,14 +3,15 @@ import re import urlparse -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class CrockoCom(SimpleHoster): __name__ = "CrockoCom" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.21" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(crocko|easy-share)\.com/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -32,7 +33,7 @@ class CrockoCom(SimpleHoster): NAME_REPLACEMENTS = [(r'<.*?>', '')] - def handleFree(self, pyfile): + def handle_free(self, pyfile): if "You need Premium membership to download this file." in self.html: self.fail(_("You need Premium membership to download this file")) @@ -57,8 +58,8 @@ class CrockoCom(SimpleHoster): inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge() self.download(action, post=inputs) - if self.checkDownload({"captcha": recaptcha.KEY_AJAX_PATTERN}): - self.invalidCaptcha() + if self.check_download({'captcha': recaptcha.KEY_AJAX_PATTERN}): + self.captcha.invalid() else: break else: diff --git a/module/plugins/hoster/CyberlockerCh.py b/module/plugins/hoster/CyberlockerCh.py index 9d748bf85..8cb9f7851 100644 --- a/module/plugins/hoster/CyberlockerCh.py +++ b/module/plugins/hoster/CyberlockerCh.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class CyberlockerCh(DeadHoster): __name__ = "CyberlockerCh" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?cyberlocker\.ch/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/CzshareCom.py b/module/plugins/hoster/CzshareCom.py index 8f72f2148..3d2de5f7f 100644 --- a/module/plugins/hoster/CzshareCom.py +++ b/module/plugins/hoster/CzshareCom.py @@ -6,13 +6,14 @@ import re from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from module.utils import parseFileSize +from module.utils import parseFileSize as parse_size class CzshareCom(SimpleHoster): __name__ = "CzshareCom" __type__ = "hoster" - __version__ = "0.99" + __version__ = "1.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(czshare|sdilej)\.(com|cz)/(\d+/|download\.php\?).+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -39,58 +40,58 @@ class CzshareCom(SimpleHoster): USER_CREDIT_PATTERN = r'<div class="credit">\s*kredit: <strong>([\d .,]+)(\w+)</strong>\s*</div><!-- .credit -->' - def checkTrafficLeft(self): - # check if user logged in + def check_traffic_left(self): + #: Check if user logged in m = re.search(self.USER_CREDIT_PATTERN, self.html) if m is None: self.account.relogin(self.user) - self.html = self.load(self.pyfile.url, decode=True) + self.html = self.load(self.pyfile.url) m = re.search(self.USER_CREDIT_PATTERN, self.html) if m is None: return False - # check user credit + #: Check user credit try: - credit = parseFileSize(m.group(1).replace(' ', ''), m.group(2)) - self.logInfo(_("Premium download for %i KiB of Credit") % (self.pyfile.size / 1024)) - self.logInfo(_("User %s has %i KiB left") % (self.user, credit / 1024)) + credit = parse_size(m.group(1).replace(' ', ''), m.group(2)) + self.log_info(_("Premium download for %i KiB of Credit") % (self.pyfile.size / 1024)) + self.log_info(_("User %s has %i KiB left") % (self.user, credit / 1024)) if credit < self.pyfile.size: - self.logInfo(_("Not enough credit to download file: %s") % self.pyfile.name) + self.log_info(_("Not enough credit to download file: %s") % self.pyfile.name) return False except Exception, e: - # let's continue and see what happens... - self.logError(e) + #: let's continue and see what happens... + self.log_error(e) return True - def handlePremium(self, pyfile): - # parse download link + def handle_premium(self, pyfile): + #: Parse download link try: form = re.search(self.PREMIUM_FORM_PATTERN, self.html, re.S).group(1) inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form)) except Exception, e: - self.logError(e) - self.resetAccount() + self.log_error(e) + self.restart(nopremium=True) - # download the file, destination is determined by pyLoad + #: Download the file, destination is determined by pyLoad self.download("http://sdilej.cz/profi_down.php", post=inputs, disposition=True) - def handleFree(self, pyfile): - # get free url + def handle_free(self, pyfile): + #: Get free url m = re.search(self.FREE_URL_PATTERN, self.html) if m is None: self.error(_("FREE_URL_PATTERN not found")) parsed_url = "http://sdilej.cz" + m.group(1) - self.logDebug("PARSED_URL:" + parsed_url) + self.log_debug("PARSED_URL:" + parsed_url) - # get download ticket and parse html - self.html = self.load(parsed_url, decode=True) + #: Get download ticket and parse html + self.html = self.load(parsed_url) if re.search(self.MULTIDL_PATTERN, self.html): - self.longWait(5 * 60, 12) + self.wait(5 * 60, 12, _("Download limit reached")) try: form = re.search(self.FREE_FORM_PATTERN, self.html, re.S).group(1) @@ -98,32 +99,32 @@ class CzshareCom(SimpleHoster): pyfile.size = int(inputs['size']) except Exception, e: - self.logError(e) + self.log_error(e) self.error(_("Form")) - # get and decrypt captcha + #: Get and decrypt captcha captcha_url = 'http://sdilej.cz/captcha.php' for _i in xrange(5): - inputs['captchastring2'] = self.decryptCaptcha(captcha_url) - self.html = self.load(parsed_url, post=inputs, decode=True) + inputs['captchastring2'] = self.captcha.decrypt(captcha_url) + self.html = self.load(parsed_url, post=inputs) if u"<li>ZadanÃœ ovÄÅovacà kód nesouhlasÃ!</li>" in self.html: - self.invalidCaptcha() + self.captcha.invalid() elif re.search(self.MULTIDL_PATTERN, self.html): - self.longWait(5 * 60, 12) + self.wait(5 * 60, 12, _("Download limit reached")) else: - self.correctCaptcha() + self.captcha.correct() break else: self.fail(_("No valid captcha code entered")) m = re.search("countdown_number = (\d+);", self.html) - self.setWait(int(m.group(1)) if m else 50) + self.set_wait(int(m.group(1)) if m else 50) - # download the file, destination is determined by pyLoad - self.logDebug("WAIT URL", self.req.lastEffectiveURL) + #: Download the file, destination is determined by pyLoad + self.log_debug("WAIT URL", self.req.lastEffectiveURL) m = re.search("free_wait.php\?server=(.*?)&(.*)", self.req.lastEffectiveURL) if m is None: @@ -134,29 +135,29 @@ class CzshareCom(SimpleHoster): self.wait() - def checkFile(self, rules={}): - # check download - check = self.checkDownload({ + def check_file(self): + #: Check download + check = self.check_download({ "temp offline" : re.compile(r"^Soubor je do.*asn.* nedostupn.*$"), - "credit" : re.compile(r"^Nem.*te dostate.*n.* kredit.$"), + 'credit' : re.compile(r"^Nem.*te dostate.*n.* kredit.$"), "multi-dl" : re.compile(self.MULTIDL_PATTERN), - "captcha" : "<li>ZadanÃœ ovÄÅovacà kód nesouhlasÃ!</li>" + 'captcha' : "<li>ZadanÃœ ovÄÅovacà kód nesouhlasÃ!</li>" }) if check == "temp offline": self.fail(_("File not available - try later")) elif check == "credit": - self.resetAccount() + self.restart(nopremium=True) elif check == "multi-dl": - self.longWait(5 * 60, 12) + self.wait(5 * 60, 12, _("Download limit reached")) elif check == "captcha": - self.invalidCaptcha() + self.captcha.invalid() self.retry() - return super(CzshareCom, self).checkFile(rules) + return super(CzshareCom, self).check_file() getInfo = create_getInfo(CzshareCom) diff --git a/module/plugins/hoster/DailymotionCom.py b/module/plugins/hoster/DailymotionCom.py index c6939e5e5..63003dc06 100644 --- a/module/plugins/hoster/DailymotionCom.py +++ b/module/plugins/hoster/DailymotionCom.py @@ -4,19 +4,19 @@ import re from module.PyFile import statusMap from module.common.json_layer import json_loads -from module.network.RequestFactory import getURL -from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL as get_url +from module.plugins.internal.Hoster import Hoster -def getInfo(urls): +def get_info(urls): result = [] regex = re.compile(DailymotionCom.__pattern__) apiurl = "https://api.dailymotion.com/video/%s" - request = {"fields": "access_error,status,title"} + request = {'fields': "access_error,status,title"} for url in urls: id = regex.match(url).group('ID') - html = getURL(apiurl % id, get=request) + html = get_url(apiurl % id, get=request) info = json_loads(html) name = info['title'] + ".mp4" if "title" in info else url @@ -40,7 +40,8 @@ def getInfo(urls): class DailymotionCom(Hoster): __name__ = "DailymotionCom" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?dailymotion\.com/.*video/(?P<ID>[\w^_]+)' __config__ = [("quality", "Lowest;LD 144p;LD 240p;SD 384p;HQ 480p;HD 720p;HD 1080p;Highest", "Quality", "Highest")] @@ -51,11 +52,11 @@ class DailymotionCom(Hoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - def getStreams(self): + def get_streams(self): streams = [] for result in re.finditer(r"\"(?P<URL>http:\\/\\/www.dailymotion.com\\/cdn\\/H264-(?P<QF>.*?)\\.*?)\"", @@ -71,8 +72,8 @@ class DailymotionCom(Hoster): return sorted(streams, key=lambda x: x[0][::-1]) - def getQuality(self): - q = self.getConfig('quality') + def get_quality(self): + q = self.get_config('quality') if q == "Lowest": quality = 0 @@ -84,7 +85,7 @@ class DailymotionCom(Hoster): return quality - def getLink(self, streams, quality): + def get_link(self, streams, quality): if quality > 0: for x, s in [item for item in enumerate(streams)][::-1]: qf = s[0][1] @@ -98,28 +99,28 @@ class DailymotionCom(Hoster): s = streams[idx] - self.logInfo(_("Download video quality %sx%s") % s[0]) + self.log_info(_("Download video quality %sx%s") % s[0]) return s[1] - def checkInfo(self, pyfile): - pyfile.name, pyfile.size, pyfile.status, pyfile.url = getInfo([pyfile.url])[0] + def check_info(self, pyfile): + pyfile.name, pyfile.size, pyfile.status, pyfile.url = get_info([pyfile.url])[0] if pyfile.status == 1: self.offline() elif pyfile.status == 6: - self.tempOffline() + self.temp_offline() def process(self, pyfile): - self.checkInfo(pyfile) + self.check_info(pyfile) id = re.match(self.__pattern__, pyfile.url).group('ID') - self.html = self.load("http://www.dailymotion.com/embed/video/" + id, decode=True) + self.html = self.load("http://www.dailymotion.com/embed/video/" + id) - streams = self.getStreams() - quality = self.getQuality() + streams = self.get_streams() + quality = self.get_quality() - self.download(self.getLink(streams, quality)) + self.download(self.get_link(streams, quality)) diff --git a/module/plugins/hoster/DataHu.py b/module/plugins/hoster/DataHu.py index 955c94437..c0f1e4aa4 100644 --- a/module/plugins/hoster/DataHu.py +++ b/module/plugins/hoster/DataHu.py @@ -11,7 +11,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DataHu(SimpleHoster): __name__ = "DataHu" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?data\.hu/get/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -28,7 +29,7 @@ class DataHu(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = self.premium diff --git a/module/plugins/hoster/DataportCz.py b/module/plugins/hoster/DataportCz.py index ad514f5eb..15caae1f7 100644 --- a/module/plugins/hoster/DataportCz.py +++ b/module/plugins/hoster/DataportCz.py @@ -6,7 +6,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DataportCz(SimpleHoster): __name__ = "DataportCz" __type__ = "hoster" - __version__ = "0.41" + __version__ = "0.42" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?dataport\.cz/file/(.+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -24,12 +25,12 @@ class DataportCz(SimpleHoster): FREE_SLOTS_PATTERN = ur'PoÄet volnÃœch slotů: <span class="darkblue">(\d+)</span><br />' - def handleFree(self, pyfile): - captchas = {"1": "jkeG", "2": "hMJQ", "3": "vmEK", "4": "ePQM", "5": "blBd"} + def handle_free(self, pyfile): + captchas = {'1': "jkeG", '2': "hMJQ", '3': "vmEK", '4': "ePQM", '5': "blBd"} for _i in xrange(60): - action, inputs = self.parseHtmlForm('free_download_form') - self.logDebug(action, inputs) + action, inputs = self.parse_html_form('free_download_form') + self.log_debug(action, inputs) if not action or not inputs: self.error(_("free_download_form")) @@ -40,15 +41,15 @@ class DataportCz(SimpleHoster): self.download("http://www.dataport.cz%s" % action, post=inputs) - check = self.checkDownload({"captcha": 'alert("\u0160patn\u011b opsan\u00fd k\u00f3d z obr\u00e1zu");', - "slot" : 'alert("Je n\u00e1m l\u00edto, ale moment\u00e1ln\u011b nejsou'}) + check = self.check_download({'captcha': 'alert("\u0160patn\u011b opsan\u00fd k\u00f3d z obr\u00e1zu");', + 'slot' : 'alert("Je n\u00e1m l\u00edto, ale moment\u00e1ln\u011b nejsou'}) if check == "captcha": self.error(_("invalid captcha")) elif check == "slot": - self.logDebug("No free slots - wait 60s and retry") + self.log_debug("No free slots - wait 60s and retry") self.wait(60, False) - self.html = self.load(pyfile.url, decode=True) + self.html = self.load(pyfile.url) continue else: diff --git a/module/plugins/hoster/DateiTo.py b/module/plugins/hoster/DateiTo.py index 92a96b9ec..d90fc5864 100644 --- a/module/plugins/hoster/DateiTo.py +++ b/module/plugins/hoster/DateiTo.py @@ -2,14 +2,15 @@ import re -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DateiTo(SimpleHoster): __name__ = "DateiTo" __type__ = "hoster" - __version__ = "0.09" + __version__ = "0.10" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -29,21 +30,21 @@ class DateiTo(SimpleHoster): DATA_PATTERN = r'url: "(.*?)", data: "(.*?)",' - def handleFree(self, pyfile): + def handle_free(self, pyfile): url = 'http://datei.to/ajax/download.php' data = {'P': 'I', 'ID': self.info['pattern']['ID']} recaptcha = ReCaptcha(self) for _i in xrange(10): - self.logDebug("URL", url, "POST", data) + self.log_debug("URL", url, "POST", data) self.html = self.load(url, post=data) - self.checkErrors() + self.check_errors() if url.endswith('download.php') and 'P' in data: - if data['P'] == 'I': - self.doWait() + if data['P'] == "I": + self.do_wait() - elif data['P'] == 'IV': + elif data['P'] == "IV": break m = re.search(self.DATA_PATTERN, self.html) @@ -60,7 +61,7 @@ class DateiTo(SimpleHoster): self.link = self.html - def doWait(self): + def do_wait(self): m = re.search(self.WAIT_PATTERN, self.html) wait_time = int(m.group(1)) if m else 30 diff --git a/module/plugins/hoster/DdlstorageCom.py b/module/plugins/hoster/DdlstorageCom.py index 976d9ccf9..5a826452b 100644 --- a/module/plugins/hoster/DdlstorageCom.py +++ b/module/plugins/hoster/DdlstorageCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class DdlstorageCom(DeadHoster): __name__ = "DdlstorageCom" __type__ = "hoster" - __version__ = "1.02" + __version__ = "1.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?ddlstorage\.com/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/DebridItaliaCom.py b/module/plugins/hoster/DebridItaliaCom.py index 4f64215fa..7cf7c4663 100644 --- a/module/plugins/hoster/DebridItaliaCom.py +++ b/module/plugins/hoster/DebridItaliaCom.py @@ -8,10 +8,12 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class DebridItaliaCom(MultiHoster): __name__ = "DebridItaliaCom" __type__ = "hoster" - __version__ = "0.17" + __version__ = "0.19" + __status__ = "testing" __pattern__ = r'https?://(?:www\.|s\d+\.)?debriditalia\.com/dl/\d+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Debriditalia.com multi-hoster plugin""" __license__ = "GPLv3" @@ -22,9 +24,9 @@ class DebridItaliaCom(MultiHoster): URL_REPLACEMENTS = [("https://", "http://")] - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): self.html = self.load("http://www.debriditalia.com/api.php", - get={'generate': "on", 'link': pyfile.url, 'p': self.getPassword()}) + get={'generate': "on", 'link': pyfile.url, 'p': self.get_password()}) if "ERROR:" not in self.html: self.link = self.html.strip() @@ -34,7 +36,7 @@ class DebridItaliaCom(MultiHoster): self.html = self.load("http://debriditalia.com/linkgen2.php", post={'xjxfun' : "convertiLink", 'xjxargs[]': "S<![CDATA[%s]]>" % pyfile.url, - 'xjxargs[]': "S%s" % self.getPassword()}) + 'xjxargs[]': "S%s" % self.get_password()}) try: self.link = re.search(r'<a href="(.+?)"', self.html).group(1) except AttributeError: diff --git a/module/plugins/hoster/DepositfilesCom.py b/module/plugins/hoster/DepositfilesCom.py index 18f23f552..9d42935cb 100644 --- a/module/plugins/hoster/DepositfilesCom.py +++ b/module/plugins/hoster/DepositfilesCom.py @@ -3,14 +3,15 @@ import re import urllib -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DepositfilesCom(SimpleHoster): __name__ = "DepositfilesCom" __type__ = "hoster" - __version__ = "0.56" + __version__ = "0.57" + __status__ = "testing" __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)] @@ -40,18 +41,18 @@ class DepositfilesCom(SimpleHoster): LINK_MIRROR_PATTERN = r'class="repeat_mirror"><a href="(.+?)"' - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.html = self.load(pyfile.url, post={'gateway_result': "1"}) - self.checkErrors() + self.check_errors() m = re.search(r"var fid = '(\w+)';", self.html) if m is None: self.retry(wait_time=5) params = {'fid': m.group(1)} - self.logDebug("FID: %s" % params['fid']) + self.log_debug("FID: %s" % params['fid']) - self.checkErrors() + self.check_errors() recaptcha = ReCaptcha(self) captcha_key = recaptcha.detect_key() @@ -69,9 +70,9 @@ class DepositfilesCom(SimpleHoster): self.link = urllib.unquote(m.group(1)) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): if '<span class="html_download_api-gold_traffic_limit">' in self.html: - self.logWarning(_("Download limit reached")) + self.log_warning(_("Download limit reached")) self.retry(25, 60 * 60, "Download limit reached") elif 'onClick="show_gold_offer' in self.html: diff --git a/module/plugins/hoster/DevhostSt.py b/module/plugins/hoster/DevhostSt.py index e7a23f6b1..d999cdf96 100644 --- a/module/plugins/hoster/DevhostSt.py +++ b/module/plugins/hoster/DevhostSt.py @@ -11,12 +11,13 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DevhostSt(SimpleHoster): __name__ = "DevhostSt" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?d-h\.st/(?!users/)\w{3}' __config__ = [("use_premium", "bool", "Use premium account if available", True)] - __description__ = """d-h.st hoster plugin""" + __description__ = """D-h.st hoster plugin""" __license__ = "GPLv3" __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")] @@ -31,7 +32,7 @@ class DevhostSt(SimpleHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 + self.chunk_limit = 1 getInfo = create_getInfo(DevhostSt) diff --git a/module/plugins/hoster/DlFreeFr.py b/module/plugins/hoster/DlFreeFr.py index 030f7e971..f9d427c1b 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.AdYouLike import AdYouLike from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns @@ -36,7 +35,8 @@ class CustomBrowser(Browser): class DlFreeFr(SimpleHoster): __name__ = "DlFreeFr" __type__ = "hoster" - __version__ = "0.29" + __version__ = "0.32" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?dl\.free\.fr/(\w+|getfile\.pl\?file=/\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -44,24 +44,24 @@ 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é' def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True self.limitDL = 5 - self.chunkLimit = 1 + self.chunk_limit = 1 def init(self): - factory = self.core.requestFactory + factory = self.pyload.requestFactory self.req = CustomBrowser(factory.bucket, factory.getOptions()) @@ -77,13 +77,15 @@ class DlFreeFr(SimpleHoster): if headers.get('code') == 200: content_type = headers.get('content-type') if content_type and content_type.startswith("text/html"): - # Undirect acces to requested file, with a web page providing it (captcha) + #: Undirect acces to requested file, with a web page providing it (captcha) self.html = self.load(valid_url) - self.handleFree(pyfile) + self.handle_free(pyfile) else: - # Direct access to requested file for users using free.fr as Internet Service Provider. + #: 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() @@ -91,33 +93,27 @@ class DlFreeFr(SimpleHoster): self.fail(_("Invalid return code: ") + str(headers.get('code'))) - def handleFree(self, pyfile): - action, inputs = self.parseHtmlForm('action="getfile.pl"') - - adyoulike = AdYouLike(self) - response, challenge = adyoulike.challenge() - inputs.update(response) - + def handle_free(self, pyfile): + action, inputs = self.parse_html_form('action="getfile.pl"') self.load("http://dl.free.fr/getfile.pl", post=inputs) - headers = self.getLastHeaders() + headers = self.get_last_headers() if headers.get("code") == 302 and "set-cookie" in headers and "location" in headers: - m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", headers.get("set-cookie")) - cj = CookieJar(__name__) + m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*)", headers.get("set-cookie")) + cj = CookieJar(self.__name__) if m: cj.setCookie(m.group(4), m.group(1), m.group(2), m.group(3)) else: self.fail(_("Cookie error")) self.link = headers.get("location") - self.req.setCookieJar(cj) else: self.fail(_("Invalid response")) - def getLastHeaders(self): - #parse header - header = {"code": self.req.code} + def get_last_headers(self): + #: Parse header + header = {'code': self.req.code} for line in self.req.http.header.splitlines(): line = line.strip() if not line or ":" not in line: @@ -128,7 +124,7 @@ class DlFreeFr(SimpleHoster): value = value.strip() if key in header: - if type(header[key]) == list: + if type(header[key]) is list: header[key].append(value) else: header[key] = [header[key], value] diff --git a/module/plugins/hoster/DodanePl.py b/module/plugins/hoster/DodanePl.py index 46f748cc4..3a2c732d8 100644 --- a/module/plugins/hoster/DodanePl.py +++ b/module/plugins/hoster/DodanePl.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class DodanePl(DeadHoster): __name__ = "DodanePl" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?dodane\.pl/file/\d+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/DropboxCom.py b/module/plugins/hoster/DropboxCom.py index eec968f5a..7c4e952df 100644 --- a/module/plugins/hoster/DropboxCom.py +++ b/module/plugins/hoster/DropboxCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class DropboxCom(SimpleHoster): __name__ = "DropboxCom" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?dropbox\.com/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -28,11 +29,11 @@ class DropboxCom(SimpleHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 - self.resumeDownload = True + self.chunk_limit = 1 + self.resume_download = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.download(pyfile.url, get={'dl': "1"}) diff --git a/module/plugins/hoster/DuploadOrg.py b/module/plugins/hoster/DuploadOrg.py index 076171544..124919d91 100644 --- a/module/plugins/hoster/DuploadOrg.py +++ b/module/plugins/hoster/DuploadOrg.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class DuploadOrg(DeadHoster): __name__ = "DuploadOrg" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?dupload\.org/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/EasybytezCom.py b/module/plugins/hoster/EasybytezCom.py index 693910c1b..81b524a20 100644 --- a/module/plugins/hoster/EasybytezCom.py +++ b/module/plugins/hoster/EasybytezCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class EasybytezCom(XFSHoster): __name__ = "EasybytezCom" __type__ = "hoster" - __version__ = "0.23" + __version__ = "0.24" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?easybytez\.com/\w{12}' diff --git a/module/plugins/hoster/EdiskCz.py b/module/plugins/hoster/EdiskCz.py index b8485001e..3204ec9ad 100644 --- a/module/plugins/hoster/EdiskCz.py +++ b/module/plugins/hoster/EdiskCz.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class EdiskCz(SimpleHoster): __name__ = "EdiskCz" __type__ = "hoster" - __version__ = "0.23" + __version__ = "0.24" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?edisk\.(cz|sk|eu)/(stahni|sk/stahni|en/download)/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -32,20 +33,20 @@ class EdiskCz(SimpleHoster): def process(self, pyfile): url = re.sub("/(stahni|sk/stahni)/", "/en/download/", pyfile.url) - self.logDebug("URL:" + url) + self.log_debug("URL:" + url) m = re.search(self.ACTION_PATTERN, url) if m is None: self.error(_("ACTION_PATTERN not found")) action = m.group(1) - self.html = self.load(url, decode=True) - self.getFileInfo() + self.html = self.load(url) + self.get_fileInfo() self.html = self.load(re.sub("/en/download/", "/en/download-slow/", url)) url = self.load(re.sub("/en/download/", "/x-download/", url), post={ - "action": action + 'action': action }) if not re.match(self.LINK_FREE_PATTERN, url): diff --git a/module/plugins/hoster/EgoFilesCom.py b/module/plugins/hoster/EgoFilesCom.py index 78108962f..d91c70fdc 100644 --- a/module/plugins/hoster/EgoFilesCom.py +++ b/module/plugins/hoster/EgoFilesCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class EgoFilesCom(DeadHoster): __name__ = "EgoFilesCom" __type__ = "hoster" - __version__ = "0.16" + __version__ = "0.17" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?egofiles\.com/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/EnteruploadCom.py b/module/plugins/hoster/EnteruploadCom.py index 8ef994e1e..bc7d2415a 100644 --- a/module/plugins/hoster/EnteruploadCom.py +++ b/module/plugins/hoster/EnteruploadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class EnteruploadCom(DeadHoster): __name__ = "EnteruploadCom" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?enterupload\.com/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/EpicShareNet.py b/module/plugins/hoster/EpicShareNet.py index 7e3c8ba0e..498a43395 100644 --- a/module/plugins/hoster/EpicShareNet.py +++ b/module/plugins/hoster/EpicShareNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class EpicShareNet(DeadHoster): __name__ = "EpicShareNet" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?epicshare\.net/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/EuroshareEu.py b/module/plugins/hoster/EuroshareEu.py index 842e0cb87..53ac9ff06 100644 --- a/module/plugins/hoster/EuroshareEu.py +++ b/module/plugins/hoster/EuroshareEu.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class EuroshareEu(SimpleHoster): __name__ = "EuroshareEu" __type__ = "hoster" - __version__ = "0.28" + __version__ = "0.30" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?euroshare\.(eu|sk|cz|hu|pl)/file/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -23,33 +24,33 @@ class EuroshareEu(SimpleHoster): LINK_FREE_PATTERN = r'<a href="(/file/\d+/[^/]*/download/)"><div class="downloadButton"' - ERR_PARDL_PATTERN = r'<h2>Prebieha s.ahovanie</h2>|<p>Naraz je z jednej IP adresy mo.n. s.ahova. iba jeden s.bor' - ERR_NOT_LOGGED_IN_PATTERN = r'href="/customer-zone/login/"' + DL_LIMIT_PATTERN = r'<h2>Prebieha s.ahovanie</h2>|<p>Naraz je z jednej IP adresy mo.n. s.ahova. iba jeden s.bor' + ERROR_PATTERN = r'href="/customer-zone/login/"' URL_REPLACEMENTS = [(r"(http://[^/]*\.)(sk|cz|hu|pl)/", r"\1eu/")] - def handlePremium(self, pyfile): - if self.ERR_NOT_LOGGED_IN_PATTERN in self.html: + def handle_premium(self, pyfile): + if self.ERROR_PATTERN in self.html: self.account.relogin(self.user) self.retry(reason=_("User not logged in")) self.link = pyfile.url.rstrip('/') + "/download/" - check = self.checkDownload({"login": re.compile(self.ERR_NOT_LOGGED_IN_PATTERN), - "json" : re.compile(r'\{"status":"error".*?"message":"(.*?)"')}) + check = self.check_download({'login': re.compile(self.ERROR_PATTERN), + 'json' : re.compile(r'\{"status":"error".*?"message":"(.*?)"')}) - if check == "login" or (check == "json" and self.lastCheck.group(1) == "Access token expired"): + if check == "login" or (check == "json" and self.last_check.group(1) == "Access token expired"): self.account.relogin(self.user) self.retry(reason=_("Access token expired")) elif check == "json": - self.fail(self.lastCheck.group(1)) + self.fail(self.last_check.group(1)) - def handleFree(self, pyfile): - if re.search(self.ERR_PARDL_PATTERN, self.html): - self.longWait(5 * 60, 12) + def handle_free(self, pyfile): + if re.search(self.DL_LIMIT_PATTERN, self.html): + self.wait(5 * 60, 12, _("Download limit reached")) m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: @@ -58,11 +59,4 @@ class EuroshareEu(SimpleHoster): self.link = "http://euroshare.eu%s" % m.group(1) - def checkFile(self, rules={}): - if self.checkDownload({"multi-dl": re.compile(self.ERR_PARDL_PATTERN)}) - self.longWait(5 * 60, 12) - - return super(EuroshareEu, self).checkFile(rules) - - getInfo = create_getInfo(EuroshareEu) diff --git a/module/plugins/hoster/ExashareCom.py b/module/plugins/hoster/ExashareCom.py index d70ca6d3a..19cd1b46c 100644 --- a/module/plugins/hoster/ExashareCom.py +++ b/module/plugins/hoster/ExashareCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class ExashareCom(XFSHoster): __name__ = "ExashareCom" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?exashare\.com/\w{12}' @@ -22,11 +23,11 @@ class ExashareCom(XFSHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 - self.resumeDownload = self.premium + self.chunk_limit = 1 + self.resume_download = self.premium - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: self.error(_("Free download link not found")) diff --git a/module/plugins/hoster/ExtabitCom.py b/module/plugins/hoster/ExtabitCom.py index ead2e1e53..3442e7d27 100644 --- a/module/plugins/hoster/ExtabitCom.py +++ b/module/plugins/hoster/ExtabitCom.py @@ -4,14 +4,15 @@ import re from module.common.json_layer import json_loads -from module.plugins.internal.ReCaptcha import ReCaptcha -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, secondsToMidnight +from module.plugins.captcha.ReCaptcha import ReCaptcha +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, seconds_to_midnight class ExtabitCom(SimpleHoster): __name__ = "ExtabitCom" __type__ = "hoster" - __version__ = "0.66" + __version__ = "0.67" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?extabit\.com/(file|go|fid)/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -29,7 +30,7 @@ class ExtabitCom(SimpleHoster): LINK_FREE_PATTERN = r'[\'"](http://guest\d+\.extabit\.com/\w+/.*?)[\'"]' - def handleFree(self, pyfile): + def handle_free(self, pyfile): if r">Only premium users can download this file" in self.html: self.fail(_("Only premium users can download this file")) @@ -37,10 +38,10 @@ class ExtabitCom(SimpleHoster): if m: self.wait(int(m.group(1)) * 60, True) elif "The daily downloads limit from your IP is exceeded" in self.html: - self.logWarning(_("You have reached your daily downloads limit for today")) - self.wait(secondsToMidnight(gmt=2), True) + self.log_warning(_("You have reached your daily downloads limit for today")) + self.wait(seconds_to_midnight(gmt=2), True) - self.logDebug("URL: " + self.req.http.lastEffectiveURL) + self.log_debug("URL: " + self.req.http.lastEffectiveURL) m = re.match(self.__pattern__, self.req.http.lastEffectiveURL) fileID = m.group('ID') if m else self.info['pattern']['ID'] @@ -50,14 +51,14 @@ class ExtabitCom(SimpleHoster): captcha_key = m.group(1) for _i in xrange(5): - get_data = {"type": "recaptcha"} + get_data = {'type': "recaptcha"} get_data['capture'], get_data['challenge'] = recaptcha.challenge(captcha_key) res = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get=get_data)) if "ok" in res: - self.correctCaptcha() + self.captcha.correct() break else: - self.invalidCaptcha() + self.captcha.invalid() else: self.fail(_("Invalid captcha")) else: diff --git a/module/plugins/hoster/FastixRu.py b/module/plugins/hoster/FastixRu.py index cc50f4229..0019cf3c2 100644 --- a/module/plugins/hoster/FastixRu.py +++ b/module/plugins/hoster/FastixRu.py @@ -10,10 +10,12 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class FastixRu(MultiHoster): __name__ = "FastixRu" __type__ = "hoster" - __version__ = "0.11" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?fastix\.(ru|it)/file/\w{24}' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Fastix multi-hoster plugin""" __license__ = "GPLv3" @@ -21,11 +23,11 @@ class FastixRu(MultiHoster): def setup(self): - self.chunkLimit = 3 + self.chunk_limit = 3 - def handlePremium(self, pyfile): - api_key = self.account.getAccountData(self.user) + def handle_premium(self, pyfile): + api_key = self.account.get_data(self.user) api_key = api_key['api'] self.html = self.load("http://fastix.ru/api_v2/", @@ -33,7 +35,7 @@ class FastixRu(MultiHoster): data = json_loads(self.html) - self.logDebug("Json data", data) + self.log_debug("Json data", data) if "error\":true" in self.html: self.offline() diff --git a/module/plugins/hoster/FastshareCz.py b/module/plugins/hoster/FastshareCz.py index 330a6e3b9..485d69d15 100644 --- a/module/plugins/hoster/FastshareCz.py +++ b/module/plugins/hoster/FastshareCz.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FastshareCz(SimpleHoster): __name__ = "FastshareCz" __type__ = "hoster" - __version__ = "0.29" + __version__ = "0.32" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?fastshare\.cz/\d+/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -33,20 +34,20 @@ class FastshareCz(SimpleHoster): CREDIT_ERROR = " credit for " - def checkErrors(self): + def check_errors(self): if self.SLOT_ERROR in self.html: errmsg = self.info['error'] = _("No free slots") self.retry(12, 60, errmsg) if self.CREDIT_ERROR in self.html: errmsg = self.info['error'] = _("Not enough traffic left") - self.logWarning(errmsg) - self.resetAccount() + self.log_warning(errmsg) + self.restart(nopremium=True) self.info.pop('error', None) - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.FREE_URL_PATTERN, self.html) if m: action, captcha_src = m.groups() @@ -54,12 +55,12 @@ class FastshareCz(SimpleHoster): self.error(_("FREE_URL_PATTERN not found")) baseurl = "http://www.fastshare.cz" - captcha = self.decryptCaptcha(urlparse.urljoin(baseurl, captcha_src)) + captcha = self.captcha.decrypt(urlparse.urljoin(baseurl, captcha_src)) self.download(urlparse.urljoin(baseurl, action), post={'code': captcha, 'btn.x': 77, 'btn.y': 18}) - def checkFile(self, rules={}): - check = self.checkDownload({ + def check_file(self): + check = self.check_download({ 'paralell-dl' : re.compile(r"<title>FastShare.cz</title>|<script>alert\('Pres FREE muzete stahovat jen jeden soubor najednou.'\)"), 'wrong captcha': re.compile(r'Download for FREE'), 'credit' : re.compile(self.CREDIT_ERROR) @@ -72,9 +73,9 @@ class FastshareCz(SimpleHoster): self.retry(max_tries=5, reason=_("Wrong captcha")) elif check == "credit": - self.resetAccount() + self.restart(nopremium=True) - return super(FastshareCz, self).checkFile(rules) + return super(FastshareCz, self).check_file() getInfo = create_getInfo(FastshareCz) diff --git a/module/plugins/hoster/FileApeCom.py b/module/plugins/hoster/FileApeCom.py index 79157539b..c91024824 100644 --- a/module/plugins/hoster/FileApeCom.py +++ b/module/plugins/hoster/FileApeCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class FileApeCom(DeadHoster): __name__ = "FileApeCom" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?fileape\.com/(index\.php\?act=download\&id=|dl/)\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/FileSharkPl.py b/module/plugins/hoster/FileSharkPl.py index de030be9c..62a7a553f 100644 --- a/module/plugins/hoster/FileSharkPl.py +++ b/module/plugins/hoster/FileSharkPl.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FileSharkPl(SimpleHoster): __name__ = "FileSharkPl" __type__ = "hoster" - __version__ = "0.10" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?fileshark\.pl/pobierz/\d+/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -20,7 +21,7 @@ class FileSharkPl(SimpleHoster): ("Walter Purcaro", "vuolter@gmail.com")] - NAME_PATTERN = r'<h2 class="name-file">(?P<N>.+)</h2>' + NAME_PATTERN = r'<h2 class="name-file">(?P<N>.+?)</h2>' SIZE_PATTERN = r'<p class="size-file">(.*?)<strong>(?P<S>\d+\.?\d*)\s(?P<U>\w+)</strong></p>' OFFLINE_PATTERN = r'(P|p)lik zosta. (usuni.ty|przeniesiony)' @@ -37,7 +38,7 @@ class FileSharkPl(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True if self.premium: self.multiDL = True @@ -46,8 +47,8 @@ class FileSharkPl(SimpleHoster): self.multiDL = False - def checkErrors(self): - # check if file is now available for download (-> file name can be found in html body) + def check_errors(self): + #: Check if file is now available for download (-> file name can be found in html body) m = re.search(self.WAIT_PATTERN, self.html) if m: errmsg = self.info['error'] = _("Another download already run") @@ -62,7 +63,7 @@ class FileSharkPl(SimpleHoster): elif re.match(self.SLOT_ERROR_PATTERN, alert): errmsg = self.info['error'] = _("No free download slots available") - self.logWarning(errmsg) + self.log_warning(errmsg) self.retry(10, 30 * 60, _("Still no free download slots available")) else: @@ -72,7 +73,7 @@ class FileSharkPl(SimpleHoster): self.info.pop('error', None) - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: self.error(_("Download url not found")) @@ -84,10 +85,10 @@ class FileSharkPl(SimpleHoster): m = re.search(self.WAIT_PATTERN, self.html) if m: seconds = int(m.group(1)) - self.logDebug("Wait %s seconds" % seconds) + self.log_debug("Wait %s seconds" % seconds) self.wait(seconds) - action, inputs = self.parseHtmlForm('action=""') + action, inputs = self.parse_html_form('action=""') m = re.search(self.TOKEN_PATTERN, self.html) if m is None: @@ -99,19 +100,10 @@ class FileSharkPl(SimpleHoster): if m is None: self.retry(reason=_("Captcha image not found")) - tmp_load = self.load - self.load = self._decode64 #: work-around: injects decode64 inside decryptCaptcha - - inputs['form[captcha]'] = self.decryptCaptcha(m.group(1), imgtype='jpeg') + inputs['form[captcha]'] = self.captcha._decrypt(m.group(1).decode('base64'), input_type='jpeg') inputs['form[start]'] = "" - self.load = tmp_load - self.download(link, post=inputs, disposition=True) - def _decode64(self, data, *args, **kwargs): - return data.decode('base64') - - getInfo = create_getInfo(FileSharkPl) diff --git a/module/plugins/hoster/FileStoreTo.py b/module/plugins/hoster/FileStoreTo.py index 3262b73ad..96c1456cb 100644 --- a/module/plugins/hoster/FileStoreTo.py +++ b/module/plugins/hoster/FileStoreTo.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FileStoreTo(SimpleHoster): __name__ = "FileStoreTo" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filestore\.to/\?d=(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -25,11 +26,11 @@ class FileStoreTo(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.wait(10) self.link = self.load("http://filestore.to/ajax/download.php", get={'D': re.search(r'"D=(\w+)', self.html).group(1)}) diff --git a/module/plugins/hoster/FilebeerInfo.py b/module/plugins/hoster/FilebeerInfo.py index 244131dc7..9db53fe19 100644 --- a/module/plugins/hoster/FilebeerInfo.py +++ b/module/plugins/hoster/FilebeerInfo.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class FilebeerInfo(DeadHoster): __name__ = "FilebeerInfo" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filebeer\.info/(?!\d*~f)(?P<ID>\w+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/FileboomMe.py b/module/plugins/hoster/FileboomMe.py index 9cdeebe3d..2798d9eda 100644 --- a/module/plugins/hoster/FileboomMe.py +++ b/module/plugins/hoster/FileboomMe.py @@ -10,7 +10,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FileboomMe(SimpleHoster): __name__ = "FileboomMe" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://f(?:ile)?boom\.me/file/(?P<ID>\w+)' @@ -30,12 +31,12 @@ class FileboomMe(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = False - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): post_url = urljoin(pyfile.url, "/file/" + self.info['pattern']['ID']) m = re.search(r'data-slow-id="(\w+)"', self.html) @@ -55,7 +56,7 @@ class FileboomMe(SimpleHoster): m = re.search(self.CAPTCHA_PATTERN, self.html) if m: - captcha = self.decryptCaptcha(urljoin(pyfile.url, m.group(1))) + captcha = self.captcha.decrypt(urljoin(pyfile.url, m.group(1))) self.html = self.load(post_url, post={'CaptchaForm[code]' : captcha, @@ -64,10 +65,10 @@ class FileboomMe(SimpleHoster): 'uniqueId' : uniqueId}) if 'The verification code is incorrect' in self.html: - self.invalidCaptcha() + self.captcha.invalid() else: - self.checkErrors() + self.check_errors() self.html = self.load(post_url, post={'free' : 1, @@ -78,7 +79,7 @@ class FileboomMe(SimpleHoster): self.link = urljoin(pyfile.url, m.group(0)) else: - self.invalidCaptcha() + self.captcha.invalid() break diff --git a/module/plugins/hoster/FilecloudIo.py b/module/plugins/hoster/FilecloudIo.py index 346e9c444..21654fee3 100644 --- a/module/plugins/hoster/FilecloudIo.py +++ b/module/plugins/hoster/FilecloudIo.py @@ -3,14 +3,15 @@ import re from module.common.json_layer import json_loads -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilecloudIo(SimpleHoster): __name__ = "FilecloudIo" __type__ = "hoster" - __version__ = "0.09" + __version__ = "0.10" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(?:filecloud\.io|ifile\.it|mihd\.net)/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -29,7 +30,7 @@ class FilecloudIo(SimpleHoster): TEMP_OFFLINE_PATTERN = r'l10n\.FILES__WARNING' UKEY_PATTERN = r'\'ukey\'\s*:\'(\w+)' - AB1_PATTERN = r'if\( __ab1 == \'(\w+)\' \)' + AB1_PATTERN = r'if\( __ab1 is \'(\w+)\' \)' ERROR_MSG_PATTERN = r'var __error_msg\s*=\s*l10n\.(.*?);' @@ -39,13 +40,13 @@ class FilecloudIo(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): - data = {"ukey": self.info['pattern']['ID']} + def handle_free(self, pyfile): + data = {'ukey': self.info['pattern']['ID']} m = re.search(self.AB1_PATTERN, self.html) if m is None: @@ -61,20 +62,20 @@ class FilecloudIo(SimpleHoster): self.error(_("ReCaptcha key not found")) response, challenge = recaptcha.challenge(captcha_key) - self.account.form_data = {"recaptcha_challenge_field": challenge, - "recaptcha_response_field" : response} + self.account.form_data = {'recaptcha_challenge_field': challenge, + 'recaptcha_response_field' : response} self.account.relogin(self.user) self.retry(2) json_url = "http://filecloud.io/download-request.json" res = self.load(json_url, post=data) - self.logDebug(res) + self.log_debug(res) res = json_loads(res) if "error" in res and res['error']: self.fail(res) - self.logDebug(res) + self.log_debug(res) if res['captcha']: data['ctype'] = "recaptcha" @@ -83,13 +84,13 @@ class FilecloudIo(SimpleHoster): json_url = "http://filecloud.io/download-request.json" res = self.load(json_url, post=data) - self.logDebug(res) + self.log_debug(res) res = json_loads(res) if "retry" in res and res['retry']: - self.invalidCaptcha() + self.captcha.invalid() else: - self.correctCaptcha() + self.captcha.correct() break else: self.fail(_("Incorrect captcha")) @@ -102,22 +103,22 @@ class FilecloudIo(SimpleHoster): self.error(_("LINK_FREE_PATTERN not found")) if "size" in self.info and self.info['size']: - self.check_data = {"size": int(self.info['size'])} + self.check_data = {'size': int(self.info['size'])} self.link = m.group(1) else: self.fail(_("Unexpected server response")) - def handlePremium(self, pyfile): - akey = self.account.getAccountData(self.user)['akey'] + def handle_premium(self, pyfile): + akey = self.account.get_data(self.user)['akey'] ukey = self.info['pattern']['ID'] - self.logDebug("Akey: %s | Ukey: %s" % (akey, ukey)) + self.log_debug("Akey: %s | Ukey: %s" % (akey, ukey)) rep = self.load("http://api.filecloud.io/api-fetch_download_url.api", - post={"akey": akey, "ukey": ukey}) - self.logDebug("FetchDownloadUrl: " + rep) + post={'akey': akey, 'ukey': ukey}) + self.log_debug("FetchDownloadUrl: " + rep) rep = json_loads(rep) - if rep['status'] == 'ok': + if rep['status'] == "ok": self.link = rep['download_url'] else: self.fail(rep['message']) diff --git a/module/plugins/hoster/FiledropperCom.py b/module/plugins/hoster/FiledropperCom.py new file mode 100644 index 000000000..3f5e2b761 --- /dev/null +++ b/module/plugins/hoster/FiledropperCom.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +import re +import urlparse + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class FiledropperCom(SimpleHoster): + __name__ = "FiledropperCom" + __type__ = "hoster" + __version__ = "0.02" + __status__ = "testing" + + __pattern__ = r'https?://(?:www\.)?filedropper\.com/\w+' + + __description__ = """Filedropper.com hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")] + + + NAME_PATTERN = r'Filename: (?P<N>.+?) <' + SIZE_PATTERN = r'Size: (?P<S>[\d.,]+) (?P<U>[\w^_]+),' #@NOTE: Website says always 0 KB + OFFLINE_PATTERN = r'value="a\.swf"' + + + def setup(self): + self.multiDL = False + self.chunk_limit = 1 + + + def handle_free(self, pyfile): + m = re.search(r'img id="img" src="(.+?)"', self.html) + if m is None: + self.fail("Captcha not found") + + captcha_code = self.captcha.decrypt("http://www.filedropper.com/%s" % m.group(1)) + + m = re.search(r'method="post" action="(.+?)"', self.html) + if m is None: + self.fail("Download link not found") + + self.download(urlparse.urljoin("http://www.filedropper.com/", m.group(1)), + post={'code': captcha_code}) + + +getInfo = create_getInfo(FiledropperCom) diff --git a/module/plugins/hoster/FilefactoryCom.py b/module/plugins/hoster/FilefactoryCom.py index ea1a38b7a..325b4bb27 100644 --- a/module/plugins/hoster/FilefactoryCom.py +++ b/module/plugins/hoster/FilefactoryCom.py @@ -3,24 +3,25 @@ import re import urlparse -from module.network.RequestFactory import getURL -from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo +from module.network.RequestFactory import getURL as get_url +from module.plugins.internal.SimpleHoster import SimpleHoster, parse_fileInfo -def getInfo(urls): +def get_info(urls): for url in urls: - h = getURL(url, just_header=True) + h = get_url(url, just_header=True) m = re.search(r'Location: (.+)\r\n', h) if m and not re.match(m.group(1), FilefactoryCom.__pattern__): #: It's a direct link! Skipping yield (url, 0, 3, url) else: #: It's a standard html page - yield parseFileInfo(FilefactoryCom, url, getURL(url)) + yield parse_fileInfo(FilefactoryCom, url, get_url(url)) class FilefactoryCom(SimpleHoster): __name__ = "FilefactoryCom" __type__ = "hoster" - __version__ = "0.55" + __version__ = "0.57" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?filefactory\.com/(file|trafficshare/\w+)/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -42,7 +43,7 @@ class FilefactoryCom(SimpleHoster): COOKIES = [("filefactory.com", "locale", "en_US.utf8")] - def handleFree(self, pyfile): + def handle_free(self, pyfile): if "Currently only Premium Members can download files larger than" in self.html: self.fail(_("File too large for free download")) elif "All free download slots on this server are currently in use" in self.html: @@ -59,22 +60,22 @@ class FilefactoryCom(SimpleHoster): self.wait(m.group(1)) - def checkFile(self, rules={}): - check = self.checkDownload({'multiple': "You are currently downloading too many files at once.", + def check_file(self): + check = self.check_download({'multiple': "You are currently downloading too many files at once.", 'error' : '<div id="errorMessage">'}) if check == "multiple": - self.logDebug("Parallel downloads detected; waiting 15 minutes") + self.log_debug("Parallel downloads detected; waiting 15 minutes") self.retry(wait_time=15 * 60, reason=_("Parallel downloads")) elif check == "error": self.error(_("Unknown error")) - return super(FilefactoryCom, self).checkFile(rules) + return super(FilefactoryCom, self).check_file() - def handlePremium(self, pyfile): - self.link = self.directLink(self.load(pyfile.url, just_header=True)) + def handle_premium(self, pyfile): + self.link = self.direct_link(self.load(pyfile.url, just_header=True)) if not self.link: html = self.load(pyfile.url) diff --git a/module/plugins/hoster/FilejungleCom.py b/module/plugins/hoster/FilejungleCom.py index 236603c6e..1a2a7d344 100644 --- a/module/plugins/hoster/FilejungleCom.py +++ b/module/plugins/hoster/FilejungleCom.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- -from module.plugins.hoster.FileserveCom import FileserveCom, checkFile -from module.plugins.Plugin import chunks +from module.plugins.hoster.FileserveCom import FileserveCom, check_file +from module.plugins.internal.Plugin import chunks class FilejungleCom(FileserveCom): __name__ = "FilejungleCom" __type__ = "hoster" - __version__ = "0.51" + __version__ = "0.53" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filejungle\.com/f/(?P<ID>[^/]+)' @@ -24,6 +25,6 @@ class FilejungleCom(FileserveCom): LONG_WAIT_PATTERN = r'<h1>Please wait for (\d+) (\w+)\s*to download the next file\.</h1>' -def getInfo(urls): +def get_info(urls): for chunk in chunks(urls, 100): - yield checkFile(FilejungleCom, chunk) + yield check_file(FilejungleCom, chunk) diff --git a/module/plugins/hoster/FileomCom.py b/module/plugins/hoster/FileomCom.py index 306953b84..0d54b6b6c 100644 --- a/module/plugins/hoster/FileomCom.py +++ b/module/plugins/hoster/FileomCom.py @@ -9,7 +9,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class FileomCom(XFSHoster): __name__ = "FileomCom" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?fileom\.com/\w{12}' @@ -26,8 +27,8 @@ class FileomCom(XFSHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 - self.resumeDownload = self.premium + self.chunk_limit = 1 + self.resume_download = self.premium getInfo = create_getInfo(FileomCom) diff --git a/module/plugins/hoster/FilepostCom.py b/module/plugins/hoster/FilepostCom.py index 1f3de6717..d8c626ef2 100644 --- a/module/plugins/hoster/FilepostCom.py +++ b/module/plugins/hoster/FilepostCom.py @@ -4,14 +4,15 @@ import re import time from module.common.json_layer import json_loads -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilepostCom(SimpleHoster): __name__ = "FilepostCom" __type__ = "hoster" - __version__ = "0.34" + __version__ = "0.35" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(?:filepost\.com/files|fp\.io)/(?P<ID>[^/]+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -29,7 +30,7 @@ class FilepostCom(SimpleHoster): FLP_TOKEN_PATTERN = r'set_store_options\({token: \'(.+?)\'' - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.FLP_TOKEN_PATTERN, self.html) if m is None: self.error(_("Token")) @@ -40,27 +41,27 @@ class FilepostCom(SimpleHoster): self.error(_("Captcha key")) captcha_key = m.group(1) - # Get wait time + #: Get wait time get_dict = {'SID': self.req.cj.getCookie('SID'), 'JsHttpRequest': str(int(time.time() * 10000)) + '-xml'} post_dict = {'action': 'set_download', 'token': flp_token, 'code': self.info['pattern']['ID']} - wait_time = int(self.getJsonResponse(get_dict, post_dict, 'wait_time')) + wait_time = int(self.get_json_response(get_dict, post_dict, 'wait_time')) if wait_time > 0: self.wait(wait_time) - post_dict = {"token": flp_token, "code": self.info['pattern']['ID'], "file_pass": ''} + post_dict = {'token': flp_token, 'code': self.info['pattern']['ID'], 'file_pass': ''} if 'var is_pass_exists = true;' in self.html: - # Solve password - password = self.getPassword() + #: Solve password + password = self.get_password() if password: - self.logInfo(_("Password protected link, trying ") + file_pass) + self.log_info(_("Password protected link, trying ") + file_pass) get_dict['JsHttpRequest'] = str(int(time.time() * 10000)) + '-xml' post_dict['file_pass'] = file_pass - self.link = self.getJsonResponse(get_dict, post_dict, 'link') + self.link = self.get_json_response(get_dict, post_dict, 'link') if not self.link: self.fail(_("Incorrect password")) @@ -68,7 +69,7 @@ class FilepostCom(SimpleHoster): self.fail(_("No password found")) else: - # Solve recaptcha + #: Solve recaptcha recaptcha = ReCaptcha(self) for i in xrange(5): @@ -76,32 +77,32 @@ class FilepostCom(SimpleHoster): if i: post_dict['recaptcha_response_field'], post_dict['recaptcha_challenge_field'] = recaptcha.challenge( captcha_key) - self.logDebug(u"RECAPTCHA: %s : %s : %s" % ( + self.log_debug(u"RECAPTCHA: %s : %s : %s" % ( captcha_key, post_dict['recaptcha_challenge_field'], post_dict['recaptcha_response_field'])) - self.link = self.getJsonResponse(get_dict, post_dict, 'link') + self.link = self.get_json_response(get_dict, post_dict, 'link') else: self.fail(_("Invalid captcha")) - def getJsonResponse(self, get_dict, post_dict, field): + def get_json_response(self, get_dict, post_dict, field): res = json_loads(self.load('https://filepost.com/files/get/', get=get_dict, post=post_dict)) - self.logDebug(res) + self.log_debug(res) if not 'js' in res: self.error(_("JSON %s 1") % field) - # i changed js_answer to res['js'] since js_answer is nowhere set. - # i don't know the JSON-HTTP specs in detail, but the previous author - # accessed res['js']['error'] as well as js_answer['error']. - # see the two lines commented out with "# ~?". + #: I changed js_answer to res['js'] since js_answer is nowhere set. + #: I don't know the JSON-HTTP specs in detail, but the previous author + #: Accessed res['js']['error'] as well as js_answer['error']. + #: See the two lines commented out with "# ~?". if 'error' in res['js']: - if res['js']['error'] == 'download_delay': + if res['js']['error'] == "download_delay": self.retry(wait_time=res['js']['params']['next_download']) - # ~? self.retry(wait_time=js_answer['params']['next_download']) + #: ~? self.retry(wait_time=js_answer['params']['next_download']) elif 'Wrong file password' in res['js']['error'] \ or 'You entered a wrong CAPTCHA code' in res['js']['error'] \ @@ -109,7 +110,7 @@ class FilepostCom(SimpleHoster): return None elif 'CAPTCHA' in res['js']['error']: - self.logDebug("Error response is unknown, but mentions CAPTCHA") + self.log_debug("Error response is unknown, but mentions CAPTCHA") return None else: diff --git a/module/plugins/hoster/FilepupNet.py b/module/plugins/hoster/FilepupNet.py index 874fde3c8..8bb23adb1 100644 --- a/module/plugins/hoster/FilepupNet.py +++ b/module/plugins/hoster/FilepupNet.py @@ -12,7 +12,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilepupNet(SimpleHoster): __name__ = "FilepupNet" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filepup\.net/files/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -33,10 +34,10 @@ class FilepupNet(SimpleHoster): def setup(self): self.multiDL = False - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: self.error(_("Download link not found")) diff --git a/module/plugins/hoster/FilerNet.py b/module/plugins/hoster/FilerNet.py index 3b876ed48..f8c41f4d1 100644 --- a/module/plugins/hoster/FilerNet.py +++ b/module/plugins/hoster/FilerNet.py @@ -8,14 +8,15 @@ import pycurl import re import urlparse -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FilerNet(SimpleHoster): __name__ = "FilerNet" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.21" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?filer\.net/get/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -34,14 +35,14 @@ class FilerNet(SimpleHoster): LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'href="([^"]+)">Get download</a>' - def handleFree(self, pyfile): - inputs = self.parseHtmlForm(input_names={'token': re.compile(r'.+')})[1] + def handle_free(self, pyfile): + inputs = self.parse_html_form(input_names={'token': re.compile(r'.+')})[1] if 'token' not in inputs: self.error(_("Unable to detect token")) - self.html = self.load(pyfile.url, post={'token': inputs['token']}, decode=True) + self.html = self.load(pyfile.url, post={'token': inputs['token']}) - inputs = self.parseHtmlForm(input_names={'hash': re.compile(r'.+')})[1] + inputs = self.parse_html_form(input_names={'hash': re.compile(r'.+')})[1] if 'hash' not in inputs: self.error(_("Unable to detect hash")) @@ -58,9 +59,9 @@ class FilerNet(SimpleHoster): if 'location' in self.req.http.header.lower(): self.link = re.search(r'location: (\S+)', self.req.http.header, re.I).group(1) - self.correctCaptcha() + self.captcha.correct() else: - self.invalidCaptcha() + self.captcha.invalid() getInfo = create_getInfo(FilerNet) diff --git a/module/plugins/hoster/FilerioCom.py b/module/plugins/hoster/FilerioCom.py index c6ebbd444..c65c07a42 100644 --- a/module/plugins/hoster/FilerioCom.py +++ b/module/plugins/hoster/FilerioCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class FilerioCom(XFSHoster): __name__ = "FilerioCom" __type__ = "hoster" - __version__ = "0.07" + __version__ = "0.08" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(filerio\.(in|com)|filekeen\.com)/\w{12}' diff --git a/module/plugins/hoster/FilesMailRu.py b/module/plugins/hoster/FilesMailRu.py index 7bd099282..a6dd56152 100644 --- a/module/plugins/hoster/FilesMailRu.py +++ b/module/plugins/hoster/FilesMailRu.py @@ -2,16 +2,16 @@ import re -from module.network.RequestFactory import getURL -from module.plugins.Hoster import Hoster -from module.plugins.Plugin import chunks +from module.network.RequestFactory import getURL as get_url +from module.plugins.internal.Hoster import Hoster +from module.plugins.internal.Plugin import chunks -def getInfo(urls): +def get_info(urls): result = [] for chunk in chunks(urls, 10): for url in chunk: - html = getURL(url) + html = get_url(url) if r'<div class="errorMessage mb10">' in html: result.append((url, 0, 1, url)) elif r'Page cannot be displayed' in html: @@ -24,15 +24,16 @@ def getInfo(urls): except Exception: pass - # status 1=OFFLINE, 2=OK, 3=UNKNOWN - # result.append((#name,#size,#status,#url)) + #: status 1=OFFLINE, 2=OK, 3=UNKNOWN + #: result.append((#name,#size,#status,#url)) yield result class FilesMailRu(Hoster): __name__ = "FilesMailRu" __type__ = "hoster" - __version__ = "0.32" + __version__ = "0.34" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?files\.mail\.ru/.+' @@ -49,57 +50,62 @@ class FilesMailRu(Hoster): self.html = self.load(pyfile.url) self.url_pattern = '<a href="(.+?)" onclick="return Act\(this\, \'dlink\'\, event\)">(.+?)</a>' - #marks the file as "offline" when the pattern was found on the html-page''' + #: Marks the file as "offline" when the pattern was found on the html-page''' if r'<div class="errorMessage mb10">' in self.html: self.offline() elif r'Page cannot be displayed' in self.html: self.offline() - #the filename that will be showed in the list (e.g. test.part1.rar)''' - pyfile.name = self.getFileName() + #: The filename that will be showed in the list (e.g. test.part1.rar)''' + pyfile.name = self.get_file_name() - #prepare and download''' + #: Prepare and download''' if not self.account: self.prepare() - self.download(self.getFileUrl()) - self.myPostProcess() + self.download(self.get_file_url()) + self.my_post_process() else: - self.download(self.getFileUrl()) - self.myPostProcess() + self.download(self.get_file_url()) + self.my_post_process() def prepare(self): - """You have to wait some seconds. Otherwise you will get a 40Byte HTML Page instead of the file you expected""" - self.setWait(10) - self.wait() + """ + You have to wait some seconds. Otherwise you will get a 40Byte HTML Page instead of the file you expected + """ + self.wait(10) return True - def getFileUrl(self): - """gives you the URL to the file. Extracted from the Files.mail.ru HTML-page stored in self.html""" + def get_file_url(self): + """ + Gives you the URL to the file. Extracted from the Files.mail.ru HTML-page stored in self.html + """ return re.search(self.url_pattern, self.html).group(0).split('<a href="')[1].split('" onclick="return Act')[0] - def getFileName(self): - """gives you the Name for each file. Also extracted from the HTML-Page""" + def get_file_name(self): + """ + Gives you the Name for each file. Also extracted from the HTML-Page + """ return re.search(self.url_pattern, self.html).group(0).split(', event)">')[1].split('</a>')[0] - def myPostProcess(self): - # searches the file for HTMl-Code. Sometimes the Redirect - # doesn't work (maybe a curl Problem) and you get only a small - # HTML file and the Download is marked as "finished" - # then the download will be restarted. It's only bad for these - # who want download a HTML-File (it's one in a million ;-) ) + def my_post_process(self): + #: Searches the file for HTMl-Code. Sometimes the Redirect + #: doesn't work (maybe a curl Problem) and you get only a small + #: HTML file and the Download is marked as "finished" + #: then the download will be restarted. It's only bad for these + #: who want download a HTML-File (it's one in a million ;-) ) # - # The maximum UploadSize allowed on files.mail.ru at the moment is 100MB - # so i set it to check every download because sometimes there are downloads - # that contain the HTML-Text and 60MB ZEROs after that in a xyzfile.part1.rar file - # (Loading 100MB in to ram is not an option) - check = self.checkDownload({"html": "<meta name="}, read_size=50000) + #: The maximum UploadSize allowed on files.mail.ru at the moment == 100MB + #: so i set it to check every download because sometimes there are downloads + #: that contain the HTML-Text and 60MB ZEROs after that in a xyzfile.part1.rar file + #: (Loading 100MB in to ram is not an option) + check = self.check_download({'html': "<meta name="}, read_size=50000) if check == "html": - self.logInfo(_( + self.log_info(_( "There was HTML Code in the Downloaded File (%s)...redirect error? The Download will be restarted." % self.pyfile.name)) self.retry() diff --git a/module/plugins/hoster/FileserveCom.py b/module/plugins/hoster/FileserveCom.py index f8cf652b9..a74589cff 100644 --- a/module/plugins/hoster/FileserveCom.py +++ b/module/plugins/hoster/FileserveCom.py @@ -3,16 +3,16 @@ import re 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.ReCaptcha import ReCaptcha -from module.plugins.internal.SimpleHoster import secondsToMidnight -from module.utils import parseFileSize +from module.network.RequestFactory import getURL as get_url +from module.plugins.internal.Hoster import Hoster +from module.plugins.internal.Plugin import chunks +from module.plugins.captcha.ReCaptcha import ReCaptcha +from module.plugins.internal.SimpleHoster import seconds_to_midnight +from module.utils import parseFileSize as parse_size -def checkFile(plugin, urls): - html = getURL(plugin.URLS[1], post={"urls": "\n".join(urls)}, decode=True) +def check_file(plugin, urls): + html = get_url(plugin.URLS[1], post={'urls': "\n".join(urls)}) file_info = [] for li in re.finditer(plugin.LINKCHECK_TR, html, re.S): @@ -21,7 +21,7 @@ def checkFile(plugin, urls): if cols: file_info.append(( cols[1] if cols[1] != '--' else cols[0], - parseFileSize(cols[2]) if cols[2] != '--' else 0, + parse_size(cols[2]) if cols[2] != '--' else 0, 2 if cols[3].startswith('Available') else 1, cols[0])) except Exception, e: @@ -33,65 +33,67 @@ def checkFile(plugin, urls): class FileserveCom(Hoster): __name__ = "FileserveCom" __type__ = "hoster" - __version__ = "0.55" + __version__ = "0.58" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?fileserve\.com/file/(?P<ID>[^/]+)' __description__ = """Fileserve.com hoster plugin""" __license__ = "GPLv3" - __authors__ = [("jeix", "jeix@hasnomail.de"), - ("mkaay", "mkaay@mkaay.de"), - ("Paul King", None), - ("zoidberg", "zoidberg@mujmail.cz")] + __authors__ = [("jeix" , "jeix@hasnomail.de" ), + ("mkaay" , "mkaay@mkaay.de" ), + ("Paul King", None ), + ("zoidberg" , "zoidberg@mujmail.cz")] - URLS = ["http://www.fileserve.com/file/", "http://www.fileserve.com/link-checker.php", + URLS = ["http://www.fileserve.com/file/", + "http://www.fileserve.com/link-checker.php", "http://www.fileserve.com/checkReCaptcha.php"] + LINKCHECK_TR = r'<tr>\s*(<td>http://www\.fileserve\.com/file/.*?)</tr>' LINKCHECK_TD = r'<td>(?:<.*?>| )*([^<]*)' - CAPTCHA_KEY_PATTERN = r'var reCAPTCHA_publickey=\'(.+?)\'' - LONG_WAIT_PATTERN = r'<li class="title">You need to wait (\d+) (\w+) to start another download\.</li>' - LINK_EXPIRED_PATTERN = r'Your download link has expired' - DAILY_LIMIT_PATTERN = r'Your daily download limit has been reached' + CAPTCHA_KEY_PATTERN = r'var reCAPTCHA_publickey=\'(.+?)\'' + LONG_WAIT_PATTERN = r'<li class="title">You need to wait (\d+) (\w+) to start another download\.</li>' + LINK_EXPIRED_PATTERN = r'Your download link has expired' + DL_LIMIT_PATTERN = r'Your daily download limit has been reached' NOT_LOGGED_IN_PATTERN = r'<form (name="loginDialogBoxForm"|id="login_form")|<li><a href="/login\.php">Login</a></li>' def setup(self): - self.resumeDownload = self.multiDL = self.premium + self.resume_download = self.multiDL = self.premium self.file_id = re.match(self.__pattern__, self.pyfile.url).group('ID') self.url = "%s%s" % (self.URLS[0], self.file_id) - self.logDebug("File ID: %s URL: %s" % (self.file_id, self.url)) + self.log_debug("File ID: %s URL: %s" % (self.file_id, self.url)) def process(self, pyfile): - pyfile.name, pyfile.size, status, self.url = checkFile(self, [self.url])[0] + pyfile.name, pyfile.size, status, self.url = check_file(self, [self.url])[0] if status != 2: self.offline() - self.logDebug("File Name: %s Size: %d" % (pyfile.name, pyfile.size)) + self.log_debug("File Name: %s Size: %d" % (pyfile.name, pyfile.size)) if self.premium: - self.handlePremium() + self.handle_premium() else: - self.handleFree() + self.handle_free() - def handleFree(self): + def handle_free(self): self.html = self.load(self.url) - action = self.load(self.url, post={"checkDownload": "check"}, decode=True) + action = self.load(self.url, post={'checkDownload': "check"}) action = json_loads(action) - self.logDebug(action) + self.log_debug(action) if "fail" in action: if action['fail'] == "timeLimit": - self.html = self.load(self.url, post={"checkDownload": "showError", "errorType": "timeLimit"}, - decode=True) + self.html = self.load(self.url, post={'checkDownload': "showError", 'errorType': "timeLimit"}) - self.doLongWait(re.search(self.LONG_WAIT_PATTERN, self.html)) + self.do_long_wait(re.search(self.LONG_WAIT_PATTERN, self.html)) elif action['fail'] == "parallelDownload": - self.logWarning(_("Parallel download error, now waiting 60s")) + self.log_warning(_("Parallel download error, now waiting 60s")) self.retry(wait_time=60, reason=_("parallelDownload")) else: @@ -99,47 +101,46 @@ class FileserveCom(Hoster): elif "success" in action: if action['success'] == "showCaptcha": - self.doCaptcha() - self.doTimmer() + self.do_captcha() + self.do_timmer() elif action['success'] == "showTimmer": - self.doTimmer() + self.do_timmer() else: self.error(_("Unknown server response")) - # show download link - res = self.load(self.url, post={"downloadLink": "show"}, decode=True) - self.logDebug("Show downloadLink response: %s" % res) + #: Show download link + res = self.load(self.url, post={'downloadLink': "show"}) + self.log_debug("Show downloadLink response: %s" % res) if "fail" in res: self.error(_("Couldn't retrieve download url")) - # this may either download our file or forward us to an error page - self.download(self.url, post={"download": "normal"}) - self.logDebug(self.req.http.lastEffectiveURL) + #: This may either download our file or forward us to an error page + self.download(self.url, post={'download': "normal"}) + self.log_debug(self.req.http.lastEffectiveURL) - check = self.checkDownload({"expired": self.LINK_EXPIRED_PATTERN, - "wait" : re.compile(self.LONG_WAIT_PATTERN), - "limit" : self.DAILY_LIMIT_PATTERN}) + check = self.check_download({'expired': self.LINK_EXPIRED_PATTERN, + 'wait' : re.compile(self.LONG_WAIT_PATTERN), + 'limit' : self.DL_LIMIT_PATTERN}) if check == "expired": - self.logDebug("Download link was expired") + self.log_debug("Download link was expired") self.retry() elif check == "wait": - self.doLongWait(self.lastCheck) + self.do_long_wait(self.last_check) elif check == "limit": - self.logWarning(_("Download limited reached for today")) - self.setWait(secondsToMidnight(gmt=2), True) - self.wait() + self.log_warning(_("Download limited reached for today")) + self.wait(seconds_to_midnight(gmt=2), True) self.retry() - self.thread.m.reconnecting.wait(3) # Ease issue with later downloads appearing to be in parallel + self.thread.m.reconnecting.wait(3) #: Ease issue with later downloads appearing to be in parallel - def doTimmer(self): - res = self.load(self.url, post={"downloadLink": "wait"}, decode=True) - self.logDebug("Wait response: %s" % res[:80]) + def do_timmer(self): + res = self.load(self.url, post={'downloadLink': "wait"}) + self.log_debug("Wait response: %s" % res[:80]) if "fail" in res: self.fail(_("Failed getting wait time")) @@ -152,11 +153,10 @@ class FileserveCom(Hoster): else: wait_time = int(res) + 3 - self.setWait(wait_time) - self.wait() + self.wait(wait_time) - def doCaptcha(self): + def do_captcha(self): captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group(1) recaptcha = ReCaptcha(self) @@ -167,50 +167,48 @@ class FileserveCom(Hoster): 'recaptcha_response_field' : response, 'recaptcha_shortencode_field': self.file_id})) if not res['success']: - self.invalidCaptcha() + self.captcha.invalid() else: - self.correctCaptcha() + self.captcha.correct() break else: self.fail(_("Invalid captcha")) - def doLongWait(self, m): + def do_long_wait(self, m): wait_time = (int(m.group(1)) * {'seconds': 1, 'minutes': 60, 'hours': 3600}[m.group(2)]) if m else 12 * 60 - self.setWait(wait_time, True) - self.wait() + self.wait(wait_time, True) self.retry() - def handlePremium(self): + def handle_premium(self): premium_url = None if self.__name__ == "FileserveCom": - #try api download + #: Try api download res = self.load("http://app.fileserve.com/api/download/premium/", - post={"username": self.user, - "password": self.account.getAccountData(self.user)['password'], - "shorten": self.file_id}, - decode=True) + post={'username': self.user, + 'password': self.account.get_info(self.user)['login']['password'], + 'shorten': self.file_id}) if res: res = json_loads(res) if res['error_code'] == "302": premium_url = res['next'] elif res['error_code'] in ["305", "500"]: - self.tempOffline() + self.temp_offline() elif res['error_code'] in ["403", "605"]: - self.resetAccount() + self.restart(nopremium=True) elif res['error_code'] in ["606", "607", "608"]: self.offline() else: - self.logError(res['error_code'], res['error_message']) + self.log_error(res['error_code'], res['error_message']) self.download(premium_url or self.pyfile.url) - if not premium_url and self.checkDownload({"login": re.compile(self.NOT_LOGGED_IN_PATTERN)}): + if not premium_url and self.check_download({'login': re.compile(self.NOT_LOGGED_IN_PATTERN)}): self.account.relogin(self.user) self.retry(reason=_("Not logged in")) -def getInfo(urls): +def get_info(urls): for chunk in chunks(urls, 100): - yield checkFile(FileserveCom, chunk) + yield check_file(FileserveCom, chunk) diff --git a/module/plugins/hoster/FileshareInUa.py b/module/plugins/hoster/FileshareInUa.py index aa1785f19..3fb181348 100644 --- a/module/plugins/hoster/FileshareInUa.py +++ b/module/plugins/hoster/FileshareInUa.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class FileshareInUa(DeadHoster): __name__ = "FileshareInUa" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?fileshare\.in\.ua/\w{7}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/FilesonicCom.py b/module/plugins/hoster/FilesonicCom.py index 5254a6f9b..59c0ea246 100644 --- a/module/plugins/hoster/FilesonicCom.py +++ b/module/plugins/hoster/FilesonicCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class FilesonicCom(DeadHoster): __name__ = "FilesonicCom" __type__ = "hoster" - __version__ = "0.35" + __version__ = "0.36" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filesonic\.com/file/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/FileuploadNet.py b/module/plugins/hoster/FileuploadNet.py new file mode 100644 index 000000000..c7f541687 --- /dev/null +++ b/module/plugins/hoster/FileuploadNet.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class FileuploadNet(SimpleHoster): + __name__ = "FileuploadNet" + __type__ = "hoster" + __version__ = "0.03" + __status__ = "testing" + + __pattern__ = r'https?://(?:www\.)?(en\.)?file-upload\.net/download-\d+/.+' + + __description__ = """File-upload.net hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")] + + + NAME_PATTERN = r'<title>File-Upload.net - (?P<N>.+?)<' + SIZE_PATTERN = r'</label><span>(?P<S>[\d.,]+) (?P<U>[\w^_]+)' + OFFLINE_PATTERN = r'Datei existiert nicht' + + LINK_FREE_PATTERN = r"<a href='(.+?)' title='download' onclick" + + + def setup(self): + self.multiDL = True + self.chunk_limit = 1 + + +getInfo = create_getInfo(FileuploadNet) diff --git a/module/plugins/hoster/FilezyNet.py b/module/plugins/hoster/FilezyNet.py index 9f442c846..249548d13 100644 --- a/module/plugins/hoster/FilezyNet.py +++ b/module/plugins/hoster/FilezyNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class FilezyNet(DeadHoster): __name__ = "FilezyNet" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.21" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?filezy\.net/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/FiredriveCom.py b/module/plugins/hoster/FiredriveCom.py index 8faee5b52..cc530a3c5 100644 --- a/module/plugins/hoster/FiredriveCom.py +++ b/module/plugins/hoster/FiredriveCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class FiredriveCom(DeadHoster): __name__ = "FiredriveCom" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(firedrive|putlocker)\.com/(mobile/)?(file|embed)/(?P<ID>\w+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/FlyFilesNet.py b/module/plugins/hoster/FlyFilesNet.py index 689eb3c66..ca2f7f270 100644 --- a/module/plugins/hoster/FlyFilesNet.py +++ b/module/plugins/hoster/FlyFilesNet.py @@ -3,14 +3,14 @@ import re import urllib -from module.network.RequestFactory import getURL from module.plugins.internal.SimpleHoster import SimpleHoster class FlyFilesNet(SimpleHoster): __name__ = "FlyFilesNet" __type__ = "hoster" - __version__ = "0.10" + __version__ = "0.11" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?flyfiles\.net/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -31,12 +31,12 @@ class FlyFilesNet(SimpleHoster): url = "http://flyfiles.net" - # get download URL - parsed_url = getURL(url, post={"getDownLink": session}) - self.logDebug("Parsed URL: %s" % parsed_url) + #: Get download URL + parsed_url = self.load(url, post={'getDownLink': session}) + self.log_debug("Parsed URL: %s" % parsed_url) - if parsed_url == '#downlink|' or parsed_url == "#downlink|#": - self.logWarning(_("Could not get the download URL. Please wait 10 minutes")) + if parsed_url == "#downlink|" or parsed_url == "#downlink|#": + self.log_warning(_("Could not get the download URL. Please wait 10 minutes")) self.wait(10 * 60, True) self.retry() diff --git a/module/plugins/hoster/FourSharedCom.py b/module/plugins/hoster/FourSharedCom.py index 79eb1fb83..e5b309dc1 100644 --- a/module/plugins/hoster/FourSharedCom.py +++ b/module/plugins/hoster/FourSharedCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class FourSharedCom(SimpleHoster): __name__ = "FourSharedCom" __type__ = "hoster" - __version__ = "0.31" + __version__ = "0.32" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?4shared(\-china)?\.com/(account/)?(download|get|file|document|photo|video|audio|mp3|office|rar|zip|archive|music)/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -35,7 +36,7 @@ class FourSharedCom(SimpleHoster): ID_PATTERN = r'name="d3fid" value="(.*?)"' - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.LINK_BTN_PATTERN, self.html) if m: link = m.group(1) @@ -53,7 +54,7 @@ class FourSharedCom(SimpleHoster): try: m = re.search(self.ID_PATTERN, self.html) res = self.load('http://www.4shared.com/web/d2/getFreeDownloadLimitInfo?fileId=%s' % m.group(1)) - self.logDebug(res) + self.log_debug(res) except Exception: pass diff --git a/module/plugins/hoster/FreakshareCom.py b/module/plugins/hoster/FreakshareCom.py index d005443d9..4564ee03e 100644 --- a/module/plugins/hoster/FreakshareCom.py +++ b/module/plugins/hoster/FreakshareCom.py @@ -2,15 +2,16 @@ import re -from module.plugins.Hoster import Hoster -from module.plugins.internal.ReCaptcha import ReCaptcha -from module.plugins.internal.SimpleHoster import secondsToMidnight +from module.plugins.internal.Hoster import Hoster +from module.plugins.captcha.ReCaptcha import ReCaptcha +from module.plugins.internal.SimpleHoster import seconds_to_midnight class FreakshareCom(Hoster): __name__ = "FreakshareCom" __type__ = "hoster" - __version__ = "0.41" + __version__ = "0.43" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?freakshare\.(net|com)/files/\S*?/' @@ -43,25 +44,24 @@ class FreakshareCom(Hoster): self.download(pyfile.url, post=self.req_opts) - check = self.checkDownload({"bad" : "bad try", - "paralell" : "> Sorry, you cant download more then 1 files at time. <", - "empty" : "Warning: Unknown: Filename cannot be empty", - "wrong_captcha" : "Wrong Captcha!", - "downloadserver": "No Downloadserver. Please try again later!"}) + check = self.check_download({'bad' : "bad try", + 'paralell' : "> Sorry, you cant download more then 1 files at time. <", + 'empty' : "Warning: Unknown: Filename cannot be empty", + 'wrong_captcha' : "Wrong Captcha!", + 'downloadserver': "No Downloadserver. Please try again later!"}) if check == "bad": self.fail(_("Bad Try")) elif check == "paralell": - self.setWait(300, True) - self.wait() + self.wait(300, True) self.retry() elif check == "empty": self.fail(_("File not downloadable")) elif check == "wrong_captcha": - self.invalidCaptcha() + self.captcha.invalid() self.retry() elif check == "downloadserver": @@ -76,7 +76,7 @@ class FreakshareCom(Hoster): if not self.file_exists(): self.offline() - self.setWait(self.get_waiting_time()) + self.set_wait(self.get_waiting_time()) pyfile.name = self.get_file_name() pyfile.size = self.get_file_size() @@ -87,19 +87,20 @@ class FreakshareCom(Hoster): def download_html(self): - self.load("http://freakshare.com/index.php", {"language": "EN"}) # Set english language in server session + self.load("http://freakshare.com/index.php", {'language': "EN"}) #: Set english language in server session self.html = self.load(self.pyfile.url) def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ if not self.html: self.download_html() if not self.wantReconnect: - self.req_opts = self.get_download_options() # get the Post options for the Request - #file_url = self.pyfile.url - #return file_url + self.req_opts = self.get_download_options() #: Get the Post options for the Request + # file_url = self.pyfile.url + # return file_url else: self.offline() @@ -141,7 +142,7 @@ class FreakshareCom(Hoster): if "Your Traffic is used up for today" in self.html: self.wantReconnect = True - return secondsToMidnight(gmt=2) + return seconds_to_midnight(gmt=2) timestring = re.search('\s*var\s(?:downloadWait|time)\s=\s(\d*)[\d.]*;', self.html) if timestring: @@ -151,7 +152,8 @@ class FreakshareCom(Hoster): def file_exists(self): - """ returns True or False + """ + Returns True or False """ if not self.html: self.download_html() @@ -163,11 +165,11 @@ class FreakshareCom(Hoster): def get_download_options(self): re_envelope = re.search(r".*?value=\"Free\sDownload\".*?\n*?(.*?<.*?>\n*)*?\n*\s*?</form>", - self.html).group(0) # get the whole request + self.html).group(0) #: Get the whole request to_sort = re.findall(r"<input\stype=\"hidden\"\svalue=\"(.*?)\"\sname=\"(.*?)\"\s\/>", re_envelope) request_options = dict((n, v) for (v, n) in to_sort) - herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page + herewego = self.load(self.pyfile.url, None, request_options) #: The actual download-Page to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego) request_options = dict((n, v) for (v, n) in to_sort) diff --git a/module/plugins/hoster/FreeWayMe.py b/module/plugins/hoster/FreeWayMe.py index 1cca24c3b..ed7c4bf7f 100644 --- a/module/plugins/hoster/FreeWayMe.py +++ b/module/plugins/hoster/FreeWayMe.py @@ -6,10 +6,12 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class FreeWayMe(MultiHoster): __name__ = "FreeWayMe" __type__ = "hoster" - __version__ = "0.16" + __version__ = "0.19" + __status__ = "testing" - __pattern__ = r'https://(?:www\.)?free-way\.me/.+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __pattern__ = r'https?://(?:www\.)?free-way\.(bz|me)/.+' + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """FreeWayMe multi-hoster plugin""" __license__ = "GPLv3" @@ -17,36 +19,36 @@ class FreeWayMe(MultiHoster): def setup(self): - self.resumeDownload = False + self.resume_download = False self.multiDL = self.premium - self.chunkLimit = 1 + self.chunk_limit = 1 - def handlePremium(self, pyfile): - user, data = self.account.selectAccount() + def handle_premium(self, pyfile): + user, data = self.account.select() for _i in xrange(5): - # try it five times - header = self.load("https://www.free-way.me/load.php", + #: Try it five times + header = self.load("http://www.free-way.bz/load.php", #@TODO: Revert to `https` in 0.4.10 get={'multiget': 7, 'url' : pyfile.url, 'user' : user, - 'pw' : self.account.getAccountData(user)['password'], + 'pw' : self.account.get_info(self.user)['login']['password'], 'json' : ""}, just_header=True) if 'location' in header: headers = self.load(header['location'], just_header=True) if headers['code'] == 500: - # error on 2nd stage - self.logError(_("Error [stage2]")) + #: Error on 2nd stage + self.log_error(_("Error [stage2]")) else: - # seems to work.. + #: Seems to work.. self.download(header['location']) break else: - # error page first stage - self.logError(_("Error [stage1]")) + #: Error page first stage + self.log_error(_("Error [stage1]")) #@TODO: handle errors diff --git a/module/plugins/hoster/FreevideoCz.py b/module/plugins/hoster/FreevideoCz.py index 49f02a28b..ec8734b6a 100644 --- a/module/plugins/hoster/FreevideoCz.py +++ b/module/plugins/hoster/FreevideoCz.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class FreevideoCz(DeadHoster): __name__ = "FreevideoCz" __type__ = "hoster" - __version__ = "0.30" + __version__ = "0.31" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?freevideo\.cz/vase-videa/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/FshareVn.py b/module/plugins/hoster/FshareVn.py index 50128db10..a5aac222c 100644 --- a/module/plugins/hoster/FshareVn.py +++ b/module/plugins/hoster/FshareVn.py @@ -4,27 +4,27 @@ import re import time import urlparse -from module.network.RequestFactory import getURL -from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo +from module.network.RequestFactory import getURL as get_url +from module.plugins.internal.SimpleHoster import SimpleHoster, parse_fileInfo -def getInfo(urls): +def get_info(urls): for url in urls: - html = getURL("http://www.fshare.vn/check_link.php", - post={'action': "check_link", 'arrlinks': url}, - decode=True) + html = get_url("http://www.fshare.vn/check_link.php", + post={'action': "check_link", 'arrlinks': url}) - yield parseFileInfo(FshareVn, url, html) + yield parse_fileInfo(FshareVn, url, html) -def doubleDecode(m): +def double_decode(m): return m.group(1).decode('raw_unicode_escape') class FshareVn(SimpleHoster): __name__ = "FshareVn" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.21" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?fshare\.vn/file/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -45,31 +45,27 @@ class FshareVn(SimpleHoster): def preload(self): self.html = self.load("http://www.fshare.vn/check_link.php", - post={'action': "check_link", 'arrlinks': pyfile.url}, - decode=True) + post={'action': "check_link", 'arrlinks': pyfile.url}) - if isinstance(self.TEXT_ENCODING, basestring): - self.html = unicode(self.html, self.TEXT_ENCODING) + def handle_free(self, pyfile): + self.html = self.load(pyfile.url) - def handleFree(self, pyfile): - self.html = self.load(pyfile.url, decode=True) + self.check_errors() - self.checkErrors() - - action, inputs = self.parseHtmlForm('frm_download') + action, inputs = self.parse_html_form('frm_download') url = urlparse.urljoin(pyfile.url, action) if not inputs: self.error(_("No FORM")) elif 'link_file_pwd_dl' in inputs: - password = self.getPassword() + password = self.get_password() if password: - self.logInfo(_("Password protected link, trying ") + password) + self.log_info(_("Password protected link, trying ") + password) inputs['link_file_pwd_dl'] = password - self.html = self.load(url, post=inputs, decode=True) + self.html = self.load(url, post=inputs) if 'name="link_file_pwd_dl"' in self.html: self.fail(_("Incorrect password")) @@ -77,12 +73,12 @@ class FshareVn(SimpleHoster): self.fail(_("No password found")) else: - self.html = self.load(url, post=inputs, decode=True) + self.html = self.load(url, post=inputs) - self.checkErrors() + self.check_errors() m = re.search(r'var count = (\d+)', self.html) - self.setWait(int(m.group(1)) if m else 30) + self.set_wait(int(m.group(1)) if m else 30) m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: @@ -92,19 +88,19 @@ class FshareVn(SimpleHoster): self.wait() - def checkErrors(self): + def check_errors(self): if '/error.php?' in self.req.lastEffectiveURL or u"Liên kết bạn chá»n khÃŽng tá»n" in self.html: self.offline() m = re.search(self.WAIT_PATTERN, self.html) if m: - self.logInfo(_("Wait until %s ICT") % m.group(1)) + self.log_info(_("Wait until %s ICT") % m.group(1)) wait_until = time.mktime.time(time.strptime.time(m.group(1), "%d/%m/%Y %H:%M")) self.wait(wait_until - time.mktime.time(time.gmtime.time()) - 7 * 60 * 60, True) self.retry() elif '<ul class="message-error">' in self.html: msg = "Unknown error occured or wait time not parsed" - self.logError(msg) + self.log_error(msg) self.retry(30, 2 * 60, msg) self.info.pop('error', None) diff --git a/module/plugins/hoster/Ftp.py b/module/plugins/hoster/Ftp.py index 295955cbe..25eb44604 100644 --- a/module/plugins/hoster/Ftp.py +++ b/module/plugins/hoster/Ftp.py @@ -5,13 +5,14 @@ import re import urllib import urlparse -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster class Ftp(Hoster): __name__ = "Ftp" __type__ = "hoster" - __version__ = "0.52" + __version__ = "0.54" + __status__ = "testing" __pattern__ = r'(?:ftps?|sftp)://([\w.-]+(:[\w.-]+)?@)?[\w.-]+(:\d+)?/.+' @@ -23,8 +24,8 @@ class Ftp(Hoster): def setup(self): - self.chunkLimit = -1 - self.resumeDownload = True + self.chunk_limit = -1 + self.resume_download = True def process(self, pyfile): @@ -41,10 +42,10 @@ class Ftp(Hoster): servers = [x['login'] for x in self.account.getAllAccounts()] if self.account else [] if netloc in servers: - self.logDebug("Logging on to %s" % netloc) - self.req.addAuth(self.account.getAccountInfo(netloc)['password']) + self.log_debug("Logging on to %s" % netloc) + self.req.addAuth(self.account.get_info(netloc)['login']['password']) else: - pwd = self.getPassword() + pwd = self.get_password() if ':' in pwd: self.req.addAuth(pwd) @@ -56,22 +57,22 @@ class Ftp(Hoster): self.fail(_("Error %d: %s") % e.args) self.req.http.c.setopt(pycurl.NOBODY, 0) - self.logDebug(self.req.http.header) + self.log_debug(self.req.http.header) m = re.search(r"Content-Length:\s*(\d+)", res) if m: pyfile.size = int(m.group(1)) self.download(pyfile.url) else: - #Naive ftp directory listing + #: Naive ftp directory listing if re.search(r'^25\d.*?"', self.req.http.header, re.M): pyfile.url = pyfile.url.rstrip('/') pkgname = "/".join([pyfile.package().name, urlparse.urlparse(pyfile.url).path.rpartition('/')[2]]) pyfile.url += '/' - self.req.http.c.setopt(48, 1) # CURLOPT_DIRLISTONLY + self.req.http.c.setopt(48, 1) #: CURLOPT_DIRLISTONLY res = self.load(pyfile.url, decode=False) - links = [pyfile.url + urllib.quote(x) for x in res.splitlines()] - self.logDebug("LINKS", links) - self.core.api.addPackage(pkgname, links) + links = [pyfile.url + x for x in res.splitlines()] + self.log_debug("LINKS", links) + self.pyload.api.addPackage(pkgname, links) else: self.fail(_("Unexpected server response")) diff --git a/module/plugins/hoster/GamefrontCom.py b/module/plugins/hoster/GamefrontCom.py index c68866f87..fb3b98f5e 100644 --- a/module/plugins/hoster/GamefrontCom.py +++ b/module/plugins/hoster/GamefrontCom.py @@ -1,90 +1,37 @@ # -*- coding: utf-8 -*- -import re +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from module.network.RequestFactory import getURL -from module.plugins.Hoster import Hoster -from module.utils import parseFileSize - -class GamefrontCom(Hoster): +class GamefrontCom(SimpleHoster): __name__ = "GamefrontCom" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.09" + __status__ = "testing" - __pattern__ = r'http://(?:www\.)?gamefront\.com/files/\w+' + __pattern__ = r'http://(?:www\.)?gamefront\.com/files/(?P<ID>\d+)' __description__ = """Gamefront.com hoster plugin""" __license__ = "GPLv3" - __authors__ = [("fwannmacher", "felipe@warhammerproject.com")] + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + NAME_PATTERN = r'<title>(?P<N>.+?) \| Game Front</title>' + SIZE_PATTERN = r'>File Size:</dt>\s*<dd>(?P<S>[\d.,]+) (?P<U>[\w^_]+)' + OFFLINE_PATTERN = r'<p>File not found' - PATTERN_FILENAME = r'<title>(.*?) | Game Front' - PATTERN_FILESIZE = r'<dt>File Size:</dt>[\n\s]*<dd>(.*?)</dd>' - PATTERN_OFFLINE = r'This file doesn\'t exist, or has been removed.' + LINK_FREE_PATTERN = r"downloadUrl = '(.+?)'" def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - self.chunkLimit = -1 - - - def process(self, pyfile): - self.pyfile = pyfile - self.html = self.load(pyfile.url, decode=True) - - if not self._checkOnline(): - self.offline() - - pyfile.name = self._getName() - - link = self._getLink() - - if not link.startswith('http://'): - link = "http://www.gamefront.com/" + link - - self.download(link) - - - def _checkOnline(self): - if re.search(self.PATTERN_OFFLINE, self.html): - return False - else: - return True - - - def _getName(self): - name = re.search(self.PATTERN_FILENAME, self.html) - if name is None: - self.fail(_("Plugin broken") - - return name.group(1) - - - def _getLink(self): - self.html2 = self.load("http://www.gamefront.com/" + re.search("(files/service/thankyou\\?id=\w+)", - self.html).group(1)) - return re.search("<a href=\"(http://media\d+\.gamefront.com/.*)\">click here</a>", self.html2).group(1).replace("&", "&") - - -def getInfo(urls): - result = [] - for url in urls: - html = getURL(url) - if re.search(GamefrontCom.PATTERN_OFFLINE, html): - result.append((url, 0, 1, url)) - else: - name = re.search(GamefrontCom.PATTERN_FILENAME, html) - if name is None: - result.append((url, 0, 1, url)) - else: - name = name.group(1) - size = re.search(GamefrontCom.PATTERN_FILESIZE, html) - size = parseFileSize(size.group(1)) + def handle_free(self, pyfile): + self.html = self.load("http://www.gamefront.com/files/service/thankyou", + get={'id': self.info['pattern']['ID']}) + return super(GamefrontCom, self).handle_free(pyfile) - result.append((name, size, 3, url)) - yield result +getInfo = create_getInfo(GamefrontCom) diff --git a/module/plugins/hoster/GigapetaCom.py b/module/plugins/hoster/GigapetaCom.py index c2feeb6f8..381c39a21 100644 --- a/module/plugins/hoster/GigapetaCom.py +++ b/module/plugins/hoster/GigapetaCom.py @@ -10,7 +10,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class GigapetaCom(SimpleHoster): __name__ = "GigapetaCom" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?gigapeta\.com/dl/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -29,27 +30,27 @@ class GigapetaCom(SimpleHoster): COOKIES = [("gigapeta.com", "lang", "us")] - def handleFree(self, pyfile): + def handle_free(self, pyfile): captcha_key = str(random.randint(1, 100000000)) captcha_url = "http://gigapeta.com/img/captcha.gif?x=%s" % captcha_key self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0) for _i in xrange(5): - self.checkErrors() + self.check_errors() - captcha = self.decryptCaptcha(captcha_url) + captcha = self.captcha.decrypt(captcha_url) self.html = self.load(pyfile.url, post={ - "captcha_key": captcha_key, - "captcha": captcha, - "download": "Download"}) + 'captcha_key': captcha_key, + 'captcha': captcha, + 'download': "Download"}) m = re.search(r'Location\s*:\s*(.+)', self.req.http.header, re.I) if m: self.link = m.group(1).rstrip() #@TODO: Remove .rstrip() in 0.4.10 break elif "Entered figures don`t coincide with the picture" in self.html: - self.invalidCaptcha() + self.captcha.invalid() else: self.fail(_("No valid captcha code entered")) diff --git a/module/plugins/hoster/GooIm.py b/module/plugins/hoster/GooIm.py index 4b27e6cc8..2c2f4aa9e 100644 --- a/module/plugins/hoster/GooIm.py +++ b/module/plugins/hoster/GooIm.py @@ -11,7 +11,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class GooIm(SimpleHoster): __name__ = "GooIm" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?goo\.im/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -26,11 +27,11 @@ class GooIm(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.wait(10) self.link = pyfile.url diff --git a/module/plugins/hoster/GoogledriveCom.py b/module/plugins/hoster/GoogledriveCom.py index 1c33a1e4e..903b5361e 100644 --- a/module/plugins/hoster/GoogledriveCom.py +++ b/module/plugins/hoster/GoogledriveCom.py @@ -13,7 +13,8 @@ from module.utils import html_unescape class GoogledriveCom(SimpleHoster): __name__ = "GoogledriveCom" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.14" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(drive|docs)\.google\.com/(file/d/\w+|uc\?.*id=)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -23,8 +24,6 @@ class GoogledriveCom(SimpleHoster): __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")] - DISPOSITION = False #: Remove in 0.4.10 - NAME_PATTERN = r'(?:<title>|class="uc-name-size".*>)(?P<N>.+?)(?: - Google Drive</title>|</a> \()' OFFLINE_PATTERN = r'align="center"><p class="errorMessage"' @@ -33,11 +32,11 @@ class GoogledriveCom(SimpleHoster): def setup(self): self.multiDL = True - self.resumeDownload = True - self.chunkLimit = 1 + self.resume_download = True + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): for _i in xrange(2): m = re.search(self.LINK_FREE_PATTERN, self.html) @@ -49,9 +48,9 @@ class GoogledriveCom(SimpleHoster): if not urlparse.urlparse(link).scheme: link = urlparse.urljoin("https://docs.google.com/", link) - direct_link = self.directLink(link, False) + direct_link = self.direct_link(link, False) if not direct_link: - self.html = self.load(link, decode=True) + self.html = self.load(link) else: self.link = direct_link break diff --git a/module/plugins/hoster/HellshareCz.py b/module/plugins/hoster/HellshareCz.py index ac0043b37..eab819ad9 100644 --- a/module/plugins/hoster/HellshareCz.py +++ b/module/plugins/hoster/HellshareCz.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class HellshareCz(SimpleHoster): __name__ = "HellshareCz" __type__ = "hoster" - __version__ = "0.85" + __version__ = "0.86" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?hellshare\.(?:cz|com|sk|hu|pl)/[^?]*/\d+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -29,8 +30,8 @@ class HellshareCz(SimpleHoster): def setup(self): - self.resumeDownload = self.multiDL = bool(self.account) - self.chunkLimit = 1 + self.resume_download = self.multiDL = bool(self.account) + self.chunk_limit = 1 getInfo = create_getInfo(HellshareCz) diff --git a/module/plugins/hoster/HellspyCz.py b/module/plugins/hoster/HellspyCz.py index 9b10760bd..499a94413 100644 --- a/module/plugins/hoster/HellspyCz.py +++ b/module/plugins/hoster/HellspyCz.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class HellspyCz(DeadHoster): __name__ = "HellspyCz" __type__ = "hoster" - __version__ = "0.28" + __version__ = "0.29" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(?:hellspy\.(?:cz|com|sk|hu|pl)|sciagaj\.pl)(/\S+/\d+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/HighWayMe.py b/module/plugins/hoster/HighWayMe.py new file mode 100644 index 000000000..119ddb70e --- /dev/null +++ b/module/plugins/hoster/HighWayMe.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo +from module.plugins.internal.SimpleHoster import seconds_to_midnight + + +class HighWayMe(MultiHoster): + __name__ = "HighWayMe" + __type__ = "hoster" + __version__ = "0.13" + __status__ = "testing" + + __pattern__ = r'https?://.+high-way\.my' + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] + + __description__ = """High-Way.me multi-hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("EvolutionClip", "evolutionclip@live.de")] + + + def setup(self): + self.chunk_limit = 4 + + + def check_errors(self): + if self.html.get('code') == 302: #@NOTE: This is not working. It should by if 302 Moved Temporarily then... But I don't now how to implement it. + self.account.relogin(self.user) + self.retry() + + elif "<code>9</code>" in self.html: + self.offline() + + elif "downloadlimit" in self.html: + self.log_warning(_("Reached maximum connctions")) + self.retry(5, 60, _("Reached maximum connctions")) + + elif "trafficlimit" in self.html: + self.log_warning(_("Reached daily limit")) + self.retry(wait_time=seconds_to_midnight(gmt=2), reason="Daily limit for this host reached") + + elif "<code>8</code>" in self.html: + self.log_warning(_("Hoster temporarily unavailable, waiting 1 minute and retry")) + self.retry(5, 60, _("Hoster is temporarily unavailable")) + + + def handle_premium(self, pyfile): + for _i in xrange(5): + self.html = self.load("https://high-way.me/load.php", + get={'link': self.pyfile.url}) + + if self.html: + self.log_debug("JSON data: " + self.html) + break + else: + self.log_info(_("Unable to get API data, waiting 1 minute and retry")) + self.retry(5, 60, _("Unable to get API data")) + + self.check_errors() + + try: + self.pyfile.name = re.search(r'<name>([^<]+)</name>', self.html).group(1) + + except AttributeError: + self.pyfile.name = "" + + try: + self.pyfile.size = re.search(r'<size>(\d+)</size>', self.html).group(1) + + except AttributeError: + self.pyfile.size = 0 + + self.link = re.search(r'<download>([^<]+)</download>', self.html).group(1) + + +getInfo = create_getInfo(HighWayMe) diff --git a/module/plugins/hoster/HostujeNet.py b/module/plugins/hoster/HostujeNet.py index ec91e50b9..4dbf550b3 100644 --- a/module/plugins/hoster/HostujeNet.py +++ b/module/plugins/hoster/HostujeNet.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class HostujeNet(SimpleHoster): __name__ = "HostujeNet" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?hostuje\.net/\w+' @@ -24,10 +25,10 @@ class HostujeNet(SimpleHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(r'<script src="([\w^_]+.php)"></script>', self.html) if m: jscript = self.load("http://hostuje.net/" + m.group(1)) @@ -39,7 +40,7 @@ class HostujeNet(SimpleHoster): else: self.error(_("script not found")) - action, inputs = self.parseHtmlForm(pyfile.url.replace(".", "\.").replace( "?", "\?")) + action, inputs = self.parse_html_form(pyfile.url.replace(".", "\.").replace( "?", "\?")) if not action: self.error(_("form not found")) diff --git a/module/plugins/hoster/HotfileCom.py b/module/plugins/hoster/HotfileCom.py index 082415c6b..032bd350e 100644 --- a/module/plugins/hoster/HotfileCom.py +++ b/module/plugins/hoster/HotfileCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class HotfileCom(DeadHoster): __name__ = "HotfileCom" __type__ = "hoster" - __version__ = "0.37" + __version__ = "0.38" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?hotfile\.com/dl/\d+/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/HugefilesNet.py b/module/plugins/hoster/HugefilesNet.py index 3fdcca1ba..582d17756 100644 --- a/module/plugins/hoster/HugefilesNet.py +++ b/module/plugins/hoster/HugefilesNet.py @@ -8,7 +8,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class HugefilesNet(XFSHoster): __name__ = "HugefilesNet" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?hugefiles\.net/\w{12}' diff --git a/module/plugins/hoster/HundredEightyUploadCom.py b/module/plugins/hoster/HundredEightyUploadCom.py index 2a35a008f..9b3550922 100644 --- a/module/plugins/hoster/HundredEightyUploadCom.py +++ b/module/plugins/hoster/HundredEightyUploadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class HundredEightyUploadCom(XFSHoster): __name__ = "HundredEightyUploadCom" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?180upload\.com/\w{12}' diff --git a/module/plugins/hoster/IFileWs.py b/module/plugins/hoster/IFileWs.py index ff263d43a..2444846d7 100644 --- a/module/plugins/hoster/IFileWs.py +++ b/module/plugins/hoster/IFileWs.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class IFileWs(DeadHoster): __name__ = "IFileWs" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?ifile\.ws/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/IcyFilesCom.py b/module/plugins/hoster/IcyFilesCom.py index f81381c66..975e6bfc0 100644 --- a/module/plugins/hoster/IcyFilesCom.py +++ b/module/plugins/hoster/IcyFilesCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class IcyFilesCom(DeadHoster): __name__ = "IcyFilesCom" __type__ = "hoster" - __version__ = "0.06" + __version__ = "0.07" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?icyfiles\.com/(.+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/IfileIt.py b/module/plugins/hoster/IfileIt.py index ef267b505..a0c435762 100644 --- a/module/plugins/hoster/IfileIt.py +++ b/module/plugins/hoster/IfileIt.py @@ -6,12 +6,13 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class IfileIt(DeadHoster): __name__ = "IfileIt" __type__ = "hoster" - __version__ = "0.29" + __version__ = "0.30" + __status__ = "testing" __pattern__ = r'^unmatchable$' __config__ = [] #@TODO: Remove in 0.4.10 - __description__ = """Ifile.it""" + __description__ = """Ifile.it hoster plugin""" __license__ = "GPLv3" __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] diff --git a/module/plugins/hoster/IfolderRu.py b/module/plugins/hoster/IfolderRu.py index 0f09731e4..85d03489d 100644 --- a/module/plugins/hoster/IfolderRu.py +++ b/module/plugins/hoster/IfolderRu.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class IfolderRu(SimpleHoster): __name__ = "IfolderRu" __type__ = "hoster" - __version__ = "0.39" + __version__ = "0.40" + __status__ = "testing" __pattern__ = r'http://(?:www)?(files\.)?(ifolder\.ru|metalarea\.org|rusfolder\.(com|net|ru))/(files/)?(?P<ID>\d+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -34,27 +35,27 @@ class IfolderRu(SimpleHoster): def setup(self): - self.resumeDownload = self.multiDL = bool(self.account) - self.chunkLimit = 1 + self.resume_download = self.multiDL = bool(self.account) + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): url = "http://rusfolder.com/%s" % self.info['pattern']['ID'] - self.html = self.load("http://rusfolder.com/%s" % self.info['pattern']['ID'], decode=True) - self.getFileInfo() + self.html = self.load("http://rusfolder.com/%s" % self.info['pattern']['ID']) + self.get_fileInfo() session_id = re.search(self.SESSION_ID_PATTERN, self.html).groups() captcha_url = "http://ints.rusfolder.com/random/images/?session=%s" % session_id for _i in xrange(5): - action, inputs = self.parseHtmlForm('id="download-step-one-form"') - inputs['confirmed_number'] = self.decryptCaptcha(captcha_url, cookies=True) + action, inputs = self.parse_html_form('id="download-step-one-form"') + inputs['confirmed_number'] = self.captcha.decrypt(captcha_url, cookies=True) inputs['action'] = '1' - self.logDebug(inputs) + self.log_debug(inputs) - self.html = self.load(url, decode=True, post=inputs) + self.html = self.load(url, post=inputs) if self.WRONG_CAPTCHA_PATTERN in self.html: - self.invalidCaptcha() + self.captcha.invalid() else: break else: diff --git a/module/plugins/hoster/JumbofilesCom.py b/module/plugins/hoster/JumbofilesCom.py index a9bf14c6d..e9c084c95 100644 --- a/module/plugins/hoster/JumbofilesCom.py +++ b/module/plugins/hoster/JumbofilesCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class JumbofilesCom(SimpleHoster): __name__ = "JumbofilesCom" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?jumbofiles\.com/(?P<ID>\w{12})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -24,13 +25,13 @@ class JumbofilesCom(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - def handleFree(self, pyfile): - post_data = {"id": self.info['pattern']['ID'], "op": "download3", "rand": ""} - html = self.load(self.pyfile.url, post=post_data, decode=True) + def handle_free(self, pyfile): + post_data = {'id': self.info['pattern']['ID'], 'op': "download3", 'rand': ""} + html = self.load(self.pyfile.url, post=post_data) self.link = re.search(self.LINK_FREE_PATTERN, html).group(1) diff --git a/module/plugins/hoster/JunocloudMe.py b/module/plugins/hoster/JunocloudMe.py index 415d5e2d0..4483ccd5d 100644 --- a/module/plugins/hoster/JunocloudMe.py +++ b/module/plugins/hoster/JunocloudMe.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class JunocloudMe(XFSHoster): __name__ = "JunocloudMe" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:\w+\.)?junocloud\.me/\w{12}' diff --git a/module/plugins/hoster/Keep2ShareCc.py b/module/plugins/hoster/Keep2ShareCc.py index fb94d12c4..bf4b157cb 100644 --- a/module/plugins/hoster/Keep2ShareCc.py +++ b/module/plugins/hoster/Keep2ShareCc.py @@ -3,14 +3,15 @@ import re import urlparse -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class Keep2ShareCc(SimpleHoster): __name__ = "Keep2ShareCc" __type__ = "hoster" - __version__ = "0.22" + __version__ = "0.24" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(keep2share|k2s|keep2s)\.cc/file/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -23,7 +24,7 @@ class Keep2ShareCc(SimpleHoster): URL_REPLACEMENTS = [(__pattern__ + ".*", "http://keep2s.cc/file/\g<ID>")] - NAME_PATTERN = r'File: <span>(?P<N>.+)</span>' + NAME_PATTERN = r'File: <span>(?P<N>.+?)</span>' SIZE_PATTERN = r'Size: (?P<S>[^<]+)</div>' OFFLINE_PATTERN = r'File not found or deleted|Sorry, this file is blocked or deleted|Error 404' @@ -39,7 +40,7 @@ class Keep2ShareCc(SimpleHoster): ERROR_PATTERN = r'>\s*(Free user can\'t download large files|You no can access to this file|This download available only for premium users|This is private file)' - def checkErrors(self): + def check_errors(self): m = re.search(self.TEMP_ERROR_PATTERN, self.html) if m: self.info['error'] = m.group(1) @@ -53,9 +54,9 @@ class Keep2ShareCc(SimpleHoster): m = re.search(self.WAIT_PATTERN, self.html) if m: - self.logDebug("Hoster told us to wait for %s" % m.group(1)) + self.log_debug("Hoster told us to wait for %s" % m.group(1)) - # string to time convert courtesy of https://stackoverflow.com/questions/10663720 + #: String to time convert courtesy of https://stackoverflow.com/questions/10663720 ftr = [3600, 60, 1] wait_time = sum(a * b for a, b in zip(ftr, map(int, m.group(1).split(':')))) @@ -65,18 +66,18 @@ class Keep2ShareCc(SimpleHoster): self.info.pop('error', None) - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.fid = re.search(r'<input type="hidden" name="slow_id" value="(.+?)">', self.html).group(1) self.html = self.load(pyfile.url, post={'yt0': '', 'slow_id': self.fid}) - # self.logDebug(self.fid) - # self.logDebug(pyfile.url) + # self.log_debug(self.fid) + # self.log_debug(pyfile.url) - self.checkErrors() + self.check_errors() m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: - self.handleCaptcha() + self.handle_captcha() self.wait(31) self.html = self.load(pyfile.url) @@ -87,20 +88,20 @@ class Keep2ShareCc(SimpleHoster): self.link = m.group(1) - def handleCaptcha(self): + def handle_captcha(self): post_data = {'free' : 1, 'freeDownloadRequest': 1, 'uniqueId' : self.fid, 'yt0' : ''} m = re.search(r'id="(captcha\-form)"', self.html) - self.logDebug("captcha-form found %s" % m) + self.log_debug("captcha-form found %s" % m) m = re.search(self.CAPTCHA_PATTERN, self.html) - self.logDebug("CAPTCHA_PATTERN found %s" % m) + self.log_debug("CAPTCHA_PATTERN found %s" % m) if m: captcha_url = urlparse.urljoin("http://keep2s.cc/", m.group(1)) - post_data['CaptchaForm[code]'] = self.decryptCaptcha(captcha_url) + post_data['CaptchaForm[code]'] = self.captcha.decrypt(captcha_url) else: recaptcha = ReCaptcha(self) response, challenge = recaptcha.challenge() @@ -110,9 +111,9 @@ class Keep2ShareCc(SimpleHoster): self.html = self.load(self.pyfile.url, post=post_data) if 'verification code is incorrect' not in self.html: - self.correctCaptcha() + self.captcha.correct() else: - self.invalidCaptcha() + self.captcha.invalid() getInfo = create_getInfo(Keep2ShareCc) diff --git a/module/plugins/hoster/KickloadCom.py b/module/plugins/hoster/KickloadCom.py index 7690c85c8..2b23b1616 100644 --- a/module/plugins/hoster/KickloadCom.py +++ b/module/plugins/hoster/KickloadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class KickloadCom(DeadHoster): __name__ = "KickloadCom" __type__ = "hoster" - __version__ = "0.21" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?kickload\.com/get/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/KingfilesNet.py b/module/plugins/hoster/KingfilesNet.py index 42547d658..98f74ad0d 100644 --- a/module/plugins/hoster/KingfilesNet.py +++ b/module/plugins/hoster/KingfilesNet.py @@ -2,14 +2,15 @@ import re -from module.plugins.internal.SolveMedia import SolveMedia +from module.plugins.captcha.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class KingfilesNet(SimpleHoster): __name__ = "KingfilesNet" __type__ = "hoster" - __version__ = "0.08" + __version__ = "0.09" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?kingfiles\.net/(?P<ID>\w{12})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -31,12 +32,12 @@ class KingfilesNet(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - def handleFree(self, pyfile): - # Click the free user button + def handle_free(self, pyfile): + #: Click the free user button post_data = {'op' : "download1", 'usr_login' : "", 'id' : self.info['pattern']['ID'], @@ -44,18 +45,18 @@ class KingfilesNet(SimpleHoster): 'referer' : "", 'method_free': "+"} - self.html = self.load(pyfile.url, post=post_data, decode=True) + self.html = self.load(pyfile.url, post=post_data) solvemedia = SolveMedia(self) response, challenge = solvemedia.challenge() - # Make the downloadlink appear and load the file + #: Make the downloadlink appear and load the file m = re.search(self.RAND_ID_PATTERN, self.html) if m is None: self.error(_("Random key not found")) rand = m.group(1) - self.logDebug("rand = ", rand) + self.log_debug("rand = ", rand) post_data = {'op' : "download2", 'id' : self.info['pattern']['ID'], @@ -67,7 +68,7 @@ class KingfilesNet(SimpleHoster): 'adcopy_challenge': challenge, 'down_direct' : "1"} - self.html = self.load(pyfile.url, post=post_data, decode=True) + self.html = self.load(pyfile.url, post=post_data) m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: diff --git a/module/plugins/hoster/LemUploadsCom.py b/module/plugins/hoster/LemUploadsCom.py index 098867c8b..1f4f96a1f 100644 --- a/module/plugins/hoster/LemUploadsCom.py +++ b/module/plugins/hoster/LemUploadsCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class LemUploadsCom(DeadHoster): __name__ = "LemUploadsCom" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?lemuploads\.com/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/LetitbitNet.py b/module/plugins/hoster/LetitbitNet.py index 62afb6c7c..e93b60460 100644 --- a/module/plugins/hoster/LetitbitNet.py +++ b/module/plugins/hoster/LetitbitNet.py @@ -10,22 +10,22 @@ import re import urlparse from module.common.json_layer import json_loads, json_dumps -from module.network.RequestFactory import getURL -from module.plugins.internal.ReCaptcha import ReCaptcha -from module.plugins.internal.SimpleHoster import SimpleHoster, secondsToMidnight +from module.network.RequestFactory import getURL as get_url +from module.plugins.captcha.ReCaptcha import ReCaptcha +from module.plugins.internal.SimpleHoster import SimpleHoster, seconds_to_midnight def api_response(url): - json_data = ["yw7XQy2v9", ["download/info", {"link": url}]] - api_rep = getURL("http://api.letitbit.net/json", - post={'r': json_dumps(json_data)}) + json_data = ["yw7XQy2v9", ["download/info", {'link': url}]] + api_rep = get_url("http://api.letitbit.net/json", + post={'r': json_dumps(json_data)}) return json_loads(api_rep) -def getInfo(urls): +def get_info(urls): for url in urls: api_rep = api_response(url) - if api_rep['status'] == 'OK': + if api_rep['status'] == "OK": info = api_rep['data'][0] yield (info['name'], info['size'], 2, url) else: @@ -35,7 +35,8 @@ def getInfo(urls): class LetitbitNet(SimpleHoster): __name__ = "LetitbitNet" __type__ = "hoster" - __version__ = "0.31" + __version__ = "0.32" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(letitbit|shareflare)\.net/download/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -53,16 +54,16 @@ class LetitbitNet(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True - def handleFree(self, pyfile): - action, inputs = self.parseHtmlForm('id="ifree_form"') + def handle_free(self, pyfile): + action, inputs = self.parse_html_form('id="ifree_form"') if not action: self.error(_("ifree_form")) pyfile.size = float(inputs['sssize']) - self.logDebug(action, inputs) + self.log_debug(action, inputs) inputs['desc'] = "" self.html = self.load(urlparse.urljoin("http://letitbit.net/", action), post=inputs) @@ -70,12 +71,12 @@ class LetitbitNet(SimpleHoster): m = re.search(self.SECONDS_PATTERN, self.html) seconds = int(m.group(1)) if m else 60 - self.logDebug("Seconds found", seconds) + self.log_debug("Seconds found", seconds) m = re.search(self.CAPTCHA_CONTROL_FIELD, self.html) recaptcha_control_field = m.group(1) - self.logDebug("ReCaptcha control field found", recaptcha_control_field) + self.log_debug("ReCaptcha control field found", recaptcha_control_field) self.wait(seconds) @@ -83,30 +84,30 @@ class LetitbitNet(SimpleHoster): if res != '1': self.error(_("Unknown response - ajax_check_url")) - self.logDebug(res) + self.log_debug(res) recaptcha = ReCaptcha(self) response, challenge = recaptcha.challenge() - post_data = {"recaptcha_challenge_field": challenge, - "recaptcha_response_field": response, - "recaptcha_control_field": recaptcha_control_field} + post_data = {'recaptcha_challenge_field': challenge, + 'recaptcha_response_field': response, + 'recaptcha_control_field': recaptcha_control_field} - self.logDebug("Post data to send", post_data) + self.log_debug("Post data to send", post_data) res = self.load("http://letitbit.net/ajax/check_recaptcha.php", post=post_data) - self.logDebug(res) + self.log_debug(res) if not res: - self.invalidCaptcha() + self.captcha.invalid() if res == "error_free_download_blocked": - self.logWarning(_("Daily limit reached")) - self.wait(secondsToMidnight(gmt=2), True) + self.log_warning(_("Daily limit reached")) + self.wait(seconds_to_midnight(gmt=2), True) if res == "error_wrong_captcha": - self.invalidCaptcha() + self.captcha.invalid() self.retry() elif res.startswith('['): @@ -121,16 +122,16 @@ class LetitbitNet(SimpleHoster): self.link = urls[0] - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): api_key = self.user - premium_key = self.account.getAccountData(self.user)['password'] + premium_key = self.account.get_info(self.user)['login']['password'] - json_data = [api_key, ["download/direct_links", {"pass": premium_key, "link": pyfile.url}]] + json_data = [api_key, ["download/direct_links", {'pass': premium_key, 'link': pyfile.url}]] api_rep = self.load('http://api.letitbit.net/json', post={'r': json_dumps(json_data)}) - self.logDebug("API Data: " + api_rep) + self.log_debug("API Data: " + api_rep) api_rep = json_loads(api_rep) - if api_rep['status'] == 'FAIL': + if api_rep['status'] == "FAIL": self.fail(api_rep['data']) self.link = api_rep['data'][0][0] diff --git a/module/plugins/hoster/LinksnappyCom.py b/module/plugins/hoster/LinksnappyCom.py index 9c3af4ae3..1c3f86d4a 100644 --- a/module/plugins/hoster/LinksnappyCom.py +++ b/module/plugins/hoster/LinksnappyCom.py @@ -10,30 +10,29 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class LinksnappyCom(MultiHoster): __name__ = "LinksnappyCom" __type__ = "hoster" - __version__ = "0.08" + __version__ = "0.11" + __status__ = "testing" __pattern__ = r'https?://(?:[^/]+\.)?linksnappy\.com' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Linksnappy.com multi-hoster plugin""" __license__ = "GPLv3" __authors__ = [("stickell", "l.stickell@yahoo.it")] - SINGLE_CHUNK_HOSTERS = ["easybytez.com"] - - - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): host = self._get_host(pyfile.url) json_params = json_dumps({'link' : pyfile.url, 'type' : host, 'username': self.user, - 'password': self.account.getAccountData(self.user)['password']}) + 'password': self.account.get_info(self.user)['login']['password']}) - r = self.load("http://gen.linksnappy.com/genAPI.php", + r = self.load("http://linksnappy.com/api/linkgen", post={'genLinks': json_params}) - self.logDebug("JSON data: " + r) + self.log_debug("JSON data: " + r) j = json_loads(r)['links'][0] @@ -43,11 +42,6 @@ class LinksnappyCom(MultiHoster): pyfile.name = j['filename'] self.link = j['generated'] - if host in self.SINGLE_CHUNK_HOSTERS: - self.chunkLimit = 1 - else: - self.setup() - @staticmethod def _get_host(url): diff --git a/module/plugins/hoster/LoadTo.py b/module/plugins/hoster/LoadTo.py index d2b25f0db..7a42e0360 100644 --- a/module/plugins/hoster/LoadTo.py +++ b/module/plugins/hoster/LoadTo.py @@ -6,25 +6,26 @@ import re -from module.plugins.internal.SolveMedia import SolveMedia +from module.plugins.captcha.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class LoadTo(SimpleHoster): __name__ = "LoadTo" __type__ = "hoster" - __version__ = "0.23" + __version__ = "0.25" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?load\.to/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] - __description__ = """ Load.to hoster plugin """ + __description__ = """Load.to hoster plugin""" __license__ = "GPLv3" __authors__ = [("halfman", "Pulpan3@gmail.com"), ("stickell", "l.stickell@yahoo.it")] - NAME_PATTERN = r'<h1>(?P<N>.+)</h1>' + NAME_PATTERN = r'<h1>(?P<N>.+?)</h1>' SIZE_PATTERN = r'Size: (?P<S>[\d.,]+) (?P<U>[\w^_]+)' OFFLINE_PATTERN = r'>Can\'t find file' @@ -36,23 +37,23 @@ class LoadTo(SimpleHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): - # Search for Download URL + def handle_free(self, pyfile): + #: Search for Download URL m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: self.error(_("LINK_FREE_PATTERN not found")) self.link = m.group(1) - # Set Timer - may be obsolete + #: Set Timer - may be obsolete m = re.search(self.WAIT_PATTERN, self.html) if m: self.wait(m.group(1)) - # Load.to is using solvemedia captchas since ~july 2014: + #: Load.to is using solvemedia captchas since ~july 2014: solvemedia = SolveMedia(self) captcha_key = solvemedia.detect_key() diff --git a/module/plugins/hoster/LolabitsEs.py b/module/plugins/hoster/LolabitsEs.py index 61df5f0bb..766f9d5b8 100644 --- a/module/plugins/hoster/LolabitsEs.py +++ b/module/plugins/hoster/LolabitsEs.py @@ -1,15 +1,16 @@ # -*- coding: utf-8 -* -import HTMLParser import re from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.utils import html_unescape class LolabitsEs(SimpleHoster): __name__ = "LolabitsEs" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?lolabits\.es/.+' @@ -28,21 +29,22 @@ class LolabitsEs(SimpleHoster): def setup(self): - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): fileid = re.search(self.FILEID_PATTERN, self.html).group(1) - self.logDebug("FileID: " + fileid) + self.log_debug("FileID: " + fileid) token = re.search(self.TOKEN_PATTERN, self.html).group(1) - self.logDebug("Token: " + token) + self.log_debug("Token: " + token) self.html = self.load("http://lolabits.es/action/License/Download", post={'fileId' : fileid, - '__RequestVerificationToken' : token}).decode('unicode-escape') + '__RequestVerificationToken' : token}, + decode="unicode-escape") - self.link = HTMLParser.HTMLParser().unescape(re.search(self.LINK_PATTERN, self.html).group(1)) + self.link = html_unescape(re.search(self.LINK_PATTERN, self.html).group(1)) getInfo = create_getInfo(LolabitsEs) diff --git a/module/plugins/hoster/LomafileCom.py b/module/plugins/hoster/LomafileCom.py index ef05cd1ea..9e625a1eb 100644 --- a/module/plugins/hoster/LomafileCom.py +++ b/module/plugins/hoster/LomafileCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class LomafileCom(DeadHoster): __name__ = "LomafileCom" __type__ = "hoster" - __version__ = "0.52" + __version__ = "0.53" + __status__ = "testing" __pattern__ = r'http://lomafile\.com/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/LuckyShareNet.py b/module/plugins/hoster/LuckyShareNet.py index f4932d93d..788c1aca8 100644 --- a/module/plugins/hoster/LuckyShareNet.py +++ b/module/plugins/hoster/LuckyShareNet.py @@ -2,16 +2,16 @@ import re -from bottle import json_loads - -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.common.json_layer import json_loads +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class LuckyShareNet(SimpleHoster): __name__ = "LuckyShareNet" __type__ = "hoster" - __version__ = "0.07" + __version__ = "0.08" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?luckyshare\.net/(?P<ID>\d{10,})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -25,13 +25,13 @@ class LuckyShareNet(SimpleHoster): OFFLINE_PATTERN = r'There is no such file available' - def parseJson(self, rep): + def parse_json(self, rep): if 'AJAX Error' in rep: - html = self.load(self.pyfile.url, decode=True) + html = self.load(self.pyfile.url) m = re.search(r"waitingtime = (\d+);", html) if m: seconds = int(m.group(1)) - self.logDebug("You have to wait %d seconds between free downloads" % seconds) + self.log_debug("You have to wait %d seconds between free downloads" % seconds) self.retry(wait_time=seconds) else: self.error(_("Unable to detect wait time between free downloads")) @@ -40,14 +40,14 @@ class LuckyShareNet(SimpleHoster): return json_loads(rep) - # TODO: There should be a filesize limit for free downloads - # TODO: Some files could not be downloaded in free mode - def handleFree(self, pyfile): - rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + self.info['pattern']['ID'], decode=True) + #@TODO: There should be a filesize limit for free downloads + #: Some files could not be downloaded in free mode + def handle_free(self, pyfile): + rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + self.info['pattern']['ID']) - self.logDebug("JSON: " + rep) + self.log_debug("JSON: " + rep) - json = self.parseJson(rep) + json = self.parse_json(rep) self.wait(json['time']) recaptcha = ReCaptcha(self) @@ -55,14 +55,14 @@ class LuckyShareNet(SimpleHoster): for _i in xrange(5): response, challenge = recaptcha.challenge() rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" % - (challenge, response, json['hash']), decode=True) - self.logDebug("JSON: " + rep) + (challenge, response, json['hash'])) + self.log_debug("JSON: " + rep) if 'link' in rep: - json.update(self.parseJson(rep)) - self.correctCaptcha() + json.update(self.parse_json(rep)) + self.captcha.correct() break elif 'Verification failed' in rep: - self.invalidCaptcha() + self.captcha.invalid() else: self.error(_("Unable to get downlaod link")) diff --git a/module/plugins/hoster/MediafireCom.py b/module/plugins/hoster/MediafireCom.py index 09eb4705d..3ba191160 100644 --- a/module/plugins/hoster/MediafireCom.py +++ b/module/plugins/hoster/MediafireCom.py @@ -1,14 +1,15 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.ReCaptcha import ReCaptcha -from module.plugins.internal.SolveMedia import SolveMedia +from module.plugins.captcha.ReCaptcha import ReCaptcha +from module.plugins.captcha.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class MediafireCom(SimpleHoster): __name__ = "MediafireCom" __type__ = "hoster" - __version__ = "0.89" + __version__ = "0.90" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?mediafire\.com/(file/|view/\??|download(\.php\?|/)|\?)(?P<ID>\w{15})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -31,11 +32,11 @@ class MediafireCom(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - def handleCaptcha(self): + def handle_captcha(self): solvemedia = SolveMedia(self) captcha_key = solvemedia.detect_key() @@ -43,8 +44,7 @@ class MediafireCom(SimpleHoster): response, challenge = solvemedia.challenge(captcha_key) self.html = self.load("http://www.mediafire.com/?" + self.info['pattern']['ID'], post={'adcopy_challenge': challenge, - 'adcopy_response' : response}, - decode=True) + 'adcopy_response' : response}) return recaptcha = ReCaptcha(self) @@ -53,26 +53,25 @@ class MediafireCom(SimpleHoster): if captcha_key: response, challenge = recaptcha.challenge(captcha_key) self.html = self.load(self.pyfile.url, - post={'g-recaptcha-response': response}, - decode=True) + post={'g-recaptcha-response': response}) - def handleFree(self, pyfile): - self.handleCaptcha() + def handle_free(self, pyfile): + self.handle_captcha() if self.PASSWORD_PATTERN in self.html: - password = self.getPassword() + password = self.get_password() if not password: self.fail(_("No password found")) else: - self.logInfo(_("Password protected link, trying: ") + password) + self.log_info(_("Password protected link, trying: ") + password) self.html = self.load(self.link, post={'downloadp': password}) if self.PASSWORD_PATTERN in self.html: self.fail(_("Incorrect password")) - return super(MediafireCom, self).handleFree(pyfile) + return super(MediafireCom, self).handle_free(pyfile) getInfo = create_getInfo(MediafireCom) diff --git a/module/plugins/hoster/MegaCoNz.py b/module/plugins/hoster/MegaCoNz.py index aa7755af4..d8a29817c 100644 --- a/module/plugins/hoster/MegaCoNz.py +++ b/module/plugins/hoster/MegaCoNz.py @@ -12,7 +12,7 @@ from Crypto.Cipher import AES from Crypto.Util import Counter from module.common.json_layer import json_loads, json_dumps -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster from module.utils import decode, fs_decode, fs_encode @@ -48,9 +48,10 @@ from module.utils import decode, fs_decode, fs_encode class MegaCoNz(Hoster): __name__ = "MegaCoNz" __type__ = "hoster" - __version__ = "0.26" + __version__ = "0.31" + __status__ = "testing" - __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" @@ -67,8 +68,10 @@ class MegaCoNz(Hoster): return standard_b64decode(data + '=' * (-len(data) % 4)) - def getCipherKey(self, key): - """ Construct the cipher key from the given data """ + def get_cipher_key(self, key): + """ + Construct the cipher key from the given data + """ a = array.array("I", self.b64_decode(key)) k = array.array("I", (a[0] ^ a[4], a[1] ^ a[5], a[2] ^ a[6], a[3] ^ a[7])) @@ -79,44 +82,46 @@ class MegaCoNz(Hoster): def api_response(self, **kwargs): - """ 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) + """ + Dispatch a call to the api, see https://mega.co.nz/#developers + """ + #: Generate a session id, no idea where to obtain elsewhere + 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) + self.log_debug("Api Response: " + res) return json_loads(res) - def decryptAttr(self, data, key): - k, iv, meta_mac = self.getCipherKey(key) + def decrypt_attr(self, data, key): + k, iv, meta_mac = self.get_cipher_key(key) cbc = AES.new(k, AES.MODE_CBC, "\0" * 16) attr = decode(cbc.decrypt(self.b64_decode(data))) - self.logDebug("Decrypted Attr: %s" % attr) + self.log_debug("Decrypted Attr: %s" % attr) if not attr.startswith("MEGA"): self.fail(_("Decryption failed")) - # Data is padded, 0-bytes must be stripped + #: Data is padded, 0-bytes must be stripped return json_loads(re.search(r'{.+?}', attr).group(0)) - def decryptFile(self, key): - """ Decrypts the file at lastDownload` """ - - # upper 64 bit of counter start + def decrypt_file(self, key): + """ + Decrypts the file at last_download` + """ + #: Upper 64 bit of counter start n = self.b64_decode(key)[16:24] - # convert counter to long and shift bytes - k, iv, meta_mac = self.getCipherKey(key) + #: Convert counter to long and shift bytes + k, iv, meta_mac = self.get_cipher_key(key) ctr = Counter.new(128, initial_value=long(n.encode("hex"), 16) << 64) cipher = AES.new(k, AES.MODE_CTR, counter=ctr) self.pyfile.setStatus("decrypting") self.pyfile.setProgress(0) - file_crypted = fs_encode(self.lastDownload) + file_crypted = fs_encode(self.last_download) file_decrypted = file_crypted.rsplit(self.FILE_SUFFIX)[0] try: @@ -126,7 +131,7 @@ class MegaCoNz(Hoster): except IOError, e: self.fail(e) - chunk_size = 2 ** 15 # buffer size, 32k + chunk_size = 2 ** 15 #: Buffer size, 32k # file_mac = [0, 0, 0, 0] # calculate CBC-MAC for checksum chunks = os.path.getsize(file_crypted) / chunk_size + 1 @@ -158,22 +163,22 @@ class MegaCoNz(Hoster): f.close() df.close() - # if file_mac[0] ^ file_mac[1], file_mac[2] ^ file_mac[3] != meta_mac: + # if file_mac[0] ^ file_mac[1], file_mac[2] ^ file_mac[3] is not meta_mac: # os.remove(file_decrypted) # self.fail(_("Checksum mismatch")) os.remove(file_crypted) - self.lastDownload = fs_decode(file_decrypted) + self.last_download = fs_decode(file_decrypted) - def checkError(self, code): + def check_error(self, code): ecode = abs(code) if ecode in (9, 16, 21): self.offline() elif ecode in (3, 13, 17, 18, 19): - self.tempOffline() + self.temp_offline() elif ecode in (1, 4, 6, 10, 15, 21): self.retry(5, 30, _("Error code: [%s]") % -ecode) @@ -186,23 +191,23 @@ class MegaCoNz(Hoster): pattern = re.match(self.__pattern__, pyfile.url).groupdict() id = pattern['ID'] key = pattern['KEY'] - public = pattern['TYPE'] == '' + public = pattern['TYPE'] == "" - self.logDebug("ID: %s" % id, "Key: %s" % key, "Type: %s" % ("public" if public else "node")) + self.log_debug("ID: %s" % id, "Key: %s" % key, "Type: %s" % ("public" if public else "node")) - # g is for requesting a download url - # this is similar to the calls in the mega js app, documentation is very bad + #: G is for requesting a download url + #: This is similar to the calls in the mega js app, documentation is very bad if public: mega = self.api_response(a="g", g=1, p=id, ssl=1)[0] else: mega = self.api_response(a="g", g=1, n=id, ssl=1)[0] if isinstance(mega, int): - self.checkError(mega) + self.check_error(mega) elif "e" in mega: - self.checkError(mega['e']) + self.check_error(mega['e']) - attr = self.decryptAttr(mega['at'], key) + attr = self.decrypt_attr(mega['at'], key) pyfile.name = attr['n'] + self.FILE_SUFFIX pyfile.size = mega['s'] @@ -211,7 +216,7 @@ class MegaCoNz(Hoster): self.download(mega['g']) - self.decryptFile(key) + self.decrypt_file(key) - # Everything is finished and final name can be set + #: Everything is finished and final name can be set pyfile.name = attr['n'] diff --git a/module/plugins/hoster/MegaDebridEu.py b/module/plugins/hoster/MegaDebridEu.py index 9c8cc2a90..4afba0a3a 100644 --- a/module/plugins/hoster/MegaDebridEu.py +++ b/module/plugins/hoster/MegaDebridEu.py @@ -10,12 +10,14 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class MegaDebridEu(MultiHoster): __name__ = "MegaDebridEu" __type__ = "hoster" - __version__ = "0.47" + __version__ = "0.50" + __status__ = "testing" __pattern__ = r'http://((?:www\d+\.|s\d+\.)?mega-debrid\.eu|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/download/file/[\w^_]+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] - __description__ = """mega-debrid.eu multi-hoster plugin""" + __description__ = """Mega-debrid.eu multi-hoster plugin""" __license__ = "GPLv3" __authors__ = [("D.Ducatel", "dducatel@je-geek.fr")] @@ -28,9 +30,9 @@ class MegaDebridEu(MultiHoster): Connexion to the mega-debrid API Return True if succeed """ - user, data = self.account.selectAccount() + user, info = self.account.select() jsonResponse = self.load(self.API_URL, - get={'action': 'connectUser', 'login': user, 'password': data['password']}) + get={'action': 'connectUser', 'login': user, 'password': info['login']['password']}) res = json_loads(jsonResponse) if res['response_code'] == "ok": @@ -40,7 +42,7 @@ class MegaDebridEu(MultiHoster): return False - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): """ Debrid a link Return The debrided link if succeed or original link if fail diff --git a/module/plugins/hoster/MegaFilesSe.py b/module/plugins/hoster/MegaFilesSe.py index 249eff952..03c684751 100644 --- a/module/plugins/hoster/MegaFilesSe.py +++ b/module/plugins/hoster/MegaFilesSe.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class MegaFilesSe(DeadHoster): __name__ = "MegaFilesSe" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?megafiles\.se/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/MegaRapidCz.py b/module/plugins/hoster/MegaRapidCz.py index e17dd4730..13f462585 100644 --- a/module/plugins/hoster/MegaRapidCz.py +++ b/module/plugins/hoster/MegaRapidCz.py @@ -4,25 +4,26 @@ import pycurl import re from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getRequest -from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo +from module.network.RequestFactory import getRequest as get_request +from module.plugins.internal.SimpleHoster import SimpleHoster, parse_fileInfo -def getInfo(urls): - h = getRequest() +def get_info(urls): + h = get_request() h.c.setopt(pycurl.HTTPHEADER, ["Accept: text/html", "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0"]) for url in urls: - html = h.load(url, decode=True) - yield parseFileInfo(MegaRapidCz, url, html) + html = h.load(url) + yield parse_fileInfo(MegaRapidCz, url, html) class MegaRapidCz(SimpleHoster): __name__ = "MegaRapidCz" __type__ = "hoster" - __version__ = "0.56" + __version__ = "0.57" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(share|mega)rapid\.cz/soubor/\d+/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -48,10 +49,10 @@ class MegaRapidCz(SimpleHoster): def setup(self): - self.chunkLimit = 1 + self.chunk_limit = 1 - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): m = re.search(self.LINK_PREMIUM_PATTERN, self.html) if m: self.link = m.group(1) diff --git a/module/plugins/hoster/MegaRapidoNet.py b/module/plugins/hoster/MegaRapidoNet.py index a3b4c72ba..6676a565d 100644 --- a/module/plugins/hoster/MegaRapidoNet.py +++ b/module/plugins/hoster/MegaRapidoNet.py @@ -5,10 +5,10 @@ import random from module.plugins.internal.MultiHoster import MultiHoster -def random_with_N_digits(n): +def random_with_n_digits(n): rand = "0." not_zero = 0 - for i in range(1, n + 1): + for i in xrange(1, n + 1): r = random.randint(0, 9) if(r > 0): not_zero += 1 @@ -23,10 +23,12 @@ def random_with_N_digits(n): class MegaRapidoNet(MultiHoster): __name__ = "MegaRapidoNet" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?\w+\.megarapido\.net/\?file=\w+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """MegaRapido.net multi-hoster plugin""" __license__ = "GPLv3" @@ -38,17 +40,17 @@ class MegaRapidoNet(MultiHoster): ERROR_PATTERN = r'<\s*?div[^>]*?class\s*?=\s*?["\']?alert-message error.*?>([^<]*)' - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): self.html = self.load("http://megarapido.net/gerar.php", post={'rand' :random_with_N_digits(16), 'urllist' : pyfile.url, 'links' : pyfile.url, 'exibir' : "normal", 'usar' : "premium", - 'user' : self.account.getAccountInfo(self.user).get('sid', None), + 'user' : self.account.get_data(self.user).get('sid', None), 'autoreset': ""}) if "desloga e loga novamente para gerar seus links" in self.html.lower(): self.error("You have logged in at another place") - return super(MegaRapidoNet, self).handlePremium(pyfile) + return super(MegaRapidoNet, self).handle_premium(pyfile) diff --git a/module/plugins/hoster/MegacrypterCom.py b/module/plugins/hoster/MegacrypterCom.py index 10a2eb025..a67dca5da 100644 --- a/module/plugins/hoster/MegacrypterCom.py +++ b/module/plugins/hoster/MegacrypterCom.py @@ -10,7 +10,8 @@ from module.plugins.hoster.MegaCoNz import MegaCoNz class MegacrypterCom(MegaCoNz): __name__ = "MegacrypterCom" __type__ = "hoster" - __version__ = "0.22" + __version__ = "0.23" + __status__ = "testing" __pattern__ = r'https?://\w{0,10}\.?megacrypter\.com/[\w!-]+' @@ -24,26 +25,28 @@ class MegacrypterCom(MegaCoNz): def api_response(self, **kwargs): - """ Dispatch a call to the api, see megacrypter.com/api_doc """ - self.logDebug("JSON request: " + json_dumps(kwargs)) + """ + Dispatch a call to the api, see megacrypter.com/api_doc + """ + self.log_debug("JSON request: " + json_dumps(kwargs)) res = self.load(self.API_URL, post=json_dumps(kwargs)) - self.logDebug("API Response: " + res) + self.log_debug("API Response: " + res) return json_loads(res) def process(self, pyfile): - # match is guaranteed because plugin was chosen to handle url + #: Match is guaranteed because plugin was chosen to handle url node = re.match(self.__pattern__, pyfile.url).group(0) - # get Mega.co.nz link info + #: get Mega.co.nz link info info = self.api_response(link=node, m="info") - # get crypted file URL + #: Get crypted file URL dl = self.api_response(link=node, m="dl") - # TODO: map error codes, implement password protection + #@TODO: map error codes, implement password protection # if info['pass'] is True: - # crypted_file_key, md5_file_key = info['key'].split("#") + # crypted_file_key, md5_file_key = info['key'].split("#") key = self.b64_decode(info['key']) @@ -51,7 +54,7 @@ class MegacrypterCom(MegaCoNz): self.download(dl['url']) - self.decryptFile(key) + self.decrypt_file(key) - # Everything is finished and final name can be set + #: Everything is finished and final name can be set pyfile.name = info['name'] diff --git a/module/plugins/hoster/MegareleaseOrg.py b/module/plugins/hoster/MegareleaseOrg.py index 6349144ec..ab9a864c9 100644 --- a/module/plugins/hoster/MegareleaseOrg.py +++ b/module/plugins/hoster/MegareleaseOrg.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class MegareleaseOrg(DeadHoster): __name__ = "MegareleaseOrg" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?megarelease\.org/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/MegasharesCom.py b/module/plugins/hoster/MegasharesCom.py index ed2363fe3..b6692263f 100644 --- a/module/plugins/hoster/MegasharesCom.py +++ b/module/plugins/hoster/MegasharesCom.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class MegasharesCom(SimpleHoster): __name__ = "MegasharesCom" __type__ = "hoster" - __version__ = "0.28" + __version__ = "0.29" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(d\d{2}\.)?megashares\.com/((index\.php)?\?d\d{2}=|dl/)\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -35,15 +36,15 @@ class MegasharesCom(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = self.premium - def handlePremium(self, pyfile): - self.handleDownload(True) + def handle_premium(self, pyfile): + self.handle_download(True) - def handleFree(self, pyfile): + def handle_free(self, pyfile): if self.NO_SLOTS_PATTERN in self.html: self.retry(wait_time=5 * 60) @@ -55,10 +56,10 @@ class MegasharesCom(SimpleHoster): for _i in xrange(5): random_num = re.search(self.REACTIVATE_NUM_PATTERN, self.html).group(1) - verifyinput = self.decryptCaptcha("http://d01.megashares.com/index.php", + verifyinput = self.captcha.decrypt("http://d01.megashares.com/index.php", get={'secgfx': "gfx", 'random_num': random_num}) - self.logInfo(_("Reactivating passport %s: %s %s") % (passport_num, random_num, verifyinput)) + self.log_info(_("Reactivating passport %s: %s %s") % (passport_num, random_num, verifyinput)) res = self.load("http://d01.megashares.com%s" % request_uri, get={'rs' : "check_passport_renewal", @@ -69,10 +70,10 @@ class MegasharesCom(SimpleHoster): 'rsrnd[]' : str(int(time.time() * 1000))}) if 'Thank you for reactivating your passport.' in res: - self.correctCaptcha() + self.captcha.correct() self.retry() else: - self.invalidCaptcha() + self.captcha.invalid() else: self.fail(_("Failed to reactivate passport")) @@ -80,33 +81,33 @@ class MegasharesCom(SimpleHoster): if m: time = [int(x) for x in m.groups()] renew = time[0] + (time[1] * 60) + (time[2] * 60) - self.logDebug("Waiting %d seconds for a new passport" % renew) + self.log_debug("Waiting %d seconds for a new passport" % renew) self.retry(wait_time=renew, reason=_("Passport renewal")) - # Check traffic left on passport + #: Check traffic left on passport m = re.search(self.PASSPORT_LEFT_PATTERN, self.html, re.M | re.S) if m is None: self.fail(_("Passport not found")) - self.logInfo(_("Download passport: %s") % m.group(1)) + self.log_info(_("Download passport: %s") % m.group(1)) data_left = float(m.group(2)) * 1024 ** {'B': 0, 'KB': 1, 'MB': 2, 'GB': 3}[m.group(3)] - self.logInfo(_("Data left: %s %s (%d MB needed)") % (m.group(2), m.group(3), self.pyfile.size / 1048576)) + self.log_info(_("Data left: %s %s (%d MB needed)") % (m.group(2), m.group(3), self.pyfile.size / 1048576)) if not data_left: self.retry(wait_time=600, reason=_("Passport renewal")) - self.handleDownload(False) + self.handle_download(False) - def handleDownload(self, premium=False): - # Find download link; + def handle_download(self, premium=False): + #: Find download link m = re.search(self.LINK_PATTERN % (1 if premium else 2), self.html) msg = _('%s download URL' % ('Premium' if premium else 'Free')) if m is None: self.error(msg) self.link = m.group(1) - self.logDebug("%s: %s" % (msg, self.link)) + self.log_debug("%s: %s" % (msg, self.link)) getInfo = create_getInfo(MegasharesCom) diff --git a/module/plugins/hoster/MegauploadCom.py b/module/plugins/hoster/MegauploadCom.py index 590819f7f..468734c35 100644 --- a/module/plugins/hoster/MegauploadCom.py +++ b/module/plugins/hoster/MegauploadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class MegauploadCom(DeadHoster): __name__ = "MegauploadCom" __type__ = "hoster" - __version__ = "0.31" + __version__ = "0.32" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?megaupload\.com/\?.*&?(d|v)=\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/MegavideoCom.py b/module/plugins/hoster/MegavideoCom.py index accd079fc..a3339a932 100644 --- a/module/plugins/hoster/MegavideoCom.py +++ b/module/plugins/hoster/MegavideoCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class MegavideoCom(DeadHoster): __name__ = "MegavideoCom" __type__ = "hoster" - __version__ = "0.21" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?megavideo\.com/\?.*&?(d|v)=\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/MovReelCom.py b/module/plugins/hoster/MovReelCom.py index 2fe5184ae..dd70ce009 100644 --- a/module/plugins/hoster/MovReelCom.py +++ b/module/plugins/hoster/MovReelCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class MovReelCom(XFSHoster): __name__ = "MovReelCom" __type__ = "hoster" - __version__ = "1.24" + __version__ = "1.25" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?movreel\.com/\w{12}' diff --git a/module/plugins/hoster/MultihostersCom.py b/module/plugins/hoster/MultihostersCom.py index bcd7c6237..11c6c4379 100644 --- a/module/plugins/hoster/MultihostersCom.py +++ b/module/plugins/hoster/MultihostersCom.py @@ -6,7 +6,8 @@ from module.plugins.hoster.ZeveraCom import ZeveraCom class MultihostersCom(ZeveraCom): __name__ = "MultihostersCom" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)multihosters\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+' diff --git a/module/plugins/hoster/MultishareCz.py b/module/plugins/hoster/MultishareCz.py index bbb77f525..6b69fa9c2 100644 --- a/module/plugins/hoster/MultishareCz.py +++ b/module/plugins/hoster/MultishareCz.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class MultishareCz(SimpleHoster): __name__ = "MultishareCz" __type__ = "hoster" - __version__ = "0.40" + __version__ = "0.42" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?multishare\.cz/stahnout/(?P<ID>\d+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -22,26 +23,26 @@ class MultishareCz(SimpleHoster): SIZE_REPLACEMENTS = [(' ', '')] CHECK_TRAFFIC = True - MULTI_HOSTER = True + LEECH_HOSTER = True INFO_PATTERN = ur'(?:<li>Název|Soubor): <strong>(?P<N>[^<]+)</strong><(?:/li><li|br)>Velikost: <strong>(?P<S>[^<]+)</strong>' OFFLINE_PATTERN = ur'<h1>Stáhnout soubor</h1><p><strong>PoÅŸadovanÃœ soubor neexistuje.</strong></p>' - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.download("http://www.multishare.cz/html/download_free.php", get={'ID': self.info['pattern']['ID']}) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): self.download("http://www.multishare.cz/html/download_premium.php", get={'ID': self.info['pattern']['ID']}) - def handleMulti(self, pyfile): - self.html = self.load('http://www.multishare.cz/html/mms_ajax.php', post={"link": pyfile.url}, decode=True) + def handle_multi(self, pyfile): + self.html = self.load('http://www.multishare.cz/html/mms_ajax.php', post={'link': pyfile.url}) - self.checkInfo() + self.check_info() - if not self.checkTrafficLeft(): + if not self.check_traffic_left(): self.fail(_("Not enough credit left to download file")) self.download("http://dl%d.mms.multishare.cz/html/mms_process.php" % round(random.random() * 10000 * random.random()), diff --git a/module/plugins/hoster/MyfastfileCom.py b/module/plugins/hoster/MyfastfileCom.py index 662638843..bbd678ba0 100644 --- a/module/plugins/hoster/MyfastfileCom.py +++ b/module/plugins/hoster/MyfastfileCom.py @@ -9,10 +9,12 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class MyfastfileCom(MultiHoster): __name__ = "MyfastfileCom" __type__ = "hoster" - __version__ = "0.08" + __version__ = "0.10" + __status__ = "testing" __pattern__ = r'http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/dl/' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Myfastfile.com multi-hoster plugin""" __license__ = "GPLv3" @@ -20,14 +22,14 @@ class MyfastfileCom(MultiHoster): def setup(self): - self.chunkLimit = -1 + self.chunk_limit = -1 - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): self.html = self.load('http://myfastfile.com/api.php', - get={'user': self.user, 'pass': self.account.getAccountData(self.user)['password'], + get={'user': self.user, 'pass': self.account.get_info(self.user)['login']['password'], 'link': pyfile.url}) - self.logDebug("JSON data: " + self.html) + self.log_debug("JSON data: " + self.html) self.html = json_loads(self.html) if self.html['status'] != 'ok': diff --git a/module/plugins/hoster/MystoreTo.py b/module/plugins/hoster/MystoreTo.py index 531368134..e4432f491 100644 --- a/module/plugins/hoster/MystoreTo.py +++ b/module/plugins/hoster/MystoreTo.py @@ -11,7 +11,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class MystoreTo(SimpleHoster): __name__ = "MystoreTo" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?mystore\.to/dl/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -27,12 +28,12 @@ class MystoreTo(SimpleHoster): def setup(self): - self.chunkLimit = 1 - self.resumeDownload = True + self.chunk_limit = 1 + self.resume_download = True self.multiDL = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): try: fid = re.search(r'wert="(.+?)"', self.html).group(1) diff --git a/module/plugins/hoster/MyvideoDe.py b/module/plugins/hoster/MyvideoDe.py index 8af4a9a61..9abb0abe9 100644 --- a/module/plugins/hoster/MyvideoDe.py +++ b/module/plugins/hoster/MyvideoDe.py @@ -2,14 +2,15 @@ import re -from module.plugins.Hoster import Hoster -from module.unescape import unescape +from module.plugins.internal.Hoster import Hoster +from module.utils import html_unescape class MyvideoDe(Hoster): __name__ = "MyvideoDe" __type__ = "hoster" - __version__ = "0.90" + __version__ = "0.92" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?myvideo\.de/watch/' @@ -38,7 +39,7 @@ class MyvideoDe(Hoster): def get_file_name(self): file_name_pattern = r'<h1 class=\'globalHd\'>(.*)</h1>' - return unescape(re.search(file_name_pattern, self.html).group(1).replace("/", "") + '.flv') + return html_unescape(re.search(file_name_pattern, self.html).group(1).replace("/", "") + '.flv') def file_exists(self): diff --git a/module/plugins/hoster/NahrajCz.py b/module/plugins/hoster/NahrajCz.py index cf708be09..0d710c9b0 100644 --- a/module/plugins/hoster/NahrajCz.py +++ b/module/plugins/hoster/NahrajCz.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class NahrajCz(DeadHoster): __name__ = "NahrajCz" __type__ = "hoster" - __version__ = "0.21" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?nahraj\.cz/content/download/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/NarodRu.py b/module/plugins/hoster/NarodRu.py index c201ac250..b0d4a4960 100644 --- a/module/plugins/hoster/NarodRu.py +++ b/module/plugins/hoster/NarodRu.py @@ -10,7 +10,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class NarodRu(SimpleHoster): __name__ = "NarodRu" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?narod(\.yandex)?\.ru/(disk|start/\d+\.\w+-narod\.yandex\.ru)/(?P<ID>\d+)/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -32,7 +33,7 @@ class NarodRu(SimpleHoster): LINK_FREE_PATTERN = r'<a class="h-link" rel="yandex_bar" href="(.+?)">' - def handleFree(self, pyfile): + def handle_free(self, pyfile): for _i in xrange(5): self.html = self.load('http://narod.ru/disk/getcapchaxml/?rnd=%d' % int(random.random() * 777)) @@ -40,20 +41,20 @@ class NarodRu(SimpleHoster): if m is None: self.error(_("Captcha")) - post_data = {"action": "sendcapcha"} + post_data = {'action': "sendcapcha"} captcha_url, post_data['key'] = m.groups() - post_data['rep'] = self.decryptCaptcha(captcha_url) + post_data['rep'] = self.captcha.decrypt(captcha_url) - self.html = self.load(pyfile.url, post=post_data, decode=True) + self.html = self.load(pyfile.url, post=post_data) m = re.search(self.LINK_FREE_PATTERN, self.html) if m: self.link = urlparse.urljoin("http://narod.ru", m.group(1)) - self.correctCaptcha() + self.captcha.correct() break elif u'<b class="error-msg"><strong>ÐÑОблОÑÑ?</strong>' in self.html: - self.invalidCaptcha() + self.captcha.invalid() else: self.error(_("Download link")) diff --git a/module/plugins/hoster/NetloadIn.py b/module/plugins/hoster/NetloadIn.py index 82f5c22fb..ff9e75c72 100644 --- a/module/plugins/hoster/NetloadIn.py +++ b/module/plugins/hoster/NetloadIn.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class NetloadIn(DeadHoster): __name__ = "NetloadIn" __type__ = "hoster" - __version__ = "0.50" + __version__ = "0.51" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?netload\.(in|me)/(?P<PATH>datei|index\.php\?id=10&file_id=)(?P<ID>\w+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/NitroflareCom.py b/module/plugins/hoster/NitroflareCom.py index a86d1af24..ad0573960 100644 --- a/module/plugins/hoster/NitroflareCom.py +++ b/module/plugins/hoster/NitroflareCom.py @@ -2,30 +2,29 @@ import re -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster class NitroflareCom(SimpleHoster): __name__ = "NitroflareCom" __type__ = "hoster" - __version__ = "0.13" + __version__ = "0.15" + __status__ = "testing" __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' @@ -33,15 +32,15 @@ class NitroflareCom(SimpleHoster): # ERROR_PATTERN = r'downloading is not possible' - def handleFree(self, pyfile): - # used here to load the cookies which will be required later + def handle_free(self, pyfile): + #: Used here to load the cookies which will be required later self.load(pyfile.url, post={'goToFreePage': ""}) self.load("http://nitroflare.com/ajax/setCookie.php", post={'fileId': self.info['pattern']['ID']}) self.html = self.load("http://nitroflare.com/ajax/freeDownload.php", post={'method': "startTimer", 'fileId': self.info['pattern']['ID']}) - self.checkErrors() + self.check_errors() try: js_file = self.load("http://nitroflare.com/js/downloadFree.js?v=1.0.1") @@ -61,12 +60,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) + return super(NitroflareCom, self).handle_free(pyfile) diff --git a/module/plugins/hoster/NoPremiumPl.py b/module/plugins/hoster/NoPremiumPl.py index c3313c525..9e2a5a93c 100644 --- a/module/plugins/hoster/NoPremiumPl.py +++ b/module/plugins/hoster/NoPremiumPl.py @@ -7,10 +7,12 @@ from module.plugins.internal.MultiHoster import MultiHoster class NoPremiumPl(MultiHoster): __name__ = "NoPremiumPl" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'https?://direct\.nopremium\.pl.+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """NoPremium.pl multi-hoster plugin""" __license__ = "GPLv3" @@ -37,68 +39,68 @@ class NoPremiumPl(MultiHoster): def prepare(self): super(NoPremiumPl, self).prepare() - data = self.account.getAccountData(self.user) + data = self.account.get_data(self.user) self.usr = data['usr'] self.pwd = data['pwd'] - def runFileQuery(self, url, mode=None): + def run_file_query(self, url, mode=None): query = self.API_QUERY.copy() - query["username"] = self.usr - query["password"] = self.pwd - query["url"] = url + query['username'] = self.usr + query['password'] = self.pwd + query['url'] = url if mode == "fileinfo": query['check'] = 2 query['loc'] = 1 - self.logDebug(query) + self.log_debug(query) return self.load(self.API_URL, post=query) - def handleFree(self, pyfile): + def handle_free(self, pyfile): try: - data = self.runFileQuery(pyfile.url, 'fileinfo') + data = self.run_file_query(pyfile.url, 'fileinfo') except Exception: - self.logDebug("runFileQuery error") - self.tempOffline() + self.log_debug("runFileQuery error") + self.temp_offline() try: parsed = json_loads(data) except Exception: - self.logDebug("loads error") - self.tempOffline() + self.log_debug("loads error") + self.temp_offline() - self.logDebug(parsed) + self.log_debug(parsed) if "errno" in parsed.keys(): - if parsed["errno"] in self.ERROR_CODES: - # error code in known - self.fail(self.ERROR_CODES[parsed["errno"]] % self.__name__) + if parsed['errno'] in self.ERROR_CODES: + #: Error code in known + self.fail(self.ERROR_CODES[parsed['errno']] % self.__name__) else: - # error code isn't yet added to plugin + #: Error code isn't yet added to plugin self.fail( - parsed["errstring"] - or _("Unknown error (code: %s)") % parsed["errno"] + parsed['errstring'] + or _("Unknown error (code: %s)") % parsed['errno'] ) if "sdownload" in parsed: - if parsed["sdownload"] == "1": + if parsed['sdownload'] == "1": self.fail( _("Download from %s is possible only using NoPremium.pl website \ - directly") % parsed["hosting"]) + directly") % parsed['hosting']) - pyfile.name = parsed["filename"] - pyfile.size = parsed["filesize"] + pyfile.name = parsed['filename'] + pyfile.size = parsed['filesize'] try: - self.link = self.runFileQuery(pyfile.url, 'filedownload') + self.link = self.run_file_query(pyfile.url, 'filedownload') except Exception: - self.logDebug("runFileQuery error #2") - self.tempOffline() + self.log_debug("runFileQuery error #2") + self.temp_offline() diff --git a/module/plugins/hoster/NosuploadCom.py b/module/plugins/hoster/NosuploadCom.py index 241ee3a29..7de26f3fb 100644 --- a/module/plugins/hoster/NosuploadCom.py +++ b/module/plugins/hoster/NosuploadCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class NosuploadCom(XFSHoster): __name__ = "NosuploadCom" __type__ = "hoster" - __version__ = "0.31" + __version__ = "0.32" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?nosupload\.com/\?d=\w{12}' @@ -23,19 +24,19 @@ class NosuploadCom(XFSHoster): WAIT_PATTERN = r'Please wait.*?>(\d+)</span>' - def getDownloadLink(self): - # stage1: press the "Free Download" button - data = self.getPostParameters() - self.html = self.load(self.pyfile.url, post=data, decode=True) + def get_download_link(self): + #: stage1: press the "Free Download" button + data = self.get_post_parameters() + self.html = self.load(self.pyfile.url, post=data) - # stage2: wait some time and press the "Download File" button - data = self.getPostParameters() + #: stage2: wait some time and press the "Download File" button + data = self.get_post_parameters() wait_time = re.search(self.WAIT_PATTERN, self.html, re.M | re.S).group(1) - self.logDebug("Hoster told us to wait %s seconds" % wait_time) + self.log_debug("Hoster told us to wait %s seconds" % wait_time) self.wait(wait_time) - self.html = self.load(self.pyfile.url, post=data, decode=True) + self.html = self.load(self.pyfile.url, post=data) - # stage3: get the download link + #: stage3: get the download link return re.search(self.LINK_PATTERN, self.html, re.S).group(1) diff --git a/module/plugins/hoster/NovafileCom.py b/module/plugins/hoster/NovafileCom.py index b00f71635..9ae73b1a8 100644 --- a/module/plugins/hoster/NovafileCom.py +++ b/module/plugins/hoster/NovafileCom.py @@ -10,7 +10,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class NovafileCom(XFSHoster): __name__ = "NovafileCom" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?novafile\.com/\w{12}' diff --git a/module/plugins/hoster/NowDownloadSx.py b/module/plugins/hoster/NowDownloadSx.py index a1cf9baf7..876a7bcb5 100644 --- a/module/plugins/hoster/NowDownloadSx.py +++ b/module/plugins/hoster/NowDownloadSx.py @@ -9,7 +9,8 @@ from module.utils import fixup class NowDownloadSx(SimpleHoster): __name__ = "NowDownloadSx" __type__ = "hoster" - __version__ = "0.09" + __version__ = "0.11" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(nowdownload\.[a-zA-Z]{2,}/(dl/|download\.php.+?id=|mobile/(#/files/|.+?id=))|likeupload\.org/)\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -26,18 +27,18 @@ class NowDownloadSx(SimpleHoster): TOKEN_PATTERN = r'"(/api/token\.php\?token=\w+)"' CONTINUE_PATTERN = r'"(/dl2/\w+/\w+)"' WAIT_PATTERN = r'\.countdown\(\{until: \+(\d+),' - LINK_FREE_PATTERN = r'(http://s\d+\.coolcdn\.info/nowdownload/.+?)["\']' + LINK_FREE_PATTERN = r'(http://s\d+(?:\.coolcdn\.info|\.mighycdndelivery\.com)/nowdownload/.+?)["\']' NAME_REPLACEMENTS = [("&#?\w+;", fixup), (r'<.*?>', '')] def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - self.chunkLimit = -1 + self.chunk_limit = -1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): tokenlink = re.search(self.TOKEN_PATTERN, self.html) continuelink = re.search(self.CONTINUE_PATTERN, self.html) if tokenlink is None or continuelink is None: @@ -49,7 +50,7 @@ class NowDownloadSx(SimpleHoster): else: wait = 60 - baseurl = "http://www.nowdownload.at" + baseurl = "http://www.nowdownload.ch" self.html = self.load(baseurl + str(tokenlink.group(1))) self.wait(wait) diff --git a/module/plugins/hoster/NowVideoSx.py b/module/plugins/hoster/NowVideoSx.py index 477379597..c1f369f2a 100644 --- a/module/plugins/hoster/NowVideoSx.py +++ b/module/plugins/hoster/NowVideoSx.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class NowVideoSx(SimpleHoster): __name__ = "NowVideoSx" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?nowvideo\.[a-zA-Z]{2,}/(video/|mobile/(#/videos/|.+?id=))(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -28,11 +29,11 @@ class NowVideoSx(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.html = self.load("http://www.nowvideo.sx/mobile/video.php", get={'id': self.info['pattern']['ID']}) m = re.search(self.LINK_FREE_PATTERN, self.html) diff --git a/module/plugins/hoster/OboomCom.py b/module/plugins/hoster/OboomCom.py index b50e2fb42..8420c6f02 100644 --- a/module/plugins/hoster/OboomCom.py +++ b/module/plugins/hoster/OboomCom.py @@ -6,18 +6,19 @@ import re from module.common.json_layer import json_loads -from module.plugins.Hoster import Hoster -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.internal.Hoster import Hoster +from module.plugins.captcha.ReCaptcha import ReCaptcha class OboomCom(Hoster): __name__ = "OboomCom" __type__ = "hoster" - __version__ = "0.33" + __version__ = "0.36" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?oboom\.com/(?:#(?:id=|/)?)?(?P<ID>\w{8})' - __description__ = """oboom.com hoster plugin""" + __description__ = """Oboom.com hoster plugin""" __license__ = "GPLv3" __authors__ = [("stanley", "stanley.foerster@gmail.com")] @@ -26,120 +27,119 @@ class OboomCom(Hoster): def setup(self): - self.chunkLimit = 1 - self.multiDL = self.resumeDownload = self.premium + self.chunk_limit = 1 + self.multiDL = self.resume_download = self.premium def process(self, pyfile): self.pyfile.url.replace(".com/#id=", ".com/#") self.pyfile.url.replace(".com/#/", ".com/#") self.html = self.load(pyfile.url) - self.getFileId(self.pyfile.url) - self.getSessionToken() - self.getFileInfo(self.sessionToken, self.fileId) - self.pyfile.name = self.fileName - self.pyfile.size = self.fileSize + self.get_file_id(self.pyfile.url) + self.get_session_token() + self.get_fileInfo(self.session_token, self.file_id) + self.pyfile.name = self.file_name + self.pyfile.size = self.file_size if not self.premium: - self.solveCaptcha() - self.getDownloadTicket() - self.download("https://%s/1.0/dlh" % self.downloadDomain, get={"ticket": self.downloadTicket, "http_errors": 0}) + self.solve_captcha() + self.get_download_ticket() + self.download("http://%s/1.0/dlh" % self.download_domain, get={'ticket': self.download_ticket, 'http_errors': 0}) - def loadUrl(self, url, get=None): + def load_url(self, url, get=None): if get is None: - get = dict() - return json_loads(self.load(url, get, decode=True)) + get = {} + return json_loads(self.load(url, get)) - def getFileId(self, url): - self.fileId = re.match(OboomCom.__pattern__, url).group('ID') + def get_file_id(self, url): + self.file_id = re.match(OboomCom.__pattern__, url).group('ID') - def getSessionToken(self): + def get_session_token(self): if self.premium: - accountInfo = self.account.getAccountInfo(self.user, True) + accountInfo = self.account.get_data(self.user, True) if "session" in accountInfo: - self.sessionToken = accountInfo['session'] + self.session_token = accountInfo['session'] else: self.fail(_("Could not retrieve premium session")) else: - apiUrl = "https://www.oboom.com/1.0/guestsession" - result = self.loadUrl(apiUrl) + apiUrl = "http://www.oboom.com/1.0/guestsession" + result = self.load_url(apiUrl) if result[0] == 200: - self.sessionToken = result[1] + self.session_token = result[1] else: self.fail(_("Could not retrieve token for guest session. Error code: %s") % result[0]) - def solveCaptcha(self): + def solve_captcha(self): recaptcha = ReCaptcha(self) for _i in xrange(5): response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) - apiUrl = "https://www.oboom.com/1.0/download/ticket" - params = {"recaptcha_challenge_field": challenge, - "recaptcha_response_field": response, - "download_id": self.fileId, - "token": self.sessionToken} - result = self.loadUrl(apiUrl, params) + apiUrl = "http://www.oboom.com/1.0/download/ticket" + params = {'recaptcha_challenge_field': challenge, + 'recaptcha_response_field': response, + 'download_id': self.file_id, + 'token': self.session_token} + result = self.load_url(apiUrl, params) if result[0] == 200: - self.downloadToken = result[1] - self.downloadAuth = result[2] - self.correctCaptcha() - self.setWait(30) - self.wait() + self.download_token = result[1] + self.download_auth = result[2] + self.captcha.correct() + self.wait(30) break elif result[0] == 400: if result[1] == "incorrect-captcha-sol": - self.invalidCaptcha() + self.captcha.invalid() elif result[1] == "captcha-timeout": - self.invalidCaptcha() + self.captcha.invalid() elif result[1] == "forbidden": self.retry(5, 15 * 60, _("Service unavailable")) elif result[0] == 403: - if result[1] == -1: # another download is running - self.setWait(15 * 60) + if result[1] == -1: #: Another download is running + self.set_wait(15 * 60) else: - self.setWait(result[1], True) + self.set_wait(result[1], True) self.wait() self.retry(5) else: - self.invalidCaptcha() + self.captcha.invalid() self.fail(_("Received invalid captcha 5 times")) - def getFileInfo(self, token, fileId): - apiUrl = "https://api.oboom.com/1.0/info" - params = {"token": token, "items": fileId, "http_errors": 0} + def get_fileInfo(self, token, fileId): + apiUrl = "http://api.oboom.com/1.0/info" + params = {'token': token, 'items': fileId, 'http_errors': 0} - result = self.loadUrl(apiUrl, params) + result = self.load_url(apiUrl, params) if result[0] == 200: item = result[1][0] if item['state'] == "online": - self.fileSize = item['size'] - self.fileName = item['name'] + self.file_size = item['size'] + self.file_name = item['name'] else: self.offline() else: self.fail(_("Could not retrieve file info. Error code %s: %s") % (result[0], result[1])) - def getDownloadTicket(self): - apiUrl = "https://api.oboom.com/1/dl" - params = {"item": self.fileId, "http_errors": 0} + def get_download_ticket(self): + apiUrl = "http://api.oboom.com/1/dl" + params = {'item': self.file_id, 'http_errors': 0} if self.premium: - params['token'] = self.sessionToken + params['token'] = self.session_token else: - params['token'] = self.downloadToken - params['auth'] = self.downloadAuth + params['token'] = self.download_token + params['auth'] = self.download_auth - result = self.loadUrl(apiUrl, params) + result = self.load_url(apiUrl, params) if result[0] == 200: - self.downloadDomain = result[1] - self.downloadTicket = result[2] + self.download_domain = result[1] + self.download_ticket = result[2] elif result[0] == 421: self.retry(wait_time=result[2] + 60, reason=_("Connection limit exceeded")) else: diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py index 4b947c554..c564dc677 100644 --- a/module/plugins/hoster/OneFichierCom.py +++ b/module/plugins/hoster/OneFichierCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class OneFichierCom(SimpleHoster): __name__ = "OneFichierCom" __type__ = "hoster" - __version__ = "0.84" + __version__ = "0.86" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(?:(?P<ID1>\w+)\.)?(?P<HOST>1fichier\.com|alterupload\.com|cjoint\.net|d(es)?fichiers\.com|dl4free\.com|megadl\.fr|mesfichiers\.org|piecejointe\.net|pjointe\.com|tenvoi\.com)(?:/\?(?P<ID2>\w+))?' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -26,7 +27,6 @@ class OneFichierCom(SimpleHoster): COOKIES = [("1fichier.com", "LG", "en")] - DISPOSITION = False #: Remove in 0.4.10 NAME_PATTERN = r'>FileName :</td>\s*<td.*>(?P<N>.+?)<' SIZE_PATTERN = r'>Size :</td>\s*<td.*>(?P<S>[\d.,]+) (?P<U>[\w^_]+)' @@ -37,25 +37,25 @@ class OneFichierCom(SimpleHoster): def setup(self): self.multiDL = self.premium - self.resumeDownload = True + self.resume_download = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): id = self.info['pattern']['ID1'] or self.info['pattern']['ID2'] - url, inputs = self.parseHtmlForm('action="https://1fichier.com/\?%s' % id) + url, inputs = self.parse_html_form('action="https://1fichier.com/\?%s' % id) if not url: self.fail(_("Download link not found")) if "pass" in inputs: - inputs['pass'] = self.getPassword() + inputs['pass'] = self.get_password() inputs['submit'] = "Download" self.download(url, post=inputs) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): self.download(pyfile.url, post={'dl': "Download", 'did': 0}) diff --git a/module/plugins/hoster/OpenloadIo.py b/module/plugins/hoster/OpenloadIo.py index c31b5b997..c46462344 100644 --- a/module/plugins/hoster/OpenloadIo.py +++ b/module/plugins/hoster/OpenloadIo.py @@ -6,21 +6,26 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class OpenloadIo(SimpleHoster): __name__ = "OpenloadIo" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.04" + __status__ = "testing" - __pattern__ = r'https?://(?:www\.)?openload\.io/f/\w{11}' + __pattern__ = r'https?://(?:www\.)?openload\.io/f/[\w_-]{11}' __description__ = """Openload.io hoster plugin""" __license__ = "GPLv3" + __authors__ = [(None, None)] - NAME_PATTERN = r'<span id="filename">(?P<N>.+)</' - SIZE_PATTERN = r'<span class="count">(?P<S>[\d.,]+) (?P<U>[\w^_]+)<' + + 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)" - LINK_FREE_PATTERN = r'id="realdownload"><a href="(https?://[\w\.]+\.openload\.io/dl/.*?)"' + LINK_FREE_PATTERN = r'id="real\w*download"><a href="(https?://[\w\.]+\.openload\.io/dl/.*?)"' + def setup(self): self.multiDL = True - self.chunkLimit = 1 + self.chunk_limit = 1 + getInfo = create_getInfo(OpenloadIo) diff --git a/module/plugins/hoster/OronCom.py b/module/plugins/hoster/OronCom.py index 2e4961704..e1887ce76 100644 --- a/module/plugins/hoster/OronCom.py +++ b/module/plugins/hoster/OronCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class OronCom(DeadHoster): __name__ = "OronCom" __type__ = "hoster" - __version__ = "0.14" + __version__ = "0.15" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?oron\.com/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/OverLoadMe.py b/module/plugins/hoster/OverLoadMe.py index d06baa0f5..0b5bab6a5 100644 --- a/module/plugins/hoster/OverLoadMe.py +++ b/module/plugins/hoster/OverLoadMe.py @@ -5,16 +5,18 @@ import urllib from module.common.json_layer import json_loads from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo -from module.utils import parseFileSize +from module.utils import parseFileSize as parse_size class OverLoadMe(MultiHoster): __name__ = "OverLoadMe" __type__ = "hoster" - __version__ = "0.11" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'https?://.*overload\.me/.+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Over-Load.me multi-hoster plugin""" __license__ = "GPLv3" @@ -22,30 +24,27 @@ class OverLoadMe(MultiHoster): def setup(self): - self.chunkLimit = 5 + self.chunk_limit = 5 - def handlePremium(self, pyfile): - https = "https" if self.getConfig('ssl') else "http" - data = self.account.getAccountData(self.user) - page = self.load(https + "://api.over-load.me/getdownload.php", + def handle_premium(self, pyfile): + data = self.account.get_data(self.user) + page = self.load("https://api.over-load.me/getdownload.php", get={'auth': data['password'], 'link': pyfile.url}) data = json_loads(page) - self.logDebug(data) + self.log_debug(data) if data['error'] == 1: - self.logWarning(data['msg']) - self.tempOffline() + self.log_warning(data['msg']) + self.temp_offline() else: + self.link = data['downloadlink'] if pyfile.name and pyfile.name.endswith('.tmp') and data['filename']: pyfile.name = data['filename'] - pyfile.size = parseFileSize(data['filesize']) - - http_repl = ["http://", "https://"] - self.link = data['downloadlink'].replace(*http_repl if self.getConfig('ssl') else *http_repl[::-1]) + pyfile.size = parse_size(data['filesize']) getInfo = create_getInfo(OverLoadMe) diff --git a/module/plugins/hoster/PandaplaNet.py b/module/plugins/hoster/PandaplaNet.py index ae8406d82..4efe20b5a 100644 --- a/module/plugins/hoster/PandaplaNet.py +++ b/module/plugins/hoster/PandaplaNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class PandaplaNet(DeadHoster): __name__ = "PandaplaNet" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?pandapla\.net/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/PornhostCom.py b/module/plugins/hoster/PornhostCom.py index 0c3b84a9d..8b0a80c7f 100644 --- a/module/plugins/hoster/PornhostCom.py +++ b/module/plugins/hoster/PornhostCom.py @@ -2,13 +2,14 @@ import re -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster class PornhostCom(Hoster): __name__ = "PornhostCom" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?pornhost\.com/(\d+/\d+\.html|\d+)' @@ -26,14 +27,15 @@ class PornhostCom(Hoster): self.download(self.get_file_url()) - # Old interface + #: Old interface def download_html(self): url = self.pyfile.url self.html = self.load(url) def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ if not self.html: self.download_html() @@ -45,7 +47,7 @@ class PornhostCom(Hoster): url = re.search(r'width: 894px; height: 675px">.*?<img src="(.*?)"', self.html) if url is None: url = re.search(r'"http://file\d+\.pornhost\.com/\d+/.*?"', - self.html) # TODO: fix this one since it doesn't match + self.html) #@TODO: fix this one since it doesn't match return url.group(1).strip() @@ -68,7 +70,8 @@ class PornhostCom(Hoster): def file_exists(self): - """ returns True or False + """ + Returns True or False """ if not self.html: self.download_html() diff --git a/module/plugins/hoster/PornhubCom.py b/module/plugins/hoster/PornhubCom.py index 16ce36ea9..5345566a1 100644 --- a/module/plugins/hoster/PornhubCom.py +++ b/module/plugins/hoster/PornhubCom.py @@ -2,13 +2,14 @@ import re -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster class PornhubCom(Hoster): __name__ = "PornhubCom" __type__ = "hoster" - __version__ = "0.50" + __version__ = "0.52" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?pornhub\.com/view_video\.php\?viewkey=\w+' @@ -32,14 +33,15 @@ class PornhubCom(Hoster): def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ if not self.html: self.download_html() url = "http://www.pornhub.com//gateway.php" video_id = self.pyfile.url.split('=')[-1] - # thanks to jD team for this one v + #: Thanks to jD team for this one v post_data = "\x00\x03\x00\x00\x00\x01\x00\x0c\x70\x6c\x61\x79\x65\x72\x43\x6f\x6e\x66\x69\x67\x00\x02\x2f\x31\x00\x00\x00\x44\x0a\x00\x00\x00\x03\x02\x00" post_data += chr(len(video_id)) post_data += video_id @@ -78,7 +80,8 @@ class PornhubCom(Hoster): def file_exists(self): - """ returns True or False + """ + Returns True or False """ if not self.html: self.download_html() diff --git a/module/plugins/hoster/PotloadCom.py b/module/plugins/hoster/PotloadCom.py index 5a41f7d3c..8279412e4 100644 --- a/module/plugins/hoster/PotloadCom.py +++ b/module/plugins/hoster/PotloadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class PotloadCom(DeadHoster): __name__ = "PotloadCom" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?potload\.com/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/PremiumTo.py b/module/plugins/hoster/PremiumTo.py index ab5016673..ec02bb12d 100644 --- a/module/plugins/hoster/PremiumTo.py +++ b/module/plugins/hoster/PremiumTo.py @@ -11,10 +11,12 @@ from module.utils import fs_encode class PremiumTo(MultiHoster): __name__ = "PremiumTo" __type__ = "hoster" - __version__ = "0.22" + __version__ = "0.25" + __status__ = "testing" __pattern__ = r'^unmatchable$' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Premium.to multi-hoster plugin""" __license__ = "GPLv3" @@ -26,8 +28,8 @@ class PremiumTo(MultiHoster): CHECK_TRAFFIC = True - def handlePremium(self, pyfile): - #raise timeout to 2min + def handle_premium(self, pyfile): + #: Raise timeout to 2 min self.download("http://premium.to/api/getfile.php", get={'username': self.account.username, 'password': self.account.password, @@ -35,14 +37,14 @@ class PremiumTo(MultiHoster): disposition=True) - def checkFile(self, rules={}): - if self.checkDownload({'nopremium': "No premium account available"}): + def check_file(self): + if self.check_download({'nopremium': "No premium account available"}): self.retry(60, 5 * 60, "No premium account available") - err = '' - if self.req.http.code == '420': - # Custom error code send - fail - file = fs_encode(self.lastDownload) + err = "" + if self.req.http.code == "420": + #: Custom error code send - fail + file = fs_encode(self.last_download) with open(file, "rb") as f: err = f.read(256).strip() os.remove(file) @@ -50,7 +52,7 @@ class PremiumTo(MultiHoster): if err: self.fail(err) - return super(PremiumTo, self).checkFile(rules) + return super(PremiumTo, self).check_file() getInfo = create_getInfo(PremiumTo) diff --git a/module/plugins/hoster/PremiumizeMe.py b/module/plugins/hoster/PremiumizeMe.py index 3227fb001..d968eccec 100644 --- a/module/plugins/hoster/PremiumizeMe.py +++ b/module/plugins/hoster/PremiumizeMe.py @@ -7,38 +7,40 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class PremiumizeMe(MultiHoster): __name__ = "PremiumizeMe" __type__ = "hoster" - __version__ = "0.16" + __version__ = "0.20" + __status__ = "testing" - __pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.coreReady - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.activate + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Premiumize.me multi-hoster plugin""" __license__ = "GPLv3" __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com")] - def handlePremium(self, pyfile): - # In some cases hostsers do not supply us with a filename at download, so we - # are going to set a fall back filename (e.g. for freakshare or xfileshare) - pyfile.name = pyfile.name.split('/').pop() # Remove everthing before last slash + def handle_premium(self, pyfile): + #: In some cases hostsers do not supply us with a filename at download, so we + #: Are going to set a fall back filename (e.g. for freakshare or xfileshare) + pyfile.name = pyfile.name.split('/').pop() #: Remove everthing before last slash - # Correction for automatic assigned filename: Removing html at end if needed + #: Correction for automatic assigned filename: Removing html at end if needed suffix_to_remove = ["html", "htm", "php", "php3", "asp", "shtm", "shtml", "cfml", "cfm"] temp = pyfile.name.split('.') if temp.pop() in suffix_to_remove: pyfile.name = ".".join(temp) - # Get account data - user, data = self.account.selectAccount() + #: Get account data + user, info = self.account.select() - # Get rewritten link using the premiumize.me api v1 (see https://secure.premiumize.me/?show=api) - data = json_loads(self.load("https://api.premiumize.me/pm-api/v1.php", + #: Get rewritten link using the premiumize.me api v1 (see https://secure.premiumize.me/?show=api) + data = json_loads(self.load("http://api.premiumize.me/pm-api/v1.php", #@TODO: Revert to `https` in 0.4.10 get={'method' : "directdownloadlink", 'params[login]': user, - 'params[pass]' : data['password'], + 'params[pass]' : info['login']['password'], 'params[link]' : pyfile.url})) - # Check status and decide what to do + #: Check status and decide what to do status = data['status'] if status == 200: @@ -52,7 +54,7 @@ class PremiumizeMe(MultiHoster): self.offline() elif status >= 500: - self.tempOffline() + self.temp_offline() else: self.fail(data['statusmessage']) diff --git a/module/plugins/hoster/PromptfileCom.py b/module/plugins/hoster/PromptfileCom.py index 3815a1a24..5f7510123 100644 --- a/module/plugins/hoster/PromptfileCom.py +++ b/module/plugins/hoster/PromptfileCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class PromptfileCom(SimpleHoster): __name__ = "PromptfileCom" __type__ = "hoster" - __version__ = "0.13" + __version__ = "0.14" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?promptfile\.com/' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -18,29 +19,27 @@ class PromptfileCom(SimpleHoster): __authors__ = [("igel", "igelkun@myopera.com")] - INFO_PATTERN = r'<span style=".+?" title=".+?">(?P<N>.*?) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</span>' + INFO_PATTERN = r'<span style=".+?" title=".+?">(?P<N>.*?) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</span>' OFFLINE_PATTERN = r'<span style=".+?" title="File Not Found">File Not Found</span>' - CHASH_PATTERN = r'<input type="hidden" name="chash" value="(.+?)" />' + CHASH_PATTERN = r'<input type="hidden" name="chash" value="(.+?)" />' LINK_FREE_PATTERN = r'<a href=\"(.+)\" target=\"_blank\" class=\"view_dl_link\">Download File</a>' - def handleFree(self, pyfile): - # STAGE 1: get link to continue + def handle_free(self, pyfile): + #: STAGE 1: get link to continue m = re.search(self.CHASH_PATTERN, self.html) if m is None: self.error(_("CHASH_PATTERN not found")) + chash = m.group(1) - self.logDebug("Read chash %s" % chash) - # continue to stage2 - self.html = self.load(pyfile.url, decode=True, post={'chash': chash}) + self.log_debug("Read chash %s" % chash) - # STAGE 2: get the direct link - m = re.search(self.LINK_FREE_PATTERN, self.html) - if m is None: - self.error(_("LINK_FREE_PATTERN not found")) + #: Continue to stage2 + self.html = self.load(pyfile.url, post={'chash': chash}) - self.link = m.group(1) + #: STAGE 2: get the direct link + return super(PromptfileCom, self).handle_free(pyfile) getInfo = create_getInfo(PromptfileCom) diff --git a/module/plugins/hoster/PrzeklejPl.py b/module/plugins/hoster/PrzeklejPl.py index e984d0033..b066444da 100644 --- a/module/plugins/hoster/PrzeklejPl.py +++ b/module/plugins/hoster/PrzeklejPl.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class PrzeklejPl(DeadHoster): __name__ = "PrzeklejPl" __type__ = "hoster" - __version__ = "0.11" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?przeklej\.pl/plik/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/PutdriveCom.py b/module/plugins/hoster/PutdriveCom.py index 7f4b7b6cc..e924fbcfc 100644 --- a/module/plugins/hoster/PutdriveCom.py +++ b/module/plugins/hoster/PutdriveCom.py @@ -6,7 +6,8 @@ from module.plugins.hoster.ZeveraCom import ZeveraCom class PutdriveCom(ZeveraCom): __name__ = "PutdriveCom" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)putdrive\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+' diff --git a/module/plugins/hoster/QuickshareCz.py b/module/plugins/hoster/QuickshareCz.py index 1e0750b88..4311a82aa 100644 --- a/module/plugins/hoster/QuickshareCz.py +++ b/module/plugins/hoster/QuickshareCz.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class QuickshareCz(SimpleHoster): __name__ = "QuickshareCz" __type__ = "hoster" - __version__ = "0.56" + __version__ = "0.57" + __status__ = "testing" __pattern__ = r'http://(?:[^/]*\.)?quickshare\.cz/stahnout-soubor/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -25,39 +26,39 @@ class QuickshareCz(SimpleHoster): def process(self, pyfile): - self.html = self.load(pyfile.url, decode=True) - self.getFileInfo() + self.html = self.load(pyfile.url) + self.get_fileInfo() - # parse js variables + #: Parse js variables self.jsvars = dict((x, y.strip("'")) for x, y in re.findall(r"var (\w+) = ([\d.]+|'.+?')", self.html)) - self.logDebug(self.jsvars) + self.log_debug(self.jsvars) pyfile.name = self.jsvars['ID3'] - # determine download type - free or premium + #: Determine download type - free or premium if self.premium: if 'UU_prihlasen' in self.jsvars: - if self.jsvars['UU_prihlasen'] == '0': - self.logWarning(_("User not logged in")) + if self.jsvars['UU_prihlasen'] == "0": + self.log_warning(_("User not logged in")) self.relogin(self.user) self.retry() elif float(self.jsvars['UU_kredit']) < float(self.jsvars['kredit_odecet']): - self.logWarning(_("Not enough credit left")) + self.log_warning(_("Not enough credit left")) self.premium = False if self.premium: - self.handlePremium(pyfile) + self.handle_premium(pyfile) else: - self.handleFree(pyfile) + self.handle_free(pyfile) - if self.checkDownload({"error": re.compile(r"\AChyba!")}, max_size=100): + if self.check_download({'error': re.compile(r"\AChyba!")}, max_size=100): self.fail(_("File not m or plugin defect")) - def handleFree(self, pyfile): - # get download url + def handle_free(self, pyfile): + #: Get download url download_url = '%s/download.php' % self.jsvars['server'] data = dict((x, self.jsvars[x]) for x in self.jsvars if x in ("ID1", "ID2", "ID3", "ID4")) - self.logDebug("FREE URL1:" + download_url, data) + self.log_debug("FREE URL1:" + download_url, data) self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0) self.load(download_url, post=data) @@ -69,20 +70,20 @@ class QuickshareCz(SimpleHoster): self.fail(_("File not found")) self.link = m.group(1).rstrip() #@TODO: Remove .rstrip() in 0.4.10 - self.logDebug("FREE URL2:" + self.link) + self.log_debug("FREE URL2:" + self.link) - # check errors + #: Check errors m = re.search(r'/chyba/(\d+)', self.link) if m: - if m.group(1) == '1': + if m.group(1) == "1": self.retry(60, 2 * 60, "This IP is already downloading") - elif m.group(1) == '2': + elif m.group(1) == "2": self.retry(60, 60, "No free slots available") else: self.fail(_("Error %d") % m.group(1)) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): download_url = '%s/download_premium.php' % self.jsvars['server'] data = dict((x, self.jsvars[x]) for x in self.jsvars if x in ("ID1", "ID2", "ID4", "ID5")) self.download(download_url, get=data) diff --git a/module/plugins/hoster/RPNetBiz.py b/module/plugins/hoster/RPNetBiz.py index 710faf25c..62e6bee4e 100644 --- a/module/plugins/hoster/RPNetBiz.py +++ b/module/plugins/hoster/RPNetBiz.py @@ -9,10 +9,12 @@ from module.common.json_layer import json_loads class RPNetBiz(MultiHoster): __name__ = "RPNetBiz" __type__ = "hoster" - __version__ = "0.14" + __version__ = "0.17" + __status__ = "testing" __pattern__ = r'https?://.+rpnet\.biz' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """RPNet.biz multi-hoster plugin""" __license__ = "GPLv3" @@ -20,53 +22,51 @@ class RPNetBiz(MultiHoster): def setup(self): - self.chunkLimit = -1 + self.chunk_limit = -1 - def handlePremium(self, pyfile): - user, data = self.account.selectAccount() + def handle_premium(self, pyfile): + user, info = self.account.select() - # Get the download link + #: Get the download link res = self.load("https://premium.rpnet.biz/client_api.php", - get={"username": user, - "password": data['password'], - "action" : "generate", - "links" : pyfile.url}) + get={'username': user, + 'password': info['login']['password'], + 'action' : "generate", + 'links' : pyfile.url}) - self.logDebug("JSON data: %s" % res) - link_status = json_loads(res)['links'][0] # get the first link... since we only queried one + self.log_debug("JSON data: %s" % res) + link_status = json_loads(res)['links'][0] #: Get the first link... since we only queried one - # Check if we only have an id as a HDD link + #: Check if we only have an id as a HDD link if 'id' in link_status: - self.logDebug("Need to wait at least 30 seconds before requery") - self.setWait(30) # wait for 30 seconds - self.wait() - # Lets query the server again asking for the status on the link, - # we need to keep doing this until we reach 100 + self.log_debug("Need to wait at least 30 seconds before requery") + self.wait(30) #: Wait for 30 seconds + #: Lets query the server again asking for the status on the link, + #: We need to keep doing this until we reach 100 max_tries = 30 my_try = 0 while (my_try <= max_tries): - self.logDebug("Try: %d ; Max Tries: %d" % (my_try, max_tries)) + self.log_debug("Try: %d ; Max Tries: %d" % (my_try, max_tries)) res = self.load("https://premium.rpnet.biz/client_api.php", - get={"username": user, - "password": data['password'], - "action": "downloadInformation", - "id": link_status['id']}) - self.logDebug("JSON data hdd query: %s" % res) + get={'username': user, + 'password': info['login']['password'], + 'action' : "downloadInformation", + 'id' : link_status['id']}) + self.log_debug("JSON data hdd query: %s" % res) download_status = json_loads(res)['download'] - if download_status['status'] == '100': + if download_status['status'] == "100": link_status['generated'] = download_status['rpnet_link'] - self.logDebug("Successfully downloaded to rpnet HDD: %s" % link_status['generated']) + self.log_debug("Successfully downloaded to rpnet HDD: %s" % link_status['generated']) break else: - self.logDebug("At %s%% for the file download" % download_status['status']) + self.log_debug("At %s%% for the file download" % download_status['status']) - self.setWait(30) - self.wait() + self.wait(30) my_try += 1 - if my_try > max_tries: # We went over the limit! + if my_try > max_tries: #: We went over the limit! self.fail(_("Waited for about 15 minutes for download to finish but failed")) if 'generated' in link_status: diff --git a/module/plugins/hoster/RapideoPl.py b/module/plugins/hoster/RapideoPl.py index 50804e8cd..e1a0d278f 100644 --- a/module/plugins/hoster/RapideoPl.py +++ b/module/plugins/hoster/RapideoPl.py @@ -7,10 +7,12 @@ from module.plugins.internal.MultiHoster import MultiHoster class RapideoPl(MultiHoster): __name__ = "RapideoPl" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'^unmatchable$' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Rapideo.pl multi-hoster plugin""" __license__ = "GPLv3" @@ -37,68 +39,68 @@ class RapideoPl(MultiHoster): def prepare(self): super(RapideoPl, self).prepare() - data = self.account.getAccountData(self.user) + data = self.account.get_data(self.user) self.usr = data['usr'] self.pwd = data['pwd'] - def runFileQuery(self, url, mode=None): + def run_file_query(self, url, mode=None): query = self.API_QUERY.copy() - query["username"] = self.usr - query["password"] = self.pwd - query["url"] = url + query['username'] = self.usr + query['password'] = self.pwd + query['url'] = url if mode == "fileinfo": query['check'] = 2 query['loc'] = 1 - self.logDebug(query) + self.log_debug(query) return self.load(self.API_URL, post=query) - def handleFree(self, pyfile): + def handle_free(self, pyfile): try: - data = self.runFileQuery(pyfile.url, 'fileinfo') + data = self.run_file_query(pyfile.url, 'fileinfo') except Exception: - self.logDebug("RunFileQuery error") - self.tempOffline() + self.log_debug("RunFileQuery error") + self.temp_offline() try: parsed = json_loads(data) except Exception: - self.logDebug("Loads error") - self.tempOffline() + self.log_debug("Loads error") + self.temp_offline() - self.logDebug(parsed) + self.log_debug(parsed) if "errno" in parsed.keys(): - if parsed["errno"] in self.ERROR_CODES: - # error code in known - self.fail(self.ERROR_CODES[parsed["errno"]] % self.__name__) + if parsed['errno'] in self.ERROR_CODES: + #: Error code in known + self.fail(self.ERROR_CODES[parsed['errno']] % self.__name__) else: - # error code isn't yet added to plugin + #: Error code isn't yet added to plugin self.fail( - parsed["errstring"] - or _("Unknown error (code: %s)") % parsed["errno"] + parsed['errstring'] + or _("Unknown error (code: %s)") % parsed['errno'] ) if "sdownload" in parsed: - if parsed["sdownload"] == "1": + if parsed['sdownload'] == "1": self.fail( _("Download from %s is possible only using Rapideo.pl website \ - directly") % parsed["hosting"]) + directly") % parsed['hosting']) - pyfile.name = parsed["filename"] - pyfile.size = parsed["filesize"] + pyfile.name = parsed['filename'] + pyfile.size = parsed['filesize'] try: - self.link = self.runFileQuery(pyfile.url, 'filedownload') + self.link = self.run_file_query(pyfile.url, 'filedownload') except Exception: - self.logDebug("runFileQuery error #2") - self.tempOffline() + self.log_debug("runFileQuery error #2") + self.temp_offline() diff --git a/module/plugins/hoster/RapidfileshareNet.py b/module/plugins/hoster/RapidfileshareNet.py index 0bbaed57f..5dd3ba82d 100644 --- a/module/plugins/hoster/RapidfileshareNet.py +++ b/module/plugins/hoster/RapidfileshareNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class RapidfileshareNet(XFSHoster): __name__ = "RapidfileshareNet" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?rapidfileshare\.net/\w{12}' diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py index bd6bb8582..636ea1bcc 100644 --- a/module/plugins/hoster/RapidgatorNet.py +++ b/module/plugins/hoster/RapidgatorNet.py @@ -5,16 +5,17 @@ import re from module.common.json_layer import json_loads from module.network.HTTPRequest import BadHeader -from module.plugins.internal.AdsCaptcha import AdsCaptcha -from module.plugins.internal.ReCaptcha import ReCaptcha -from module.plugins.internal.SolveMedia import SolveMedia +from module.plugins.captcha.AdsCaptcha import AdsCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha +from module.plugins.captcha.SolveMedia import SolveMedia from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class RapidgatorNet(SimpleHoster): __name__ = "RapidgatorNet" __type__ = "hoster" - __version__ = "0.34" + __version__ = "0.35" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(rapidgator\.net|rg\.to)/file/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -50,29 +51,29 @@ class RapidgatorNet(SimpleHoster): def setup(self): if self.account: - self.sid = self.account.getAccountInfo(self.user).get('sid', None) + self.sid = self.account.get_data(self.user).get('sid', None) else: self.sid = None if self.sid: self.premium = True - self.resumeDownload = self.multiDL = self.premium - self.chunkLimit = 1 + self.resume_download = self.multiDL = self.premium + self.chunk_limit = 1 def api_response(self, cmd): try: json = self.load('%s/%s' % (self.API_URL, cmd), get={'sid': self.sid, - 'url': self.pyfile.url}, decode=True) - self.logDebug("API:%s" % cmd, json, "SID: %s" % self.sid) + 'url': self.pyfile.url}) + self.log_debug("API:%s" % cmd, json, "SID: %s" % self.sid) json = json_loads(json) status = json['response_status'] msg = json['response_details'] except BadHeader, e: - self.logError("API: %s" % cmd, e, "SID: %s" % self.sid) + self.log_error("API: %s" % cmd, e, "SID: %s" % self.sid) status = e.code msg = e @@ -88,7 +89,7 @@ class RapidgatorNet(SimpleHoster): self.retry(wait_time=60) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): self.api_data = self.api_response('info') self.api_data['md5'] = self.api_data['hash'] @@ -98,22 +99,22 @@ class RapidgatorNet(SimpleHoster): self.link = self.api_response('download')['url'] - def handleFree(self, pyfile): + def handle_free(self, pyfile): jsvars = dict(re.findall(self.JSVARS_PATTERN, self.html)) - self.logDebug(jsvars) + self.log_debug(jsvars) self.req.http.lastURL = pyfile.url self.req.http.c.setopt(pycurl.HTTPHEADER, ["X-Requested-With: XMLHttpRequest"]) url = "http://rapidgator.net%s?fid=%s" % ( jsvars.get('startTimerUrl', '/download/AjaxStartTimer'), jsvars['fid']) - jsvars.update(self.getJsonResponse(url)) + jsvars.update(self.get_json_response(url)) self.wait(jsvars.get('secs', 45), False) url = "http://rapidgator.net%s?sid=%s" % ( jsvars.get('getDownloadUrl', '/download/AjaxGetDownload'), jsvars['sid']) - jsvars.update(self.getJsonResponse(url)) + jsvars.update(self.get_json_response(url)) self.req.http.lastURL = pyfile.url self.req.http.c.setopt(pycurl.HTTPHEADER, ["X-Requested-With:"]) @@ -127,7 +128,7 @@ class RapidgatorNet(SimpleHoster): self.link = m.group(1) break else: - captcha = self.handleCaptcha() + captcha = self.handle_captcha() if not captcha: self.error(_("Captcha pattern not found")) @@ -139,25 +140,25 @@ class RapidgatorNet(SimpleHoster): 'adcopy_response' : response}) if "The verification code is incorrect" in self.html: - self.invalidCaptcha() + self.captcha.invalid() else: - self.correctCaptcha() + self.captcha.correct() else: self.error(_("Download link")) - def handleCaptcha(self): + def handle_captcha(self): for klass in (AdsCaptcha, ReCaptcha, SolveMedia): inst = klass(self) if inst.detect_key(): return inst - def getJsonResponse(self, url): - res = self.load(url, decode=True) + def get_json_response(self, url): + res = self.load(url) if not res.startswith('{'): self.retry() - self.logDebug(url, res) + self.log_debug(url, res) return json_loads(res) diff --git a/module/plugins/hoster/RapiduNet.py b/module/plugins/hoster/RapiduNet.py index da353ec70..267f41f36 100644 --- a/module/plugins/hoster/RapiduNet.py +++ b/module/plugins/hoster/RapiduNet.py @@ -5,14 +5,15 @@ import re import time from module.common.json_layer import json_loads -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class RapiduNet(SimpleHoster): __name__ = "RapiduNet" __type__ = "hoster" - __version__ = "0.09" + __version__ = "0.10" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?rapidu\.net/(?P<ID>\d{10})' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -33,23 +34,22 @@ class RapiduNet(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = self.premium - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.req.http.lastURL = pyfile.url self.req.http.c.setopt(pycurl.HTTPHEADER, ["X-Requested-With: XMLHttpRequest"]) - jsvars = self.getJsonResponse("https://rapidu.net/ajax.php", + jsvars = self.get_json_response("https://rapidu.net/ajax.php", get={'a': "getLoadTimeToDownload"}, - post={'_go': ""}, - decode=True) + post={'_go': ""}) - if str(jsvars['timeToDownload']) is "stop": + if str(jsvars['timeToDownload']) == "stop": t = (24 * 60 * 60) - (int(time.time()) % (24 * 60 * 60)) + time.altzone - self.logInfo("You've reach your daily download transfer") + self.log_info(_("You've reach your daily download transfer")) self.retry(10, 10 if t < 1 else None, _("Try tomorrow again")) #@NOTE: check t in case of not synchronised clock @@ -59,24 +59,23 @@ class RapiduNet(SimpleHoster): recaptcha = ReCaptcha(self) response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) - jsvars = self.getJsonResponse("https://rapidu.net/ajax.php", + jsvars = self.get_json_response("https://rapidu.net/ajax.php", get={'a': "getCheckCaptcha"}, post={'_go' : "", 'captcha1': challenge, 'captcha2': response, - 'fileId' : self.info['pattern']['ID']}, - decode=True) + 'fileId' : self.info['pattern']['ID']}) - if jsvars['message'] == 'success': + if jsvars['message'] == "success": self.link = jsvars['url'] - def getJsonResponse(self, *args, **kwargs): + def get_json_response(self, *args, **kwargs): res = self.load(*args, **kwargs) if not res.startswith('{'): self.retry() - self.logDebug(res) + self.log_debug(res) return json_loads(res) diff --git a/module/plugins/hoster/RarefileNet.py b/module/plugins/hoster/RarefileNet.py index a45e4ed4d..7b19996dc 100644 --- a/module/plugins/hoster/RarefileNet.py +++ b/module/plugins/hoster/RarefileNet.py @@ -8,7 +8,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class RarefileNet(XFSHoster): __name__ = "RarefileNet" __type__ = "hoster" - __version__ = "0.09" + __version__ = "0.10" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?rarefile\.net/\w{12}' diff --git a/module/plugins/hoster/RealdebridCom.py b/module/plugins/hoster/RealdebridCom.py index 4500fcefc..6409701e4 100644 --- a/module/plugins/hoster/RealdebridCom.py +++ b/module/plugins/hoster/RealdebridCom.py @@ -6,16 +6,18 @@ import urllib from module.common.json_layer import json_loads from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo -from module.utils import parseFileSize +from module.utils import parseFileSize as parse_size class RealdebridCom(MultiHoster): __name__ = "RealdebridCom" __type__ = "hoster" - __version__ = "0.67" + __version__ = "0.69" + __status__ = "testing" __pattern__ = r'https?://((?:www\.|s\d+\.)?real-debrid\.com/dl/|[\w^_]\.rdb\.so/d/)[\w^_]+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Real-Debrid.com multi-hoster plugin""" __license__ = "GPLv3" @@ -23,34 +25,29 @@ class RealdebridCom(MultiHoster): def setup(self): - self.chunkLimit = 3 + self.chunk_limit = 3 - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): data = json_loads(self.load("https://real-debrid.com/ajax/unrestrict.php", get={'lang' : "en", 'link' : pyfile.url, - 'password': self.getPassword(), + 'password': self.get_password(), 'time' : int(time.time() * 1000)})) - self.logDebug("Returned Data: %s" % data) + self.log_debug("Returned Data: %s" % data) if data['error'] != 0: if data['message'] == "Your file is unavailable on the hoster.": self.offline() else: - self.logWarning(data['message']) - self.tempOffline() + self.log_warning(data['message']) + self.temp_offline() else: if pyfile.name and pyfile.name.endswith('.tmp') and data['file_name']: pyfile.name = data['file_name'] - pyfile.size = parseFileSize(data['file_size']) + pyfile.size = parse_size(data['file_size']) self.link = data['generated_links'][0][-1] - if self.getConfig('ssl'): - self.link = self.link.replace("http://", "https://") - else: - self.link = self.link.replace("https://", "http://") - getInfo = create_getInfo(RealdebridCom) diff --git a/module/plugins/hoster/RedtubeCom.py b/module/plugins/hoster/RedtubeCom.py index 9051c498a..94a0ead20 100644 --- a/module/plugins/hoster/RedtubeCom.py +++ b/module/plugins/hoster/RedtubeCom.py @@ -2,14 +2,15 @@ import re -from module.plugins.Hoster import Hoster -from module.unescape import unescape +from module.plugins.internal.Hoster import Hoster +from module.utils import html_unescape class RedtubeCom(Hoster): __name__ = "RedtubeCom" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?redtube\.com/\d+' @@ -33,14 +34,13 @@ class RedtubeCom(Hoster): def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ if not self.html: self.download_html() - file_url = unescape(re.search(r'hashlink=(http.*?)"', self.html).group(1)) - - return file_url + return html_unescape(re.search(r'hashlink=(http.*?)"', self.html).group(1)) def get_file_name(self): @@ -51,7 +51,8 @@ class RedtubeCom(Hoster): def file_exists(self): - """ returns True or False + """ + Returns True or False """ if not self.html: self.download_html() diff --git a/module/plugins/hoster/RehostTo.py b/module/plugins/hoster/RehostTo.py index 9c07364ec..6f0645e9f 100644 --- a/module/plugins/hoster/RehostTo.py +++ b/module/plugins/hoster/RehostTo.py @@ -8,20 +8,22 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class RehostTo(MultiHoster): __name__ = "RehostTo" __type__ = "hoster" - __version__ = "0.21" + __version__ = "0.23" + __status__ = "testing" __pattern__ = r'https?://.*rehost\.to\..+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Rehost.com multi-hoster plugin""" __license__ = "GPLv3" __authors__ = [("RaNaN", "RaNaN@pyload.org")] - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): self.download("http://rehost.to/process_download.php", get={'user': "cookie", - 'pass': self.account.getAccountInfo(self.user)['session'], + 'pass': self.account.get_data(self.user)['session'], 'dl' : pyfile.url}, disposition=True) diff --git a/module/plugins/hoster/RemixshareCom.py b/module/plugins/hoster/RemixshareCom.py index d60101aed..295362174 100644 --- a/module/plugins/hoster/RemixshareCom.py +++ b/module/plugins/hoster/RemixshareCom.py @@ -16,7 +16,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class RemixshareCom(SimpleHoster): __name__ = "RemixshareCom" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://remixshare\.com/(download|dl)/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -40,10 +41,10 @@ class RemixshareCom(SimpleHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): b = re.search(self.LINK_PATTERN, self.html) if not b: self.error(_("File url")) diff --git a/module/plugins/hoster/RgHostNet.py b/module/plugins/hoster/RgHostNet.py index 1a45def44..0aa4b7d73 100644 --- a/module/plugins/hoster/RgHostNet.py +++ b/module/plugins/hoster/RgHostNet.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class RgHostNet(SimpleHoster): __name__ = "RgHostNet" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?rghost\.(net|ru)/[\d-]+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] diff --git a/module/plugins/hoster/SafesharingEu.py b/module/plugins/hoster/SafesharingEu.py index 08612e413..e7d53fe75 100644 --- a/module/plugins/hoster/SafesharingEu.py +++ b/module/plugins/hoster/SafesharingEu.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class SafesharingEu(XFSHoster): __name__ = "SafesharingEu" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?safesharing\.eu/\w{12}' diff --git a/module/plugins/hoster/SecureUploadEu.py b/module/plugins/hoster/SecureUploadEu.py index 6bfbce328..df2ac1627 100644 --- a/module/plugins/hoster/SecureUploadEu.py +++ b/module/plugins/hoster/SecureUploadEu.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class SecureUploadEu(XFSHoster): __name__ = "SecureUploadEu" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?secureupload\.eu/\w{12}' diff --git a/module/plugins/hoster/SendspaceCom.py b/module/plugins/hoster/SendspaceCom.py index 0ab20949d..13dd20b7c 100644 --- a/module/plugins/hoster/SendspaceCom.py +++ b/module/plugins/hoster/SendspaceCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class SendspaceCom(SimpleHoster): __name__ = "SendspaceCom" __type__ = "hoster" - __version__ = "0.17" + __version__ = "0.18" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?sendspace\.com/file/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -28,30 +29,30 @@ class SendspaceCom(SimpleHoster): USER_CAPTCHA_PATTERN = r'<td><img src="/captchas/captcha\.php?user=(.+?))"></td>' - def handleFree(self, pyfile): + def handle_free(self, pyfile): params = {} for _i in xrange(3): m = re.search(self.LINK_FREE_PATTERN, self.html) if m: if 'captcha_hash' in params: - self.correctCaptcha() + self.captcha.correct() self.link = m.group(1) break m = re.search(self.CAPTCHA_PATTERN, self.html) if m: if 'captcha_hash' in params: - self.invalidCaptcha() + self.captcha.invalid() captcha_url1 = "http://www.sendspace.com/" + m.group(1) m = re.search(self.USER_CAPTCHA_PATTERN, self.html) captcha_url2 = "http://www.sendspace.com/" + m.group(1) params = {'captcha_hash': m.group(2), 'captcha_submit': 'Verify', - 'captcha_answer': self.decryptCaptcha(captcha_url1) + " " + self.decryptCaptcha(captcha_url2)} + 'captcha_answer': self.captcha.decrypt(captcha_url1) + " " + self.captcha.decrypt(captcha_url2)} else: params = {'download': "Regular Download"} - self.logDebug(params) + self.log_debug(params) self.html = self.load(pyfile.url, post=params) else: self.fail(_("Download link not found")) diff --git a/module/plugins/hoster/Share4WebCom.py b/module/plugins/hoster/Share4WebCom.py index 7a276c1fe..3f128be5e 100644 --- a/module/plugins/hoster/Share4WebCom.py +++ b/module/plugins/hoster/Share4WebCom.py @@ -7,7 +7,8 @@ from module.plugins.internal.SimpleHoster import create_getInfo class Share4WebCom(UnibytesCom): __name__ = "Share4WebCom" __type__ = "hoster" - __version__ = "0.11" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?share4web\.com/get/\w+' diff --git a/module/plugins/hoster/Share76Com.py b/module/plugins/hoster/Share76Com.py index 4a4af1672..863fb0a7e 100644 --- a/module/plugins/hoster/Share76Com.py +++ b/module/plugins/hoster/Share76Com.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class Share76Com(DeadHoster): __name__ = "Share76Com" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?share76\.com/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/ShareFilesCo.py b/module/plugins/hoster/ShareFilesCo.py index d9a71d786..a42ceb91c 100644 --- a/module/plugins/hoster/ShareFilesCo.py +++ b/module/plugins/hoster/ShareFilesCo.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class ShareFilesCo(DeadHoster): __name__ = "ShareFilesCo" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?sharefiles\.co/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/SharebeesCom.py b/module/plugins/hoster/SharebeesCom.py index 9387483cc..c987ac0f9 100644 --- a/module/plugins/hoster/SharebeesCom.py +++ b/module/plugins/hoster/SharebeesCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class SharebeesCom(DeadHoster): __name__ = "SharebeesCom" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?sharebees\.com/\w{12}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py index 33e37cbc7..b5af3ea35 100644 --- a/module/plugins/hoster/ShareonlineBiz.py +++ b/module/plugins/hoster/ShareonlineBiz.py @@ -5,15 +5,16 @@ import time import urllib import urlparse -from module.network.RequestFactory import getURL -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.network.RequestFactory import getURL as get_url +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class ShareonlineBiz(SimpleHoster): __name__ = "ShareonlineBiz" __type__ = "hoster" - __version__ = "0.51" + __version__ = "0.55" + __status__ = "testing" __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)] @@ -36,70 +37,67 @@ class ShareonlineBiz(SimpleHoster): @classmethod - def apiInfo(cls, url): - info = super(ShareonlineBiz, cls).apiInfo(url) + def api_info(cls, url): + info = super(ShareonlineBiz, cls).api_info(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(";") + field = get_url("http://api.share-online.biz/linkcheck.php", + get={'md5' : "1", + 'links': re.match(cls.__pattern__, url).group("ID")}).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 + 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 + elif field[1] in ("DELETED", "NOTFOUND"): + info['status'] = 1 - except IndexError: - pass + except IndexError: + pass return info def setup(self): - self.resumeDownload = self.premium + self.resume_download = self.premium self.multiDL = False - def handleCaptcha(self): + def handle_captcha(self): recaptcha = ReCaptcha(self) for _i in xrange(5): response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) m = re.search(r'var wait=(\d+);', self.html) - self.setWait(int(m.group(1)) if m else 30) + self.set_wait(int(m.group(1)) if m else 30) res = self.load("%s/free/captcha/%d" % (self.pyfile.url, int(time.time() * 1000)), post={'dl_free' : "1", 'recaptcha_challenge_field': challenge, 'recaptcha_response_field' : response}) - if not res == '0': - self.correctCaptcha() + if not res == "0": + self.captcha.correct() return res else: - self.invalidCaptcha() + self.captcha.invalid() else: - self.invalidCaptcha() + self.captcha.invalid() self.fail(_("No valid captcha solution received")) - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.wait(3) self.html = self.load("%s/free/" % pyfile.url, - post={'dl_free': "1", 'choice': "free"}, - decode=True) + post={'dl_free': "1", 'choice': "free"}) - self.checkErrors() + self.check_errors() - res = self.handleCaptcha() + res = self.handle_captcha() self.link = res.decode('base64') if not self.link.startswith("http://"): @@ -108,25 +106,25 @@ class ShareonlineBiz(SimpleHoster): self.wait() - def checkFile(self, rules={}): - check = self.checkDownload({'cookie': re.compile(r'<div id="dl_failure"'), + def check_file(self): + check = self.check_download({'cookie': re.compile(r'<div id="dl_failure"'), 'fail' : re.compile(r"<title>Share-Online")}) if check == "cookie": - self.invalidCaptcha() + self.captcha.invalid() self.retry(5, 60, _("Cookie failure")) elif check == "fail": - self.invalidCaptcha() + self.captcha.invalid() self.retry(5, 5 * 60, _("Download failed")) - return super(ShareonlineBiz, self).checkFile(rules) + return super(ShareonlineBiz, self).check_file() - def handlePremium(self, pyfile): #: should be working better loading (account) api internally - html = self.load("http://api.share-online.biz/account.php", + def handle_premium(self, pyfile): #: Should be working better loading (account) api internally + html = self.load("https://api.share-online.biz/account.php", get={'username': self.user, - 'password': self.account.getAccountData(self.user)['password'], + 'password': self.account.get_info(self.user)['login']['password'], 'act' : "download", 'lid' : self.info['fileid']}) @@ -136,7 +134,7 @@ class ShareonlineBiz(SimpleHoster): key, value = line.split(": ") dlinfo[key.lower()] = value - self.logDebug(dlinfo) + self.log_debug(dlinfo) if not dlinfo['status'] == "online": self.offline() @@ -147,12 +145,12 @@ class ShareonlineBiz(SimpleHoster): self.link = dlinfo['url'] if self.link == "server_under_maintenance": - self.tempOffline() + self.temp_offline() else: self.multiDL = True - def checkErrors(self): + def check_errors(self): m = re.search(r"/failure/(.*?)/1", self.req.lastEffectiveURL) if m is None: self.info.pop('error', None) @@ -161,11 +159,11 @@ class ShareonlineBiz(SimpleHoster): errmsg = m.group(1).lower() try: - self.logError(errmsg, re.search(self.ERROR_PATTERN, self.html).group(1)) + self.log_error(errmsg, re.search(self.ERROR_PATTERN, self.html).group(1)) except Exception: - self.logError("Unknown error occurred", errmsg) + self.log_error(_("Unknown error occurred"), errmsg) - if errmsg is "invalid": + if errmsg == "invalid": self.fail(_("File not available")) elif errmsg in ("freelimit", "size", "proxy"): @@ -174,6 +172,9 @@ class ShareonlineBiz(SimpleHoster): elif errmsg in ("expired", "server"): self.retry(wait_time=600, reason=errmsg) + elif errmsg == "full": + self.retry(10, 600, _("Server is full")) + elif 'slot' in errmsg: self.wantReconnect = True self.retry(24, 3600, errmsg) diff --git a/module/plugins/hoster/ShareplaceCom.py b/module/plugins/hoster/ShareplaceCom.py index babd0d1d4..11aef0c90 100644 --- a/module/plugins/hoster/ShareplaceCom.py +++ b/module/plugins/hoster/ShareplaceCom.py @@ -3,13 +3,14 @@ import re import urllib -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster class ShareplaceCom(Hoster): __name__ = "ShareplaceCom" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.14" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?shareplace\.(com|org)/\?\w+' @@ -30,16 +31,14 @@ class ShareplaceCom(Hoster): self.pyfile.name = self.get_file_name() - wait_time = self.get_waiting_time() - self.setWait(wait_time) - self.wait() + self.wait(self.get_waiting_time()) def get_waiting_time(self): if not self.html: self.download_html() - #var zzipitime = 15; + #: var zzipitime = 15 m = re.search(r'var zzipitime = (\d+);', self.html) if m: sec = int(m.group(1)) @@ -51,11 +50,12 @@ class ShareplaceCom(Hoster): def download_html(self): url = re.sub("shareplace.com\/\?", "shareplace.com//index1.php/?a=", self.pyfile.url) - self.html = self.load(url, decode=True) + self.html = self.load(url) def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ url = re.search(r"var beer = '(.*?)';", self.html) if url: @@ -63,7 +63,7 @@ class ShareplaceCom(Hoster): url = urllib.unquote( url.replace("http://http:/", "").replace("vvvvvvvvv", "").replace("lllllllll", "").replace( "teletubbies", "")) - self.logDebug("URL: %s" % url) + self.log_debug("URL: %s" % url) return url else: self.error(_("Absolute filepath not found")) @@ -77,7 +77,8 @@ class ShareplaceCom(Hoster): def file_exists(self): - """ returns True or False + """ + Returns True or False """ if not self.html: self.download_html() diff --git a/module/plugins/hoster/SharingmatrixCom.py b/module/plugins/hoster/SharingmatrixCom.py index 3958ebbd6..e6d5d4ab8 100644 --- a/module/plugins/hoster/SharingmatrixCom.py +++ b/module/plugins/hoster/SharingmatrixCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class SharingmatrixCom(DeadHoster): __name__ = "SharingmatrixCom" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?sharingmatrix\.com/file/\w+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/ShragleCom.py b/module/plugins/hoster/ShragleCom.py index 689223322..1313ba0e0 100644 --- a/module/plugins/hoster/ShragleCom.py +++ b/module/plugins/hoster/ShragleCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class ShragleCom(DeadHoster): __name__ = "ShragleCom" __type__ = "hoster" - __version__ = "0.22" + __version__ = "0.23" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(cloudnator|shragle)\.com/files/(?P<ID>.+?)/' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/SimplyPremiumCom.py b/module/plugins/hoster/SimplyPremiumCom.py index b3f52bc8c..be1578bfb 100644 --- a/module/plugins/hoster/SimplyPremiumCom.py +++ b/module/plugins/hoster/SimplyPremiumCom.py @@ -3,16 +3,18 @@ import re from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo -from module.plugins.internal.SimpleHoster import secondsToMidnight +from module.plugins.internal.SimpleHoster import seconds_to_midnight class SimplyPremiumCom(MultiHoster): __name__ = "SimplyPremiumCom" __type__ = "hoster" - __version__ = "0.08" + __version__ = "0.10" + __status__ = "testing" __pattern__ = r'https?://.+simply-premium\.com' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Simply-Premium.com multi-hoster plugin""" __license__ = "GPLv3" @@ -20,10 +22,10 @@ class SimplyPremiumCom(MultiHoster): def setup(self): - self.chunkLimit = 16 + self.chunk_limit = 16 - def checkErrors(self): + def check_errors(self): if '<valid>0</valid>' in self.html or ( "You are not allowed to download from this host" in self.html and self.premium): self.account.relogin(self.user) @@ -33,30 +35,30 @@ class SimplyPremiumCom(MultiHoster): self.offline() elif "downloadlimit" in self.html: - self.logWarning(_("Reached maximum connctions")) + self.log_warning(_("Reached maximum connctions")) self.retry(5, 60, _("Reached maximum connctions")) elif "trafficlimit" in self.html: - self.logWarning(_("Reached daily limit for this host")) - self.retry(wait_time=secondsToMidnight(gmt=2), reason="Daily limit for this host reached") + self.log_warning(_("Reached daily limit for this host")) + self.retry(wait_time=seconds_to_midnight(gmt=2), reason="Daily limit for this host reached") elif "hostererror" in self.html: - self.logWarning(_("Hoster temporarily unavailable, waiting 1 minute and retry")) + self.log_warning(_("Hoster temporarily unavailable, waiting 1 minute and retry")) self.retry(5, 60, _("Hoster is temporarily unavailable")) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): for i in xrange(5): self.html = self.load("http://www.simply-premium.com/premium.php", get={'info': "", 'link': self.pyfile.url}) if self.html: - self.logDebug("JSON data: " + self.html) + self.log_debug("JSON data: " + self.html) break else: - self.logInfo(_("Unable to get API data, waiting 1 minute and retry")) + self.log_info(_("Unable to get API data, waiting 1 minute and retry")) self.retry(5, 60, _("Unable to get API data")) - self.checkErrors() + self.check_errors() try: self.pyfile.name = re.search(r'<name>([^<]+)</name>', self.html).group(1) diff --git a/module/plugins/hoster/SimplydebridCom.py b/module/plugins/hoster/SimplydebridCom.py index aae71d983..829609228 100644 --- a/module/plugins/hoster/SimplydebridCom.py +++ b/module/plugins/hoster/SimplydebridCom.py @@ -8,18 +8,20 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo, rep class SimplydebridCom(MultiHoster): __name__ = "SimplydebridCom" __type__ = "hoster" - __version__ = "0.17" + __version__ = "0.20" + __status__ = "testing" __pattern__ = r'http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/sd\.php' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Simply-debrid.com multi-hoster plugin""" __license__ = "GPLv3" __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")] - def handlePremium(self, pyfile): - #fix the links for simply-debrid.com! + def handle_premium(self, pyfile): + #: Fix the links for simply-debrid.com! self.link = replace_patterns(pyfile.url, [("clz.to", "cloudzer.net/file") ("http://share-online", "http://www.share-online") ("ul.to", "uploaded.net/file") @@ -39,11 +41,11 @@ class SimplydebridCom(MultiHoster): self.wait(5) - def checkFile(self, rules={}): - if self.checkDownload({"error": "No address associated with hostname"}): + def check_file(self): + if self.check_download({'error': "No address associated with hostname"}): self.retry(24, 3 * 60, _("Bad file downloaded")) - return super(SimplydebridCom, self).checkFile(rules) + return super(SimplydebridCom, self).check_file() getInfo = create_getInfo(SimplydebridCom) diff --git a/module/plugins/hoster/SizedriveCom.py b/module/plugins/hoster/SizedriveCom.py index 3b9748fb6..8bfe46e86 100644 --- a/module/plugins/hoster/SizedriveCom.py +++ b/module/plugins/hoster/SizedriveCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class SizedriveCom(SimpleHoster): __name__ = "SizedriveCom" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?sizedrive\.com/[rd]/(?P<ID>\w+)' @@ -23,12 +24,12 @@ class SizedriveCom(SimpleHoster): def setup(self): - self.resumeDownload = False + self.resume_download = False self.multiDL = False - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.wait(5) self.html = self.load("http://www.sizedrive.com/getdownload.php", post={'id': self.info['pattern']['ID']}) diff --git a/module/plugins/hoster/SmoozedCom.py b/module/plugins/hoster/SmoozedCom.py index 9ae12f145..33d098a00 100644 --- a/module/plugins/hoster/SmoozedCom.py +++ b/module/plugins/hoster/SmoozedCom.py @@ -7,58 +7,56 @@ from module.plugins.internal.MultiHoster import MultiHoster class SmoozedCom(MultiHoster): __name__ = "SmoozedCom" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.08" + __status__ = "testing" - __pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.coreReady - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.activate + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Smoozed.com hoster plugin""" __license__ = "GPLv3" __authors__ = [("", "")] - def handleFree(self, pyfile): - # In some cases hostsers do not supply us with a filename at download, so we - # are going to set a fall back filename (e.g. for freakshare or xfileshare) - pyfile.name = pyfile.name.split('/').pop() # Remove everthing before last slash + FILE_ERRORS = [("Error", r'{"state":"error"}'), + ("Retry", r'{"state":"retry"}')] - # Correction for automatic assigned filename: Removing html at end if needed + + def handle_free(self, pyfile): + #: In some cases hostsers do not supply us with a filename at download, so we + #: Are going to set a fall back filename (e.g. for freakshare or xfileshare) + pyfile.name = pyfile.name.split('/').pop() #: Remove everthing before last slash + + #: Correction for automatic assigned filename: Removing html at end if needed suffix_to_remove = ["html", "htm", "php", "php3", "asp", "shtm", "shtml", "cfml", "cfm"] temp = pyfile.name.split('.') if temp.pop() in suffix_to_remove: pyfile.name = ".".join(temp) - # Check the link - get_data = {'session_key': self.account.getAccountInfo(self.user)['session'], + #: Check the link + get_data = {'session_key': self.account.get_data(self.user)['session'], 'url' : pyfile.url} data = json_loads(self.load("http://www2.smoozed.com/api/check", get=get_data)) - if data["state"] != "ok": - self.fail(data["message"]) + if data['state'] != "ok": + self.fail(data['message']) - if data["data"].get("state", "ok") != "ok": - if data["data"] == "Offline": + if data['data'].get("state", "ok") != "ok": + if data['data'] == "Offline": self.offline() else: - self.fail(data["data"]["message"]) + self.fail(data['data']['message']) - pyfile.name = data["data"]["name"] - pyfile.size = int(data["data"]["size"]) + pyfile.name = data['data']['name'] + pyfile.size = int(data['data']['size']) - # Start the download + #: Start the download header = self.load("http://www2.smoozed.com/api/download", get=get_data, just_header=True) if not "location" in header: self.fail(_("Unable to initialize download")) else: - self.link = header["location"][-1] if isinstance(header["location"], list) else header["location"] - - - def checkFile(self, rules={}): - if self.checkDownload({'error': '{"state":"error"}', - 'retry': '{"state":"retry"}'}): - self.fail(_("Error response received")) - - return super(SmoozedCom, self).checkFile(rules) + self.link = header['location'][-1] if isinstance(header['location'], list) else header['location'] diff --git a/module/plugins/hoster/SockshareCom.py b/module/plugins/hoster/SockshareCom.py index 44eedf9d4..b45a22b72 100644 --- a/module/plugins/hoster/SockshareCom.py +++ b/module/plugins/hoster/SockshareCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class SockshareCom(DeadHoster): __name__ = "SockshareCom" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?sockshare\.com/(mobile/)?(file|embed)/(?P<ID>\w+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/SolidfilesCom.py b/module/plugins/hoster/SolidfilesCom.py index d359577d6..16e23045b 100644 --- a/module/plugins/hoster/SolidfilesCom.py +++ b/module/plugins/hoster/SolidfilesCom.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Test links: -# http://www.solidfiles.com/d/609cdb4b1b +# http://www.solidfiles.com/d/609cdb4b1b from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class SolidfilesCom(SimpleHoster): __name__ = "SolidfilesCom" __type__ = "hoster" - __version__ = "0.02" + __version__ = "0.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?solidfiles\.com\/d/\w+' @@ -27,7 +28,7 @@ class SolidfilesCom(SimpleHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 + self.chunk_limit = 1 getInfo = create_getInfo(SolidfilesCom) diff --git a/module/plugins/hoster/SoundcloudCom.py b/module/plugins/hoster/SoundcloudCom.py index 8dff4f42a..b189ee1ba 100644 --- a/module/plugins/hoster/SoundcloudCom.py +++ b/module/plugins/hoster/SoundcloudCom.py @@ -9,7 +9,8 @@ from module.common.json_layer import json_loads class SoundcloudCom(SimpleHoster): __name__ = "SoundcloudCom" __type__ = "hoster" - __version__ = "0.11" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?soundcloud\.com/[\w-]+/[\w-]+' __config__ = [("use_premium", "bool" , "Use premium account if available", True ), @@ -24,7 +25,7 @@ class SoundcloudCom(SimpleHoster): OFFLINE_PATTERN = r'<title>"SoundCloud - Hear the worldâs sounds"</title>' - def handleFree(self, pyfile): + def handle_free(self, pyfile): try: song_id = re.search(r'sounds:(\d+)"', self.html).group(1) @@ -37,19 +38,19 @@ class SoundcloudCom(SimpleHoster): except Exception: client_id = "b45b1aa10f1ac2941910a7f0d10f8e28" - # url to retrieve the actual song url + #: Url to retrieve the actual song url streams = json_loads(self.load("https://api.soundcloud.com/tracks/%s/streams" % song_id, get={'client_id': client_id})) regex = re.compile(r'[^\d]') - http_streams = sorted([(key, value) for key, value in streams.iteritems() if key.startswith('http_')], + http_streams = sorted([(key, value) for key, value in streams.items() if key.startswith('http_')], key=lambda t: regex.sub(t[0], ''), reverse=True) - self.logDebug("Streams found: %s" % (http_streams or "None")) + self.log_debug("Streams found: %s" % (http_streams or "None")) if http_streams: - stream_name, self.link = http_streams[0 if self.getConfig('quality') == "Higher" else -1] + stream_name, self.link = http_streams[0 if self.get_config('quality') == "Higher" else -1] pyfile.name += '.' + stream_name.split('_')[1].lower() diff --git a/module/plugins/hoster/SpeedLoadOrg.py b/module/plugins/hoster/SpeedLoadOrg.py index 18f04b611..abba1be79 100644 --- a/module/plugins/hoster/SpeedLoadOrg.py +++ b/module/plugins/hoster/SpeedLoadOrg.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class SpeedLoadOrg(DeadHoster): __name__ = "SpeedLoadOrg" __type__ = "hoster" - __version__ = "1.02" + __version__ = "1.03" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?speedload\.org/(?P<ID>\w+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/SpeedfileCz.py b/module/plugins/hoster/SpeedfileCz.py index cd6d65082..75a55d490 100644 --- a/module/plugins/hoster/SpeedfileCz.py +++ b/module/plugins/hoster/SpeedfileCz.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class SpeedfileCz(DeadHoster): __name__ = "SpeedFileCz" __type__ = "hoster" - __version__ = "0.32" + __version__ = "0.33" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?speedfile\.cz/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/SpeedyshareCom.py b/module/plugins/hoster/SpeedyshareCom.py index 91788b2c8..7d7a60f04 100644 --- a/module/plugins/hoster/SpeedyshareCom.py +++ b/module/plugins/hoster/SpeedyshareCom.py @@ -12,7 +12,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class SpeedyshareCom(SimpleHoster): __name__ = "SpeedyshareCom" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(speedyshare\.com|speedy\.sh)/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -32,10 +33,10 @@ class SpeedyshareCom(SimpleHoster): def setup(self): self.multiDL = False - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: self.link = m.group(1) diff --git a/module/plugins/hoster/StorageTo.py b/module/plugins/hoster/StorageTo.py index feb9f3300..3d0852204 100644 --- a/module/plugins/hoster/StorageTo.py +++ b/module/plugins/hoster/StorageTo.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class StorageTo(DeadHoster): __name__ = "StorageTo" __type__ = "hoster" - __version__ = "0.01" + __version__ = "0.02" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?storage\.to/get/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/StreamCz.py b/module/plugins/hoster/StreamCz.py index 97bed8109..a5578fd96 100644 --- a/module/plugins/hoster/StreamCz.py +++ b/module/plugins/hoster/StreamCz.py @@ -2,18 +2,18 @@ import re -from module.network.RequestFactory import getURL -from module.plugins.Hoster import Hoster +from module.network.RequestFactory import getURL as get_url +from module.plugins.internal.Hoster import Hoster -def getInfo(urls): +def get_info(urls): result = [] for url in urls: - html = getURL(url) + html = get_url(url) if re.search(StreamCz.OFFLINE_PATTERN, html): - # File offline + #: File offline result.append((url, 0, 1, url)) else: result.append((url, 0, 2, url)) @@ -23,7 +23,8 @@ def getInfo(urls): class StreamCz(Hoster): __name__ = "StreamCz" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?stream\.cz/[^/]+/\d+' @@ -39,12 +40,12 @@ class StreamCz(Hoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True def process(self, pyfile): - self.html = self.load(pyfile.url, decode=True) + self.html = self.load(pyfile.url) if re.search(self.OFFLINE_PATTERN, self.html): self.offline() @@ -53,7 +54,7 @@ class StreamCz(Hoster): if m is None: self.error(_("CDN_PATTERN not found")) cdn = m.groupdict() - self.logDebug(cdn) + self.log_debug(cdn) for cdnkey in ("cdnHD", "cdnHQ", "cdnLQ"): if cdnkey in cdn and cdn[cdnkey] > '': cdnid = cdn[cdnkey] @@ -67,5 +68,5 @@ class StreamCz(Hoster): pyfile.name = "%s-%s.%s.mp4" % (m.group(2), m.group(1), cdnkey[-2:]) download_url = "http://cdn-dispatcher.stream.cz/?id=" + cdnid - self.logInfo(_("STREAM: %s") % cdnkey[-2:], download_url) + self.log_info(_("STREAM: %s") % cdnkey[-2:], download_url) self.download(download_url) diff --git a/module/plugins/hoster/StreamcloudEu.py b/module/plugins/hoster/StreamcloudEu.py index 0f8c08ad9..97cde6e92 100644 --- a/module/plugins/hoster/StreamcloudEu.py +++ b/module/plugins/hoster/StreamcloudEu.py @@ -8,7 +8,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class StreamcloudEu(XFSHoster): __name__ = "StreamcloudEu" __type__ = "hoster" - __version__ = "0.10" + __version__ = "0.11" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?streamcloud\.eu/\w{12}' @@ -22,8 +23,8 @@ class StreamcloudEu(XFSHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 - self.resumeDownload = self.premium + self.chunk_limit = 1 + self.resume_download = self.premium getInfo = create_getInfo(StreamcloudEu) diff --git a/module/plugins/hoster/TurbobitNet.py b/module/plugins/hoster/TurbobitNet.py index 254e06c2a..d323a214b 100644 --- a/module/plugins/hoster/TurbobitNet.py +++ b/module/plugins/hoster/TurbobitNet.py @@ -9,20 +9,20 @@ import urllib from Crypto.Cipher import ARC4 -from module.network.RequestFactory import getURL -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp class TurbobitNet(SimpleHoster): __name__ = "TurbobitNet" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.21" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?turbobit\.net/(?:download/free/)?(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] - __description__ = """ Turbobit.net hoster plugin """ + __description__ = """Turbobit.net hoster plugin""" __license__ = "GPLv3" __authors__ = [("zoidberg", "zoidberg@mujmail.cz"), ("prOq", None)] @@ -42,17 +42,16 @@ class TurbobitNet(SimpleHoster): CAPTCHA_PATTERN = r'<img alt="Captcha" src="(.+?)"' - def handleFree(self, pyfile): - self.html = self.load("http://turbobit.net/download/free/%s" % self.info['pattern']['ID'], - decode=True) + def handle_free(self, pyfile): + self.html = self.load("http://turbobit.net/download/free/%s" % self.info['pattern']['ID']) - rtUpdate = self.getRtUpdate() + rtUpdate = self.get_rt_update() - self.solveCaptcha() + self.solve_captcha() self.req.http.c.setopt(pycurl.HTTPHEADER, ["X-Requested-With: XMLHttpRequest"]) - self.html = self.load(self.getDownloadUrl(rtUpdate)) + self.html = self.load(self.get_download_url(rtUpdate)) self.req.http.c.setopt(pycurl.HTTPHEADER, ["X-Requested-With:"]) @@ -61,7 +60,7 @@ class TurbobitNet(SimpleHoster): self.link = m.group(1) - def solveCaptcha(self): + def solve_captcha(self): for _i in xrange(5): m = re.search(self.LIMIT_WAIT_PATTERN, self.html) if m: @@ -69,12 +68,12 @@ class TurbobitNet(SimpleHoster): self.wait(wait_time, wait_time > 60) self.retry() - action, inputs = self.parseHtmlForm("action='#'") + action, inputs = self.parse_html_form("action='#'") if not inputs: self.error(_("Captcha form not found")) - self.logDebug(inputs) + self.log_debug(inputs) - if inputs['captcha_type'] == 'recaptcha': + if inputs['captcha_type'] == "recaptcha": recaptcha = ReCaptcha(self) inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge() else: @@ -82,44 +81,44 @@ class TurbobitNet(SimpleHoster): if m is None: self.error(_("captcha")) captcha_url = m.group(1) - inputs['captcha_response'] = self.decryptCaptcha(captcha_url) + inputs['captcha_response'] = self.captcha.decrypt(captcha_url) - self.logDebug(inputs) + self.log_debug(inputs) self.html = self.load(self.url, post=inputs) if '<div class="captcha-error">Incorrect, try again!<' in self.html: - self.invalidCaptcha() + self.captcha.invalid() else: - self.correctCaptcha() + self.captcha.correct() break else: self.fail(_("Invalid captcha")) - def getRtUpdate(self): - rtUpdate = self.getStorage("rtUpdate") + def get_rt_update(self): + rtUpdate = self.retrieve("rtUpdate") if not rtUpdate: - if self.getStorage("version") != self.__version__ \ - or int(self.getStorage("timestamp", 0)) + 86400000 < timestamp(): - # that's right, we are even using jdownloader updates - rtUpdate = getURL("http://update0.jdownloader.org/pluginstuff/tbupdate.js") + if self.retrieve("version") is not self.__version__ \ + or int(self.retrieve("timestamp", 0)) + 86400000 < timestamp(): + #: that's right, we are even using jdownloader updates + rtUpdate = self.load("http://update0.jdownloader.org/pluginstuff/tbupdate.js") rtUpdate = self.decrypt(rtUpdate.splitlines()[1]) - # but we still need to fix the syntax to work with other engines than rhino + #: But we still need to fix the syntax to work with other engines than rhino rtUpdate = re.sub(r'for each\(var (\w+) in(\[[^\]]+\])\)\{', r'zza=\2;for(var zzi=0;zzi<zza.length;zzi++){\1=zza[zzi];', rtUpdate) rtUpdate = re.sub(r"for\((\w+)=", r"for(var \1=", rtUpdate) - self.setStorage("rtUpdate", rtUpdate) - self.setStorage("timestamp", timestamp()) - self.setStorage("version", self.__version__) + self.store("rtUpdate", rtUpdate) + self.store("timestamp", timestamp()) + self.store("version", self.__version__) else: - self.logError(_("Unable to download, wait for update...")) - self.tempOffline() + self.log_error(_("Unable to download, wait for update...")) + self.temp_offline() return rtUpdate - def getDownloadUrl(self, rtUpdate): + def get_download_url(self, rtUpdate): self.req.http.lastURL = self.url m = re.search("(/\w+/timeout\.js\?\w+=)([^\"\'<>]+)", self.html) @@ -130,7 +129,7 @@ class TurbobitNet(SimpleHoster): fun = self.load(url) - self.setWait(65, False) + self.set_wait(65, False) for b in [1, 3]: self.jscode = "var id = \'%s\';var b = %d;var inn = \'%s\';%sout" % ( @@ -138,16 +137,16 @@ class TurbobitNet(SimpleHoster): try: out = self.js.eval(self.jscode) - self.logDebug("URL", self.js.engine, out) + self.log_debug("URL", self.js.engine, out) if out.startswith('/download/'): return "http://turbobit.net%s" % out.strip() except Exception, e: - self.logError(e) + self.log_error(e) else: if self.retries >= 2: - # retry with updated js - self.delStorage("rtUpdate") + #: Retry with updated js + self.delete("rtUpdate") else: self.retry() @@ -159,7 +158,7 @@ class TurbobitNet(SimpleHoster): return binascii.unhexlify(cipher.encrypt(binascii.unhexlify(data))) - def getLocalTimeString(self): + def get_local_time_string(self): lt = time.localtime() tz = time.altzone if lt.tm_isdst else time.timezone return "%s GMT%+03d%02d" % (time.strftime("%a %b %d %Y %H:%M:%S", lt), -tz // 3600, tz % 3600) diff --git a/module/plugins/hoster/TurbouploadCom.py b/module/plugins/hoster/TurbouploadCom.py index e4b53b818..ffb88d53b 100644 --- a/module/plugins/hoster/TurbouploadCom.py +++ b/module/plugins/hoster/TurbouploadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class TurbouploadCom(DeadHoster): __name__ = "TurbouploadCom" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?turboupload\.com/(\w+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/TusfilesNet.py b/module/plugins/hoster/TusfilesNet.py index 6021a4c30..8fadb41c3 100644 --- a/module/plugins/hoster/TusfilesNet.py +++ b/module/plugins/hoster/TusfilesNet.py @@ -1,13 +1,15 @@ # -*- coding: utf-8 -*- from module.network.HTTPRequest import BadHeader +from module.plugins.internal.Plugin import Retry from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class TusfilesNet(XFSHoster): __name__ = "TusfilesNet" __type__ = "hoster" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?tusfiles\.net/\w{12}' @@ -18,21 +20,20 @@ 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): - self.chunkLimit = -1 + self.chunk_limit = -1 self.multiDL = True - self.resumeDownload = True + self.resume_download = True - def downloadLink(self, link, disposition=True): + def download(self, url, *args, **kwargs): try: - return super(TusfilesNet, self).downloadLink(link, disposition) + return super(TusfilesNet, self).download(url, *args, **kwargs) except BadHeader, e: - if e.code is 503: + if e.code == 503: self.multiDL = False raise Retry("503") diff --git a/module/plugins/hoster/TwoSharedCom.py b/module/plugins/hoster/TwoSharedCom.py index 086228637..1335bafae 100644 --- a/module/plugins/hoster/TwoSharedCom.py +++ b/module/plugins/hoster/TwoSharedCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class TwoSharedCom(SimpleHoster): __name__ = "TwoSharedCom" __type__ = "hoster" - __version__ = "0.13" + __version__ = "0.14" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?2shared\.com/(account/)?(download|get|file|document|photo|video|audio)/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -26,7 +27,7 @@ class TwoSharedCom(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True diff --git a/module/plugins/hoster/UlozTo.py b/module/plugins/hoster/UlozTo.py index b43ff8d92..b402433a4 100644 --- a/module/plugins/hoster/UlozTo.py +++ b/module/plugins/hoster/UlozTo.py @@ -7,15 +7,16 @@ from module.common.json_layer import json_loads from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -def convertDecimalPrefix(m): - # decimal prefixes used in filesize and traffic +def convert_decimal_prefix(m): + #: Decimal prefixes used in filesize and traffic return ("%%.%df" % {'k': 3, 'M': 6, 'G': 9}[m.group(2)] % float(m.group(1))).replace('.', '') class UlozTo(SimpleHoster): __name__ = "UlozTo" __type__ = "hoster" - __version__ = "1.09" + __version__ = "1.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj\.cz|zachowajto\.pl)/(?:live/)?(?P<ID>\w+/[^/?]*)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -31,10 +32,9 @@ class UlozTo(SimpleHoster): OFFLINE_PATTERN = r'<title>404 - Page not found</title>|<h1 class="h1">File (has been deleted|was banned)</h1>' URL_REPLACEMENTS = [(r'(?<=http://)([^/]+)', "www.ulozto.net")] - SIZE_REPLACEMENTS = [(r'([\d.]+)\s([kMG])B', convertDecimalPrefix)] + SIZE_REPLACEMENTS = [(r'([\d.]+)\s([kMG])B', convert_decimal_prefix)] CHECK_TRAFFIC = True - DISPOSITION = False #: Remove in 0.4.10 ADULT_PATTERN = r'<form action="(.+?)" method="post" id="frm-askAgeForm">' PASSWD_PATTERN = r'<div class="passwordProtectedFile">' @@ -43,37 +43,37 @@ class UlozTo(SimpleHoster): def setup(self): - self.chunkLimit = 16 if self.premium else 1 + self.chunk_limit = 16 if self.premium else 1 self.multiDL = True - self.resumeDownload = True + self.resume_download = True - def handleFree(self, pyfile): - action, inputs = self.parseHtmlForm('id="frm-downloadDialog-freeDownloadForm"') + def handle_free(self, pyfile): + action, inputs = self.parse_html_form('id="frm-downloadDialog-freeDownloadForm"') if not action or not inputs: self.error(_("Free download form not found")) - self.logDebug("inputs.keys = " + str(inputs.keys())) - # get and decrypt captcha + self.log_debug("inputs.keys = " + str(inputs.keys())) + #: Get and decrypt captcha if all(key in inputs for key in ("captcha_value", "captcha_id", "captcha_key")): - # Old version - last seen 9.12.2013 - self.logDebug('Using "old" version') + #: Old version - last seen 9.12.2013 + self.log_debug('Using "old" version') - captcha_value = self.decryptCaptcha("http://img.uloz.to/captcha/%s.png" % inputs['captcha_id']) - self.logDebug("CAPTCHA ID: " + inputs['captcha_id'] + ", CAPTCHA VALUE: " + captcha_value) + captcha_value = self.captcha.decrypt("http://img.uloz.to/captcha/%s.png" % inputs['captcha_id']) + self.log_debug("CAPTCHA ID: " + inputs['captcha_id'] + ", CAPTCHA VALUE: " + captcha_value) inputs.update({'captcha_id': inputs['captcha_id'], 'captcha_key': inputs['captcha_key'], 'captcha_value': captcha_value}) elif all(key in inputs for key in ("captcha_value", "timestamp", "salt", "hash")): - # New version - better to get new parameters (like captcha reload) because of image url - since 6.12.2013 - self.logDebug('Using "new" version') + #: New version - better to get new parameters (like captcha reload) because of image url - since 6.12.2013 + self.log_debug('Using "new" version') xapca = self.load("http://www.ulozto.net/reloadXapca.php", get={'rnd': str(int(time.time()))}) - self.logDebug("xapca = " + str(xapca)) + self.log_debug("xapca = " + str(xapca)) data = json_loads(xapca) - captcha_value = self.decryptCaptcha(str(data['image'])) - self.logDebug("CAPTCHA HASH: " + data['hash'], "CAPTCHA SALT: " + str(data['salt']), "CAPTCHA VALUE: " + captcha_value) + captcha_value = self.captcha.decrypt(str(data['image'])) + self.log_debug("CAPTCHA HASH: " + data['hash'], "CAPTCHA SALT: " + str(data['salt']), "CAPTCHA VALUE: " + captcha_value) inputs.update({'timestamp': data['timestamp'], 'salt': data['salt'], 'hash': data['hash'], 'captcha_value': captcha_value}) @@ -83,13 +83,13 @@ class UlozTo(SimpleHoster): self.download("http://www.ulozto.net" + action, post=inputs) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): self.download(pyfile.url, get={'do': "directDownload"}) - def checkErrors(self): + def check_errors(self): if re.search(self.ADULT_PATTERN, self.html): - self.logInfo(_("Adult content confirmation needed")) + self.log_info(_("Adult content confirmation needed")) m = re.search(self.TOKEN_PATTERN, self.html) if m is None: @@ -97,16 +97,16 @@ class UlozTo(SimpleHoster): self.html = self.load(pyfile.url, get={'do': "askAgeForm-submit"}, - post={"agree": "Confirm", "_token_": m.group(1)}) + post={'agree': "Confirm", '_token_': m.group(1)}) if self.PASSWD_PATTERN in self.html: - password = self.getPassword() + password = self.get_password() if password: - self.logInfo(_("Password protected link, trying ") + password) + self.log_info(_("Password protected link, trying ") + password) self.html = self.load(pyfile.url, get={'do': "passwordProtectedForm-submit"}, - post={"password": password, "password_send": 'Send'}) + post={'password': password, 'password_send': 'Send'}) if self.PASSWD_PATTERN in self.html: self.fail(_("Incorrect password")) @@ -116,20 +116,20 @@ class UlozTo(SimpleHoster): if re.search(self.VIPLINK_PATTERN, self.html): self.html = self.load(pyfile.url, get={'disclaimer': "1"}) - return super(UlozTo, self).checkErrors() + return super(UlozTo, self).check_errors() - def checkFile(self, rules={}): - check = self.checkDownload({ - "wrong_captcha": re.compile(r'<ul class="error">\s*<li>Error rewriting the text.</li>'), - "offline" : re.compile(self.OFFLINE_PATTERN), - "passwd" : self.PASSWD_PATTERN, - "server_error" : 'src="http://img.ulozto.cz/error403/vykricnik.jpg"', # paralell dl, server overload etc. - "not_found" : "<title>UloÅŸ.to</title>" + def check_file(self): + check = self.check_download({ + 'wrong_captcha': re.compile(r'<ul class="error">\s*<li>Error rewriting the text.</li>'), + 'offline' : re.compile(self.OFFLINE_PATTERN), + 'passwd' : self.PASSWD_PATTERN, + 'server_error' : 'src="http://img.ulozto.cz/error403/vykricnik.jpg"', #: Paralell dl, server overload etc. + 'not_found' : "<title>UloÅŸ.to</title>" }) if check == "wrong_captcha": - self.invalidCaptcha() + self.captcha.invalid() self.retry(reason=_("Wrong captcha code")) elif check == "offline": @@ -139,7 +139,7 @@ class UlozTo(SimpleHoster): self.fail(_("Wrong password")) elif check == "server_error": - self.logError(_("Server error, try downloading later")) + self.log_error(_("Server error, try downloading later")) self.multiDL = False self.wait(1 * 60 * 60, True) self.retry() @@ -147,7 +147,7 @@ class UlozTo(SimpleHoster): elif check == "not_found": self.fail(_("Server error, file not downloadable")) - return super(UlozTo, self).checkFile(rules) + return super(UlozTo, self).check_file() getInfo = create_getInfo(UlozTo) diff --git a/module/plugins/hoster/UloziskoSk.py b/module/plugins/hoster/UloziskoSk.py index ad809b47c..7cbcb4d40 100644 --- a/module/plugins/hoster/UloziskoSk.py +++ b/module/plugins/hoster/UloziskoSk.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UloziskoSk(SimpleHoster): __name__ = "UloziskoSk" __type__ = "hoster" - __version__ = "0.25" + __version__ = "0.26" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?ulozisko\.sk/.+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -30,17 +31,17 @@ class UloziskoSk(SimpleHoster): def process(self, pyfile): - self.html = self.load(pyfile.url, decode=True) - self.getFileInfo() + self.html = self.load(pyfile.url) + self.get_fileInfo() m = re.search(self.IMG_PATTERN, self.html) if m: self.link = "http://ulozisko.sk" + m.group(1) else: - self.handleFree(pyfile) + self.handle_free(pyfile) - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: self.error(_("LINK_FREE_PATTERN not found")) @@ -51,22 +52,22 @@ class UloziskoSk(SimpleHoster): self.error(_("ID_PATTERN not found")) id = m.group(1) - self.logDebug("URL:" + parsed_url + ' ID:' + id) + self.log_debug("URL:" + parsed_url + ' ID:' + id) m = re.search(self.CAPTCHA_PATTERN, self.html) if m is None: self.error(_("CAPTCHA_PATTERN not found")) captcha_url = urlparse.urljoin("http://www.ulozisko.sk", m.group(1)) - captcha = self.decryptCaptcha(captcha_url, cookies=True) + captcha = self.captcha.decrypt(captcha_url, cookies=True) - self.logDebug("CAPTCHA_URL:" + captcha_url + ' CAPTCHA:' + captcha) + self.log_debug("CAPTCHA_URL:" + captcha_url + ' CAPTCHA:' + captcha) self.download(parsed_url, - post={"antispam": captcha, - "id" : id, - "name" : pyfile.name, - "but" : "++++STIAHNI+S%DABOR++++"}) + post={'antispam': captcha, + 'id' : id, + 'name' : pyfile.name, + 'but' : "++++STIAHNI+S%DABOR++++"}) getInfo = create_getInfo(UloziskoSk) diff --git a/module/plugins/hoster/UnibytesCom.py b/module/plugins/hoster/UnibytesCom.py index d090c8e7d..ac2589f47 100644 --- a/module/plugins/hoster/UnibytesCom.py +++ b/module/plugins/hoster/UnibytesCom.py @@ -10,7 +10,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UnibytesCom(SimpleHoster): __name__ = "UnibytesCom" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.14" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?unibytes\.com/[\w .-]{11}B' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -28,14 +29,14 @@ class UnibytesCom(SimpleHoster): LINK_FREE_PATTERN = r'<a href="(.+?)">Download</a>' - def handleFree(self, pyfile): + def handle_free(self, pyfile): domain = "http://www.%s/" % self.HOSTER_DOMAIN - action, post_data = self.parseHtmlForm('id="startForm"') + action, post_data = self.parse_html_form('id="startForm"') self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0) for _i in xrange(8): - self.logDebug(action, post_data) + self.log_debug(action, post_data) self.html = self.load(urlparse.urljoin(domain, action), post=post_data) m = re.search(r'location:\s*(\S+)', self.req.http.header, re.I) @@ -47,24 +48,24 @@ class UnibytesCom(SimpleHoster): self.wait(10 * 60, True) self.retry() - if post_data['step'] == 'last': + if post_data['step'] == "last": m = re.search(self.LINK_FREE_PATTERN, self.html) if m: self.link = m.group(1) - self.correctCaptcha() + self.captcha.correct() break else: - self.invalidCaptcha() + self.captcha.invalid() last_step = post_data['step'] - action, post_data = self.parseHtmlForm('id="stepForm"') + action, post_data = self.parse_html_form('id="stepForm"') - if last_step == 'timer': + if last_step == "timer": m = re.search(self.WAIT_PATTERN, self.html) self.wait(m.group(1) if m else 60, False) elif last_step in ("captcha", "last"): - post_data['captcha'] = self.decryptCaptcha(urlparse.urljoin(domain, "/captcha.jpg")) + post_data['captcha'] = self.captcha.decrypt(urlparse.urljoin(domain, "/captcha.jpg")) else: self.fail(_("No valid captcha code entered")) diff --git a/module/plugins/hoster/UnrestrictLi.py b/module/plugins/hoster/UnrestrictLi.py index b63796fe0..082ad3e02 100644 --- a/module/plugins/hoster/UnrestrictLi.py +++ b/module/plugins/hoster/UnrestrictLi.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class UnrestrictLi(DeadHoster): __name__ = "UnrestrictLi" __type__ = "hoster" - __version__ = "0.23" + __version__ = "0.24" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(unrestrict|unr)\.li/dl/[\w^_]+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/UpleaCom.py b/module/plugins/hoster/UpleaCom.py index 9d460ef98..db9517f42 100644 --- a/module/plugins/hoster/UpleaCom.py +++ b/module/plugins/hoster/UpleaCom.py @@ -9,7 +9,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class UpleaCom(XFSHoster): __name__ = "UpleaCom" __type__ = "hoster" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?uplea\.com/dl/\w{15}' @@ -19,8 +20,6 @@ class UpleaCom(XFSHoster): ("GammaC0de", None)] - DISPOSITION = False #@TODO: Remove in 0.4.10 - HOSTER_DOMAIN = "uplea.com" SIZE_REPLACEMENTS = [('ko','KB'), ('mo','MB'), ('go','GB'), ('Ko','KB'), ('Mo','MB'), ('Go','GB')] @@ -38,11 +37,11 @@ class UpleaCom(XFSHoster): def setup(self): self.multiDL = False - self.chunkLimit = 1 - self.resumeDownload = True + self.chunk_limit = 1 + self.resume_download = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.STEP_PATTERN, self.html) if m is None: self.error(_("STEP_PATTERN not found")) @@ -51,7 +50,7 @@ class UpleaCom(XFSHoster): m = re.search(self.WAIT_PATTERN, self.html) if m: - self.logDebug(_("Waiting %s seconds") % m.group(1)) + self.log_debug("Waiting %s seconds" % m.group(1)) self.wait(m.group(1), True) self.retry() diff --git a/module/plugins/hoster/UploadStationCom.py b/module/plugins/hoster/UploadStationCom.py index 61226e3da..36b766b7e 100644 --- a/module/plugins/hoster/UploadStationCom.py +++ b/module/plugins/hoster/UploadStationCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class UploadStationCom(DeadHoster): __name__ = "UploadStationCom" __type__ = "hoster" - __version__ = "0.52" + __version__ = "0.53" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?uploadstation\.com/file/(?P<ID>\w+)' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/UploadableCh.py b/module/plugins/hoster/UploadableCh.py index f323a3538..88d79e9ba 100644 --- a/module/plugins/hoster/UploadableCh.py +++ b/module/plugins/hoster/UploadableCh.py @@ -2,14 +2,15 @@ import re -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UploadableCh(SimpleHoster): __name__ = "UploadableCh" __type__ = "hoster" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?uploadable\.ch/file/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -32,46 +33,45 @@ class UploadableCh(SimpleHoster): RECAPTCHA_KEY = "6LdlJuwSAAAAAPJbPIoUhyqOJd7-yrah5Nhim5S3" - def handleFree(self, pyfile): - # Click the "free user" button and wait - a = self.load(pyfile.url, post={'downloadLink': "wait"}, decode=True) - self.logDebug(a) + def handle_free(self, pyfile): + #: Click the "free user" button and wait + a = self.load(pyfile.url, post={'downloadLink': "wait"}) + self.log_debug(a) self.wait(30) - # Make the recaptcha appear and show it the pyload interface - b = self.load(pyfile.url, post={'checkDownload': "check"}, decode=True) - self.logDebug(b) #: Expected output: {"success":"showCaptcha"} + #: Make the recaptcha appear and show it the pyload interface + b = self.load(pyfile.url, post={'checkDownload': "check"}) + self.log_debug(b) #: Expected output: {'success': "showCaptcha"} recaptcha = ReCaptcha(self) response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY) - # Submit the captcha solution + #: Submit the captcha solution self.load("http://www.uploadable.ch/checkReCaptcha.php", post={'recaptcha_challenge_field' : challenge, 'recaptcha_response_field' : response, - 'recaptcha_shortencode_field': self.info['pattern']['ID']}, - decode=True) + 'recaptcha_shortencode_field': self.info['pattern']['ID']}) self.wait(3) - # Get ready for downloading - self.load(pyfile.url, post={'downloadLink': "show"}, decode=True) + #: Get ready for downloading + self.load(pyfile.url, post={'downloadLink': "show"}) self.wait(3) - # Download the file + #: Download the file self.download(pyfile.url, post={'download': "normal"}, disposition=True) - def checkFile(self, rules={}): - if self.checkDownload({'wait': re.compile("Please wait for")}): - self.logInfo("Downloadlimit reached, please wait or reconnect") + def check_file(self): + if self.check_download({'wait': re.compile("Please wait for")}): + self.log_info(_("Downloadlimit reached, please wait or reconnect")) self.wait(60 * 60, True) self.retry() - return super(UploadableCh, self).checkFile(rules) + return super(UploadableCh, self).check_file() getInfo = create_getInfo(UploadableCh) diff --git a/module/plugins/hoster/UploadboxCom.py b/module/plugins/hoster/UploadboxCom.py index cb4f50184..a1053a413 100644 --- a/module/plugins/hoster/UploadboxCom.py +++ b/module/plugins/hoster/UploadboxCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class UploadboxCom(DeadHoster): __name__ = "Uploadbox" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?uploadbox\.com/files/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/UploadedTo.py b/module/plugins/hoster/UploadedTo.py index 16966a23d..c90f2bb0f 100644 --- a/module/plugins/hoster/UploadedTo.py +++ b/module/plugins/hoster/UploadedTo.py @@ -2,16 +2,18 @@ import re import time +import urlparse -from module.network.RequestFactory import getURL -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.network.RequestFactory import getURL as get_url +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UploadedTo(SimpleHoster): __name__ = "UploadedTo" __type__ = "hoster" - __version__ = "0.89" + __version__ = "0.96" + __status__ = "testing" __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)] @@ -21,28 +23,30 @@ class UploadedTo(SimpleHoster): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - DISPOSITION = False - - API_KEY = "lhF2IeeprweDfu9ccWlxXVVypA5nA3EL" + CHECK_TRAFFIC = True URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://uploaded.net/file/\g<ID>')] + API_KEY = "lhF2IeeprweDfu9ccWlxXVVypA5nA3EL" + + OFFLINE_PATTERN = r'>Page not found' TEMP_OFFLINE_PATTERN = r'<title>uploaded\.net - Maintenance' + LINK_FREE_PATTERN = r"url:\s*'(.+?)'" LINK_PREMIUM_PATTERN = r'<div class="tfree".*\s*<form method="post" action="(.+?)"' - WAIT_PATTERN = r'Current waiting period: <span>(\d+)' - DL_LIMIT_ERROR = r'You have reached the max. number of possible free downloads for this hour' + WAIT_PATTERN = r'Current waiting period: <span>(\d+)' + DL_LIMIT_PATTERN = r'You have reached the max. number of possible free downloads for this hour' @classmethod - def apiInfo(cls, url): - info = super(UploadedTo, cls).apiInfo(url) + def api_info(cls, url): + info = super(UploadedTo, cls).api_info(url) for _i in xrange(5): - html = getURL("http://uploaded.net/api/filemultiple", - get={"apikey": cls.API_KEY, 'id_0': re.match(cls.__pattern__, url).group('ID')}, - decode=True) + html = get_url("http://uploaded.net/api/filemultiple", + get={'apikey': cls.API_KEY, + 'id_0': re.match(cls.__pattern__, url).group('ID')}) if html != "can't find request": api = html.split(",", 4) @@ -58,42 +62,14 @@ class UploadedTo(SimpleHoster): def setup(self): - self.multiDL = self.resumeDownload = self.premium - self.chunkLimit = 1 # critical problems with more chunks - - - def checkErrors(self): - if 'var free_enabled = false;' in self.html: - self.logError(_("Free-download capacities exhausted")) - self.retry(24, 5 * 60) - - elif "limit-size" in self.html: - self.fail(_("File too big for free download")) - - elif "limit-slot" in self.html: # Temporary restriction so just wait a bit - self.wait(30 * 60, True) - self.retry() - - elif "limit-parallel" in self.html: - self.fail(_("Cannot download in parallel")) + self.multiDL = self.resume_download = self.premium + self.chunk_limit = 1 #: Critical problems with more chunks - elif "limit-dl" in self.html or self.DL_LIMIT_ERROR in self.html: # limit-dl - self.wait(3 * 60 * 60, True) - self.retry() - elif '"err":"captcha"' in self.html: - self.invalidCaptcha() - - else: - m = re.search(self.WAIT_PATTERN, self.html) - if m: - self.wait(m.group(1)) - - - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.load("http://uploaded.net/language/en", just_header=True) - self.html = self.load("http://uploaded.net/js/download.js", decode=True) + self.html = self.load("http://uploaded.net/js/download.js") recaptcha = ReCaptcha(self) response, challenge = recaptcha.challenge() @@ -102,23 +78,8 @@ class UploadedTo(SimpleHoster): post={'recaptcha_challenge_field': challenge, 'recaptcha_response_field' : response}) - if "type:'download'" in self.html: - self.correctCaptcha() - try: - self.link = re.search("url:'(.+?)'", self.html).group(1) - - except Exception: - pass - - self.checkErrors() - - - def checkFile(self, rules={}): - if self.checkDownload({'limit-dl': self.DL_LIMIT_ERROR}): - self.wait(3 * 60 * 60, True) - self.retry() - - return super(UploadedTo, self).checkFile(rules) + super(UploadedTo, self).handle_free(pyfile) + self.check_errors() getInfo = create_getInfo(UploadedTo) diff --git a/module/plugins/hoster/UploadhereCom.py b/module/plugins/hoster/UploadhereCom.py index bc94e644e..a3c41e824 100644 --- a/module/plugins/hoster/UploadhereCom.py +++ b/module/plugins/hoster/UploadhereCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class UploadhereCom(DeadHoster): __name__ = "UploadhereCom" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?uploadhere\.com/\w{10}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/UploadheroCom.py b/module/plugins/hoster/UploadheroCom.py index 5c74f10eb..2af0f32fc 100644 --- a/module/plugins/hoster/UploadheroCom.py +++ b/module/plugins/hoster/UploadheroCom.py @@ -12,7 +12,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UploadheroCom(SimpleHoster): __name__ = "UploadheroCom" __type__ = "hoster" - __version__ = "0.18" + __version__ = "0.19" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?uploadhero\.com?/dl/\w+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -38,15 +39,15 @@ class UploadheroCom(SimpleHoster): LINK_PREMIUM_PATTERN = r'<a href="(.+?)" id="downloadnow"' - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.CAPTCHA_PATTERN, self.html) if m is None: self.error(_("Captcha not found")) - captcha = self.decryptCaptcha(urlparse.urljoin("http://uploadhero.co", m.group(1))) + captcha = self.captcha.decrypt(urlparse.urljoin("http://uploadhero.co", m.group(1))) self.html = self.load(pyfile.url, - get={"code": captcha}) + get={'code': captcha}) m = re.search(self.LINK_FREE_PATTERN, self.html) if m: @@ -54,7 +55,7 @@ class UploadheroCom(SimpleHoster): self.wait(50) - def checkErrors(self): + def check_errors(self): m = re.search(self.IP_BLOCKED_PATTERN, self.html) if m: self.html = self.load(urlparse.urljoin("http://uploadhero.co", m.group(1))) @@ -64,7 +65,7 @@ class UploadheroCom(SimpleHoster): self.wait(wait_time, True) self.retry() - return super(UploadheroCom, self).checkErrors() + return super(UploadheroCom, self).check_errors() getInfo = create_getInfo(UploadheroCom) diff --git a/module/plugins/hoster/UploadingCom.py b/module/plugins/hoster/UploadingCom.py index c2e0d2873..36f0c766e 100644 --- a/module/plugins/hoster/UploadingCom.py +++ b/module/plugins/hoster/UploadingCom.py @@ -4,13 +4,15 @@ import pycurl import re from module.common.json_layer import json_loads +from module.plugins.internal.Plugin import encode from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp class UploadingCom(SimpleHoster): __name__ = "UploadingCom" __type__ = "hoster" - __version__ = "0.40" + __version__ = "0.43" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?uploading\.com/files/(?:get/)?(?P<ID>\w+)' @@ -21,7 +23,7 @@ class UploadingCom(SimpleHoster): ("zoidberg", "zoidberg@mujmail.cz")] - NAME_PATTERN = r'id="file_title">(?P<N>.+)</' + NAME_PATTERN = r'id="file_title">(?P<N>.+?)</' SIZE_PATTERN = r'size tip_container">(?P<S>[\d.,]+) (?P<U>[\w^_]+)<' OFFLINE_PATTERN = r'(Page|file) not found' @@ -35,16 +37,16 @@ class UploadingCom(SimpleHoster): if not "/get/" in pyfile.url: pyfile.url = pyfile.url.replace("/files", "/files/get") - self.html = self.load(pyfile.url, decode=True) - self.getFileInfo() + self.html = self.load(pyfile.url) + self.get_fileInfo() if self.premium: - self.handlePremium(pyfile) + self.handle_premium(pyfile) else: - self.handleFree(pyfile) + self.handle_free(pyfile) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): postData = {'action': 'get_link', 'code' : self.info['pattern']['ID'], 'pass' : 'undefined'} @@ -57,11 +59,11 @@ class UploadingCom(SimpleHoster): raise Exception("Plugin defect") - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search('<h2>((Daily )?Download Limit)</h2>', self.html) if m: - pyfile.error = m.group(1) - self.logWarning(pyfile.error) + pyfile.error = encode(m.group(1)) + self.log_warning(pyfile.error) self.retry(6, (6 * 60 if m.group(2) else 15) * 60, pyfile.error) ajax_url = "http://uploading.com/files/get/?ajax" @@ -72,7 +74,7 @@ class UploadingCom(SimpleHoster): if 'answer' in res and 'wait_time' in res['answer']: wait_time = int(res['answer']['wait_time']) - self.logInfo(_("Waiting %d seconds") % wait_time) + self.log_info(_("Waiting %d seconds") % wait_time) self.wait(wait_time) else: self.error(_("No AJAX/WAIT")) diff --git a/module/plugins/hoster/UploadkingCom.py b/module/plugins/hoster/UploadkingCom.py index 0d60cef1f..54fe47cc8 100644 --- a/module/plugins/hoster/UploadkingCom.py +++ b/module/plugins/hoster/UploadkingCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class UploadkingCom(DeadHoster): __name__ = "UploadkingCom" __type__ = "hoster" - __version__ = "0.14" + __version__ = "0.15" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?uploadking\.com/\w{10}' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/UpstoreNet.py b/module/plugins/hoster/UpstoreNet.py index 6410a2dce..12c667efb 100644 --- a/module/plugins/hoster/UpstoreNet.py +++ b/module/plugins/hoster/UpstoreNet.py @@ -2,14 +2,15 @@ import re -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class UpstoreNet(SimpleHoster): __name__ = "UpstoreNet" __type__ = "hoster" - __version__ = "0.06" + __version__ = "0.07" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?upstore\.net/' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -27,39 +28,39 @@ class UpstoreNet(SimpleHoster): LINK_FREE_PATTERN = r'<a href="(https?://.*?)" target="_blank"><b>' - def handleFree(self, pyfile): - # STAGE 1: get link to continue + def handle_free(self, pyfile): + #: STAGE 1: get link to continue m = re.search(self.CHASH_PATTERN, self.html) if m is None: self.error(_("CHASH_PATTERN not found")) chash = m.group(1) - self.logDebug("Read hash " + chash) - # continue to stage2 + self.log_debug("Read hash " + chash) + #: Continue to stage2 post_data = {'hash': chash, 'free': 'Slow download'} - self.html = self.load(pyfile.url, post=post_data, decode=True) + self.html = self.load(pyfile.url, post=post_data) - # STAGE 2: solv captcha and wait - # first get the infos we need: recaptcha key and wait time + #: STAGE 2: solv captcha and wait + #: First get the infos we need: recaptcha key and wait time recaptcha = ReCaptcha(self) - # try the captcha 5 times + #: Try the captcha 5 times for i in xrange(5): m = re.search(self.WAIT_PATTERN, self.html) if m is None: self.error(_("Wait pattern not found")) wait_time = int(m.group(1)) - # then, do the waiting + #: then, do the waiting self.wait(wait_time) - # then, handle the captcha + #: then, handle the captcha response, challenge = recaptcha.challenge() post_data.update({'recaptcha_challenge_field': challenge, 'recaptcha_response_field' : response}) - self.html = self.load(pyfile.url, post=post_data, decode=True) + self.html = self.load(pyfile.url, post=post_data) - # STAGE 3: get direct link + #: STAGE 3: get direct link m = re.search(self.LINK_FREE_PATTERN, self.html, re.S) if m: break diff --git a/module/plugins/hoster/UptoboxCom.py b/module/plugins/hoster/UptoboxCom.py index 2c06558e4..d6baa3990 100644 --- a/module/plugins/hoster/UptoboxCom.py +++ b/module/plugins/hoster/UptoboxCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class UptoboxCom(XFSHoster): __name__ = "UptoboxCom" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.21" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(uptobox|uptostream)\.com/\w{12}' @@ -24,8 +25,8 @@ class UptoboxCom(XFSHoster): def setup(self): self.multiDL = True - self.chunkLimit = 1 - self.resumeDownload = True + self.chunk_limit = 1 + self.resume_download = True getInfo = create_getInfo(UptoboxCom) diff --git a/module/plugins/hoster/VeehdCom.py b/module/plugins/hoster/VeehdCom.py index 78da91020..cf206992d 100644 --- a/module/plugins/hoster/VeehdCom.py +++ b/module/plugins/hoster/VeehdCom.py @@ -2,13 +2,14 @@ import re -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster class VeehdCom(Hoster): __name__ = "VeehdCom" __type__ = "hoster" - __version__ = "0.23" + __version__ = "0.25" + __status__ = "testing" __pattern__ = r'http://veehd\.com/video/\d+_\S+' __config__ = [("filename_spaces", "bool", "Allow spaces in filename", False), @@ -35,7 +36,7 @@ class VeehdCom(Hoster): def download_html(self): url = self.pyfile.url - self.logDebug("Requesting page: %s" % url) + self.log_debug("Requesting page: %s" % url) self.html = self.load(url) @@ -58,17 +59,18 @@ class VeehdCom(Hoster): name = m.group(1) - # replace unwanted characters in filename - if self.getConfig('filename_spaces'): + #: Replace unwanted characters in filename + if self.get_config('filename_spaces'): pattern = '[^\w ]+' else: pattern = '[^\w.]+' - return re.sub(pattern, self.getConfig('replacement_char'), name) + '.avi' + return re.sub(pattern, self.get_config('replacement_char'), name) + '.avi' def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ if not self.html: self.download_html() diff --git a/module/plugins/hoster/VeohCom.py b/module/plugins/hoster/VeohCom.py index 57b24623b..7d46ee335 100644 --- a/module/plugins/hoster/VeohCom.py +++ b/module/plugins/hoster/VeohCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class VeohCom(SimpleHoster): __name__ = "VeohCom" __type__ = "hoster" - __version__ = "0.22" + __version__ = "0.23" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?veoh\.com/(tv/)?(watch|videos)/(?P<ID>v\w+)' __config__ = [("use_premium", "bool" , "Use premium account if available", True ), @@ -28,13 +29,13 @@ class VeohCom(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - self.chunkLimit = -1 + self.chunk_limit = -1 - def handleFree(self, pyfile): - quality = self.getConfig('quality') + def handle_free(self, pyfile): + quality = self.get_config('quality') if quality == "Auto": quality = ("High", "Low") @@ -46,7 +47,7 @@ class VeohCom(SimpleHoster): self.link = m.group(1).replace("\\", "") return else: - self.logInfo(_("No %s quality video found") % q.upper()) + self.log_info(_("No %s quality video found") % q.upper()) else: self.fail(_("No video found!")) diff --git a/module/plugins/hoster/VidPlayNet.py b/module/plugins/hoster/VidPlayNet.py index f1a32a897..f9df18c85 100644 --- a/module/plugins/hoster/VidPlayNet.py +++ b/module/plugins/hoster/VidPlayNet.py @@ -9,7 +9,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class VidPlayNet(XFSHoster): __name__ = "VidPlayNet" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.05" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?vidplay\.net/\w{12}' diff --git a/module/plugins/hoster/VimeoCom.py b/module/plugins/hoster/VimeoCom.py index a5196cb92..d47677c42 100644 --- a/module/plugins/hoster/VimeoCom.py +++ b/module/plugins/hoster/VimeoCom.py @@ -8,7 +8,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class VimeoCom(SimpleHoster): __name__ = "VimeoCom" __type__ = "hoster" - __version__ = "0.04" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(player\.)?vimeo\.com/(video/)?(?P<ID>\d+)' __config__ = [("use_premium", "bool" , "Use premium account if available" , True ), @@ -20,7 +21,7 @@ class VimeoCom(SimpleHoster): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - NAME_PATTERN = r'<title>(?P<N>.+) on Vimeo<' + NAME_PATTERN = r'<title>(?P<N>.+?) on Vimeo<' OFFLINE_PATTERN = r'class="exception_header"' TEMP_OFFLINE_PATTERN = r'Please try again in a few minutes.<' @@ -30,16 +31,16 @@ class VimeoCom(SimpleHoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True - self.chunkLimit = -1 + self.chunk_limit = -1 - def handleFree(self, pyfile): - password = self.getPassword() + def handle_free(self, pyfile): + password = self.get_password() if self.js and 'class="btn iconify_down_b"' in self.html: - html = self.js.eval(self.load(pyfile.url, get={'action': "download", 'password': password}, decode=True)) + html = self.js.eval(self.load(pyfile.url, get={'action': "download", 'password': password})) pattern = r'href="(?P<URL>http://vimeo\.com.+?)".*?\>(?P<QL>.+?) ' else: html = self.load("https://player.vimeo.com/video/" + self.info['pattern']['ID'], get={'password': password}) @@ -47,14 +48,14 @@ class VimeoCom(SimpleHoster): link = dict((l.group('QL').lower(), l.group('URL')) for l in re.finditer(pattern, html)) - if self.getConfig('original'): + if self.get_config('original'): if "original" in link: self.link = link[q] return else: - self.logInfo(_("Original file not downloadable")) + self.log_info(_("Original file not downloadable")) - quality = self.getConfig('quality') + quality = self.get_config('quality') if quality == "Highest": qlevel = ("hd", "sd", "mobile") elif quality == "Lowest": @@ -67,7 +68,7 @@ class VimeoCom(SimpleHoster): self.link = link[q] return else: - self.logInfo(_("No %s quality video found") % q.upper()) + self.log_info(_("No %s quality video found") % q.upper()) else: self.fail(_("No video found!")) diff --git a/module/plugins/hoster/Vipleech4UCom.py b/module/plugins/hoster/Vipleech4UCom.py index 5668e0fad..8eac61341 100644 --- a/module/plugins/hoster/Vipleech4UCom.py +++ b/module/plugins/hoster/Vipleech4UCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class Vipleech4UCom(DeadHoster): __name__ = "Vipleech4UCom" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.21" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?vipleech4u\.com/manager\.php' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/VkCom.py b/module/plugins/hoster/VkCom.py new file mode 100644 index 000000000..d0b0b780e --- /dev/null +++ b/module/plugins/hoster/VkCom.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# +# Test links: +# http://vk.com/video_ext.php?oid=166335015&id=162608895&hash=b55affa83774504b&hd=1 + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class VkCom(SimpleHoster): + __name__ = "VkCom" + __type__ = "hoster" + __version__ = "0.02" + __status__ = "testing" + + __pattern__ = r"https?://(?:www\.)?vk\.com/video_ext\.php/\?.+" + __config__ = [("quality", "Low;High;Auto", "Quality", "Auto")] + + __description__ = """Vk.com hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + NAME_PATTERN = r'"md_title":"(?P<N>.+?)"' + OFFLINE_PATTERN = r'<div id="video_ext_msg">' + + LINK_FREE_PATTERN = r'url\d+":"(.+?)"' + + + def handle_free(self, pyfile): + self.link = re.findall(self.LINK_FREE_PATTERN, self.html)[0 if self.get_config('quality') == "Low" else -1] + + +getInfo = create_getInfo(VkCom) diff --git a/module/plugins/hoster/WarserverCz.py b/module/plugins/hoster/WarserverCz.py index 6cb94e57e..a356dccdd 100644 --- a/module/plugins/hoster/WarserverCz.py +++ b/module/plugins/hoster/WarserverCz.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class WarserverCz(DeadHoster): __name__ = "WarserverCz" __type__ = "hoster" - __version__ = "0.13" + __version__ = "0.14" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?warserver\.cz/stahnout/\d+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/WebshareCz.py b/module/plugins/hoster/WebshareCz.py index ae670c8d4..0a89363f8 100644 --- a/module/plugins/hoster/WebshareCz.py +++ b/module/plugins/hoster/WebshareCz.py @@ -2,61 +2,59 @@ import re -from module.network.RequestFactory import getURL +from module.network.RequestFactory import getURL as get_url from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class WebshareCz(SimpleHoster): __name__ = "WebshareCz" __type__ = "hoster" - __version__ = "0.16" + __version__ = "0.19" + __status__ = "testing" - __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 api_info(cls, url): + info = super(WebshareCz, cls).api_info(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 = get_url("https://webshare.cz/api/file_info/", + post={'ident': info['pattern']['ID'], 'wst': ""}) - 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 "" + def handle_free(self, pyfile): + wst = self.account.get_data(self.user).get('wst', None) if self.account else None - api_data = getURL('https://webshare.cz/api/file_link/', - post={'ident': self.info['pattern']['ID'], 'wst': wst}, - decode=True) + api_data = get_url("https://webshare.cz/api/file_link/", + post={'ident': self.info['pattern']['ID'], 'wst': wst}) - self.logDebug("API data: " + api_data) + self.log_debug("API data: " + api_data) m = re.search('<link>(.+)</link>', api_data) if m: self.link = m.group(1) - def handlePremium(self, pyfile): - return self.handleFree(pyfile) + def handle_premium(self, pyfile): + return self.handle_free(pyfile) getInfo = create_getInfo(WebshareCz) diff --git a/module/plugins/hoster/WrzucTo.py b/module/plugins/hoster/WrzucTo.py index f11d03ea8..4c3b47b37 100644 --- a/module/plugins/hoster/WrzucTo.py +++ b/module/plugins/hoster/WrzucTo.py @@ -9,7 +9,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class WrzucTo(SimpleHoster): __name__ = "WrzucTo" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?wrzuc\.to/(\w+(\.wt|\.html)|(\w+/?linki/\w+))' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -29,17 +30,17 @@ class WrzucTo(SimpleHoster): self.multiDL = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): data = dict(re.findall(r'(md5|file): "(.*?)"', self.html)) if len(data) != 2: self.error(_("No file ID")) self.req.http.c.setopt(pycurl.HTTPHEADER, ["X-Requested-With: XMLHttpRequest"]) self.req.http.lastURL = pyfile.url - self.load("http://www.wrzuc.to/ajax/server/prepair", post={"md5": data['md5']}) + self.load("http://www.wrzuc.to/ajax/server/prepair", post={'md5': data['md5']}) self.req.http.lastURL = pyfile.url - self.html = self.load("http://www.wrzuc.to/ajax/server/download_link", post={"file": data['file']}) + self.html = self.load("http://www.wrzuc.to/ajax/server/download_link", post={'file': data['file']}) data.update(re.findall(r'"(download_link|server_id)":"(.*?)"', self.html)) if len(data) != 4: diff --git a/module/plugins/hoster/WuploadCom.py b/module/plugins/hoster/WuploadCom.py index 73c008ae8..028e557e9 100644 --- a/module/plugins/hoster/WuploadCom.py +++ b/module/plugins/hoster/WuploadCom.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class WuploadCom(DeadHoster): __name__ = "WuploadCom" __type__ = "hoster" - __version__ = "0.23" + __version__ = "0.24" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?wupload\..+?/file/((\w+/)?\d+)(/.*)?' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/X7To.py b/module/plugins/hoster/X7To.py index 8e2dd3a53..285499807 100644 --- a/module/plugins/hoster/X7To.py +++ b/module/plugins/hoster/X7To.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class X7To(DeadHoster): __name__ = "X7To" __type__ = "hoster" - __version__ = "0.41" + __version__ = "0.42" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?x7\.to/' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py index 169fbc8d3..8ede709de 100644 --- a/module/plugins/hoster/XFileSharingPro.py +++ b/module/plugins/hoster/XFileSharingPro.py @@ -8,7 +8,8 @@ from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo class XFileSharingPro(XFSHoster): __name__ = "XFileSharingPro" __type__ = "hoster" - __version__ = "0.46" + __version__ = "0.53" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?(?:\w+\.)*?(?P<DOMAIN>(?:[\d.]+|[\w\-^_]{3,}(?:\.[a-zA-Z]{2,}){1,2})(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)' @@ -20,40 +21,54 @@ class XFileSharingPro(XFSHoster): URL_REPLACEMENTS = [("/embed-", "/")] - 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 _log(self, level, plugintype, pluginname, messages): + return super(XFileSharingPro, self)._log(level, + plugintype, + "%s: %s" % (pluginname, self.HOSTER_NAME), + messages) def init(self): - super(XFileSharingPro, self).init() - - self.__pattern__ = self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] + self.__pattern__ = self.pyload.pluginManager.hosterPlugins[self.__name__]['pattern'] 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 != '.') - - account = self.core.accountManager.getAccountPlugin(self.HOSTER_NAME) + self.HOSTER_NAME = "".join(part.capitalize() for part in re.split(r'(\.|\d+|\-)', self.HOSTER_DOMAIN) if part != '.') - if account and account.canUse(): - self.account = account - elif self.account: - self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN + def _setup(self): + account_name = self.__name__ if self.account.HOSTER_DOMAIN is None else self.HOSTER_NAME + self.chunk_limit = 1 + self.multiDL = True + if self.account: + self.req = self.pyload.requestFactory.getRequest(accountname, self.user) + self.premium = self.account.is_premium(self.user) + self.resume_download = self.premium else: - return + self.req = self.pyload.requestFactory.getRequest(account_name) + self.premium = False + self.resume_download = False + + + def load_account(self): + if self.req: + self.req.close() + + if not self.account: + self.account = self.pyload.accountManager.getAccountPlugin(self.HOSTER_NAME) + + if not self.account: + self.account = self.pyload.accountManager.getAccountPlugin(self.__name__) - self.user, data = self.account.selectAccount() - self.req = self.account.getAccountRequest(self.user) - self.premium = self.account.isPremium(self.user) + if self.account: + if not self.account.HOSTER_DOMAIN: + self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN + if not self.user: + self.user = self.account.select()[0] - def setup(self): - self.chunkLimit = 1 - self.resumeDownload = self.premium - self.multiDL = True + if not self.user or not self.account.is_logged(self.user, True): + self.account = False getInfo = create_getInfo(XFileSharingPro) diff --git a/module/plugins/hoster/XHamsterCom.py b/module/plugins/hoster/XHamsterCom.py index a1711cb0e..8df1a441f 100644 --- a/module/plugins/hoster/XHamsterCom.py +++ b/module/plugins/hoster/XHamsterCom.py @@ -4,7 +4,7 @@ import re import urllib from module.common.json_layer import json_loads -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster def clean_json(json_expr): @@ -18,7 +18,8 @@ def clean_json(json_expr): class XHamsterCom(Hoster): __name__ = "XHamsterCom" __type__ = "hoster" - __version__ = "0.12" + __version__ = "0.14" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?xhamster\.com/movies/.+' __config__ = [("type", ".mp4;.flv", "Preferred type", ".mp4")] @@ -34,8 +35,8 @@ class XHamsterCom(Hoster): if not self.file_exists(): self.offline() - if self.getConfig('type'): - self.desired_fmt = self.getConfig('type') + if self.get_config('type'): + self.desired_fmt = self.get_config('type') pyfile.name = self.get_file_name() + self.desired_fmt self.download(self.get_file_url()) @@ -47,7 +48,8 @@ class XHamsterCom(Hoster): def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ if not self.html: self.download_html() @@ -79,19 +81,19 @@ class XHamsterCom(Hoster): self.error(_("file_url not found")) file_url = file_url.group(1) long_url = srv_url + file_url - self.logDebug("long_url = " + long_url) + self.log_debug("long_url = " + long_url) else: if flashvars['file']: file_url = urllib.unquote(flashvars['file']) else: self.error(_("file_url not found")) - if url_mode == '3': + if url_mode == "3": long_url = file_url - self.logDebug("long_url = " + long_url) + self.log_debug("long_url = " + long_url) else: long_url = srv_url + "key=" + file_url - self.logDebug("long_url = " + long_url) + self.log_debug("long_url = " + long_url) return long_url @@ -118,7 +120,8 @@ class XHamsterCom(Hoster): def file_exists(self): - """ returns True or False + """ + Returns True or False """ if not self.html: self.download_html() diff --git a/module/plugins/hoster/XVideosCom.py b/module/plugins/hoster/XVideosCom.py index a8f291824..d74f35616 100644 --- a/module/plugins/hoster/XVideosCom.py +++ b/module/plugins/hoster/XVideosCom.py @@ -3,13 +3,14 @@ import re import urllib -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster class XVideosCom(Hoster): __name__ = "XVideos.com" __type__ = "hoster" - __version__ = "0.10" + __version__ = "0.12" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?xvideos\.com/video(\d+)' diff --git a/module/plugins/hoster/XdadevelopersCom.py b/module/plugins/hoster/XdadevelopersCom.py index 45d1e92cb..12f27c880 100644 --- a/module/plugins/hoster/XdadevelopersCom.py +++ b/module/plugins/hoster/XdadevelopersCom.py @@ -11,7 +11,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class XdadevelopersCom(SimpleHoster): __name__ = "XdadevelopersCom" __type__ = "hoster" - __version__ = "0.03" + __version__ = "0.04" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)?forum\.xda-developers\.com/devdb/project/dl/\?id=\d+' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -28,11 +29,11 @@ class XdadevelopersCom(SimpleHoster): def setup(self): self.multiDL = True - self.resumeDownload = True - self.chunkLimit = 1 + self.resume_download = True + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): self.link = pyfile.url + "&task=get" #@TODO: Revert to `get={'task': "get"}` in 0.4.10 diff --git a/module/plugins/hoster/Xdcc.py b/module/plugins/hoster/Xdcc.py index d167e4cab..aba66ee94 100644 --- a/module/plugins/hoster/Xdcc.py +++ b/module/plugins/hoster/Xdcc.py @@ -8,14 +8,16 @@ import time from select import select -from module.plugins.Hoster import Hoster -from module.utils import save_join +from module.plugins.internal.Hoster import Hoster +# from module.utils import decode +from module.utils import save_join as fs_join class Xdcc(Hoster): __name__ = "Xdcc" __type__ = "hoster" - __version__ = "0.32" + __version__ = "0.34" + __status__ = "testing" __config__ = [("nick", "str", "Nickname", "pyload"), ("ident", "str", "Ident", "pyloadident"), @@ -27,20 +29,19 @@ class Xdcc(Hoster): def setup(self): - self.debug = 0 # 0,1,2 self.timeout = 30 self.multiDL = False def process(self, pyfile): - # change request type - self.req = pyfile.m.core.requestFactory.getRequest(self.__name__, type="XDCC") + #: Change request type + self.req = self.pyload.requestFactory.getRequest(self.__name__, type="XDCC") self.pyfile = pyfile for _i in xrange(0, 3): try: - nmn = self.doDownload(pyfile.url) - self.logDebug("Download of %s finished." % nmn) + nmn = self.do_download(pyfile.url) + self.log_debug("Download of %s finished." % nmn) return except socket.error, e: if hasattr(e, "errno"): @@ -49,9 +50,8 @@ class Xdcc(Hoster): errno = e.args[0] if errno == 10054: - self.logDebug("Server blocked our ip, retry in 5 min") - self.setWait(300) - self.wait() + self.log_debug("Server blocked our ip, retry in 5 min") + self.wait(300) continue self.fail(_("Failed due to socket errors. Code: %d") % errno) @@ -59,17 +59,17 @@ class Xdcc(Hoster): self.fail(_("Server blocked our ip, retry again later manually")) - def doDownload(self, url): - self.pyfile.setStatus("waiting") # real link + def do_download(self, url): + self.pyfile.setStatus("waiting") #: Real link m = re.match(r'xdcc://(.*?)/#?(.*?)/(.*?)/#?(\d+)/?', url) server = m.group(1) chan = m.group(2) bot = m.group(3) pack = m.group(4) - nick = self.getConfig('nick') - ident = self.getConfig('ident') - real = self.getConfig('realname') + nick = self.get_config('nick') + ident = self.get_config('ident') + real = self.get_config('realname') temp = server.split(':') ln = len(temp) @@ -81,30 +81,29 @@ class Xdcc(Hoster): self.fail(_("Invalid hostname for IRC Server: %s") % server) ####################### - # CONNECT TO IRC AND IDLE FOR REAL LINK + #: CONNECT TO IRC AND IDLE FOR REAL LINK dl_time = time.time() sock = socket.socket() sock.connect((host, int(port))) if nick == "pyload": - nick = "pyload-%d" % (time.time() % 1000) # last 3 digits + nick = "pyload-%d" % (time.time() % 1000) #: last 3 digits sock.send("NICK %s\r\n" % nick) sock.send("USER %s %s bla :%s\r\n" % (ident, host, real)) - self.setWait(3) - self.wait() + self.wait(3) sock.send("JOIN #%s\r\n" % chan) sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack)) - # IRC recv loop + #: IRC recv loop readbuffer = "" done = False retry = None m = None while True: - # done is set if we got our real link + #: Done is set if we got our real link if done: break @@ -115,7 +114,7 @@ class Xdcc(Hoster): sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack)) else: - if (dl_time + self.timeout) < time.time(): # todo: add in config + if (dl_time + self.timeout) < time.time(): #@TODO: add in config sock.send("QUIT :byebye\r\n") sock.close() self.fail(_("XDCC Bot did not answer")) @@ -129,8 +128,8 @@ class Xdcc(Hoster): readbuffer = temp.pop() for line in temp: - if self.debug is 2: - print "*> " + unicode(line, errors='ignore') + # if self.pyload.debug: + # self.log_debug("*> " + decode(line)) line = line.rstrip() first = line.split() @@ -145,29 +144,29 @@ class Xdcc(Hoster): continue msg = { - "origin": msg[0][1:], - "action": msg[1], - "target": msg[2], - "text": msg[3][1:] + 'origin': msg[0][1:], + 'action': msg[1], + 'target': msg[2], + 'text': msg[3][1:] } - if nick == msg['target'][0:len(nick)] and "PRIVMSG" == msg['action']: + if nick is msg['target'][0:len(nick)] and "PRIVMSG" is msg['action']: if msg['text'] == "\x01VERSION\x01": - self.logDebug("Sending CTCP VERSION") + self.log_debug("Sending CTCP VERSION") sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) elif msg['text'] == "\x01TIME\x01": - self.logDebug("Sending CTCP TIME") + self.log_debug("Sending CTCP TIME") sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time())) elif msg['text'] == "\x01LAG\x01": - pass # don't know how to answer + pass #: don't know how to answer - if not (bot == msg['origin'][0:len(bot)] - and nick == msg['target'][0:len(nick)] + if not (bot is msg['origin'][0:len(bot)] + and nick is msg['target'][0:len(nick)] and msg['action'] in ("PRIVMSG", "NOTICE")): continue - if self.debug is 1: - print "%s: %s" % (msg['origin'], msg['text']) + if self.pyload.debug: + self.log_debug(msg['origin'], msg['text']) if "You already requested that pack" in msg['text']: retry = time.time() + 300 @@ -179,7 +178,7 @@ class Xdcc(Hoster): if m: done = True - # get connection data + #: Get connection data ip = socket.inet_ntoa(struct.pack('L', socket.ntohl(int(m.group(2))))) port = int(m.group(3)) packname = m.group(1) @@ -189,20 +188,20 @@ class Xdcc(Hoster): self.pyfile.name = packname - download_folder = self.config['general']['download_folder'] - filename = save_join(download_folder, packname) + download_folder = self.pyload.config.get("general", "download_folder") + filename = fs_join(download_folder, packname) - self.logInfo(_("Downloading %s from %s:%d") % (packname, ip, port)) + self.log_info(_("Downloading %s from %s:%d") % (packname, ip, port)) self.pyfile.setStatus("downloading") newname = self.req.download(ip, port, filename, sock, self.pyfile.setProgress) - if newname and newname != filename: - self.logInfo(_("%(name)s saved as %(newname)s") % {"name": self.pyfile.name, "newname": newname}) + if newname and newname is not filename: + self.log_info(_("%(name)s saved as %(newname)s") % {'name': self.pyfile.name, 'newname': newname}) filename = newname - # kill IRC socket - # sock.send("QUIT :byebye\r\n") + #: kill IRC socket + #: sock.send("QUIT :byebye\r\n") sock.close() - self.lastDownload = filename - return self.lastDownload + self.last_download = filename + return self.last_download diff --git a/module/plugins/hoster/YadiSk.py b/module/plugins/hoster/YadiSk.py index 3b4c9d985..a907cd282 100644 --- a/module/plugins/hoster/YadiSk.py +++ b/module/plugins/hoster/YadiSk.py @@ -10,7 +10,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class YadiSk(SimpleHoster): __name__ = "YadiSk" __type__ = "hoster" - __version__ = "0.05" + __version__ = "0.06" + __status__ = "testing" __pattern__ = r'https?://yadi\.sk/d/[\w-]+' @@ -23,8 +24,8 @@ class YadiSk(SimpleHoster): @classmethod - def getInfo(cls, url="", html=""): - info = super(YadiSk, cls).getInfo(url, html) + def get_info(cls, url="", html=""): + info = super(YadiSk, cls).get_info(url, html) if html: if 'idclient' not in info: @@ -59,12 +60,12 @@ class YadiSk(SimpleHoster): def setup(self): - self.resumeDownload = False + self.resume_download = False self.multiDL = False - self.chunkLimit = 1 + self.chunk_limit = 1 - def handleFree(self, pyfile): + def handle_free(self, pyfile): if any(True for _k in ['id', 'sk', 'version', 'idclient'] if _k not in self.info): self.error(_("Missing JSON data")) diff --git a/module/plugins/hoster/YibaishiwuCom.py b/module/plugins/hoster/YibaishiwuCom.py index 00185c05a..e0e90a311 100644 --- a/module/plugins/hoster/YibaishiwuCom.py +++ b/module/plugins/hoster/YibaishiwuCom.py @@ -10,7 +10,8 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class YibaishiwuCom(SimpleHoster): __name__ = "YibaishiwuCom" __type__ = "hoster" - __version__ = "0.14" + __version__ = "0.15" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?(?:u\.)?115\.com/file/(?P<ID>\w+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] @@ -27,14 +28,14 @@ class YibaishiwuCom(SimpleHoster): LINK_FREE_PATTERN = r'(/\?ct=(pickcode|download)[^"\']+)' - def handleFree(self, pyfile): + def handle_free(self, pyfile): m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: self.error(_("LINK_FREE_PATTERN not found")) url = m.group(1) - self.logDebug(('FREEUSER' if m.group(2) == 'download' else 'GUEST') + ' URL', url) + self.log_debug(('FREEUSER' if m.group(2) == "download" else 'GUEST') + ' URL', url) res = json_loads(self.load(urlparse.urljoin("http://115.com", url), decode=False)) if "urls" in res: @@ -49,7 +50,7 @@ class YibaishiwuCom(SimpleHoster): for mr in mirrors: try: self.link = mr['url'].replace("\\", "") - self.logDebug("Trying URL: " + self.link) + self.log_debug("Trying URL: " + self.link) break except Exception: continue diff --git a/module/plugins/hoster/YoupornCom.py b/module/plugins/hoster/YoupornCom.py index 19d07fa36..02272bf36 100644 --- a/module/plugins/hoster/YoupornCom.py +++ b/module/plugins/hoster/YoupornCom.py @@ -2,13 +2,14 @@ import re -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster class YoupornCom(Hoster): __name__ = "YoupornCom" __type__ = "hoster" - __version__ = "0.20" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?youporn\.com/watch/.+' @@ -29,11 +30,12 @@ class YoupornCom(Hoster): def download_html(self): url = self.pyfile.url - self.html = self.load(url, post={"user_choice": "Enter"}, cookies=False) + self.html = self.load(url, post={'user_choice': "Enter"}, cookies=False) def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ if not self.html: self.download_html() @@ -50,7 +52,8 @@ class YoupornCom(Hoster): def file_exists(self): - """ returns True or False + """ + Returns True or False """ if not self.html: self.download_html() diff --git a/module/plugins/hoster/YourfilesTo.py b/module/plugins/hoster/YourfilesTo.py index d0316d3ac..a75bbcc94 100644 --- a/module/plugins/hoster/YourfilesTo.py +++ b/module/plugins/hoster/YourfilesTo.py @@ -1,14 +1,16 @@ # -*- coding: utf-8 -*- -import reimport urllib +import re +import urllib -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster class YourfilesTo(Hoster): __name__ = "YourfilesTo" __type__ = "hoster" - __version__ = "0.22" + __version__ = "0.24" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?yourfiles\.(to|biz)/\?d=\w+' @@ -30,16 +32,14 @@ class YourfilesTo(Hoster): self.pyfile.name = self.get_file_name() - wait_time = self.get_waiting_time() - self.setWait(wait_time) - self.wait() + self.wait(self.get_waiting_time()) def get_waiting_time(self): if not self.html: self.download_html() - #var zzipitime = 15; + #: var zzipitime = 15 m = re.search(r'var zzipitime = (\d+);', self.html) if m: sec = int(m.group(1)) @@ -55,7 +55,8 @@ class YourfilesTo(Hoster): def get_file_url(self): - """ returns the absolute downloadable filepath + """ + Returns the absolute downloadable filepath """ url = re.search(r"var bla = '(.*?)';", self.html) if url: @@ -74,7 +75,8 @@ class YourfilesTo(Hoster): def file_exists(self): - """ returns True or False + """ + Returns True or False """ if not self.html: self.download_html() diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py index e2ab146a9..865eeef2e 100644 --- a/module/plugins/hoster/YoutubeCom.py +++ b/module/plugins/hoster/YoutubeCom.py @@ -2,17 +2,19 @@ import os import re -import subprocessimport urllib +import subprocess +import urllib -from module.plugins.Hoster import Hoster -from module.plugins.internal.SimpleHoster import replace_patterns +from module.plugins.internal.Hoster import Hoster +from module.plugins.internal.Plugin import replace_patterns from module.utils import html_unescape def which(program): - """Works exactly like the unix command which - Courtesy of http://stackoverflow.com/a/377028/675646""" - + """ + Works exactly like the unix command which + Courtesy of http://stackoverflow.com/a/377028/675646 + """ isExe = lambda x: os.path.isfile(x) and os.access(x, os.X_OK) fpath, fname = os.path.split(program) @@ -31,7 +33,8 @@ def which(program): class YoutubeCom(Hoster): __name__ = "YoutubeCom" __type__ = "hoster" - __version__ = "0.41" + __version__ = "0.44" + __status__ = "testing" __pattern__ = r'https?://(?:[^/]*\.)?(youtube\.com|youtu\.be)/watch\?(?:.*&)?v=.+' __config__ = [("quality", "sd;hd;fullhd;240p;360p;480p;720p;1080p;3072p", "Quality Setting" , "hd" ), @@ -50,10 +53,10 @@ class YoutubeCom(Hoster): URL_REPLACEMENTS = [(r'youtu\.be/', 'youtube.com/')] - # Invalid characters that must be removed from the file name + #: Invalid characters that must be removed from the file name invalidChars = u'\u2605:?><"|\\' - # name, width, height, quality ranking, 3D + #: name, width, height, quality ranking, 3D formats = {5 : (".flv" , 400 , 240 , 1 , False), 6 : (".flv" , 640 , 400 , 4 , False), 17 : (".3gp" , 176 , 144 , 0 , False), @@ -78,88 +81,88 @@ class YoutubeCom(Hoster): def setup(self): - self.resumeDownload = True + self.resume_download = True self.multiDL = True def process(self, pyfile): pyfile.url = replace_patterns(pyfile.url, self.URL_REPLACEMENTS) - html = self.load(pyfile.url, decode=True) + html = self.load(pyfile.url) if re.search(r'<div id="player-unavailable" class="\s*player-width player-height\s*">', html): self.offline() if "We have been receiving a large volume of requests from your network." in html: - self.tempOffline() + self.temp_offline() - #get config - use3d = self.getConfig('3d') + #: Get config + use3d = self.get_config('3d') if use3d: - quality = {"sd": 82, "hd": 84, "fullhd": 85, "240p": 83, "360p": 82, - "480p": 82, "720p": 84, "1080p": 85, "3072p": 85} + quality = {'sd': 82, 'hd': 84, 'fullhd': 85, '240p': 83, '360p': 82, + '480p': 82, '720p': 84, '1080p': 85, '3072p': 85} else: - quality = {"sd": 18, "hd": 22, "fullhd": 37, "240p": 5, "360p": 18, - "480p": 35, "720p": 22, "1080p": 37, "3072p": 38} + quality = {'sd': 18, 'hd': 22, 'fullhd': 37, '240p': 5, '360p': 18, + '480p': 35, '720p': 22, '1080p': 37, '3072p': 38} - desired_fmt = self.getConfig('fmt') + desired_fmt = self.get_config('fmt') if not desired_fmt: - desired_fmt = quality.get(self.getConfig('quality'), 18) + desired_fmt = quality.get(self.get_config('quality'), 18) elif desired_fmt not in self.formats: - self.logWarning(_("FMT %d unknown, using default") % desired_fmt) + self.log_warning(_("FMT %d unknown, using default") % desired_fmt) desired_fmt = 0 - #parse available streams + #: Parse available streams streams = re.search(r'"url_encoded_fmt_stream_map":"(.+?)",', html).group(1) streams = [x.split('\u0026') for x in streams.split(',')] streams = [dict((y.split('=', 1)) for y in x) for x in streams] streams = [(int(x['itag']), urllib.unquote(x['url'])) for x in streams] - # self.logDebug("Found links: %s" % streams) + # self.log_debug("Found links: %s" % streams) - self.logDebug("AVAILABLE STREAMS: %s" % [x[0] for x in streams]) + self.log_debug("AVAILABLE STREAMS: %s" % [x[0] for x in streams]) - #build dictionary of supported itags (3D/2D) - allowed = lambda x: self.getConfig(self.formats[x][0]) + #: Build dictionary of supported itags (3D/2D) + allowed = lambda x: self.get_config(self.formats[x][0]) streams = [x for x in streams if x[0] in self.formats and allowed(x[0])] if not streams: self.fail(_("No available stream meets your preferences")) - fmt_dict = dict([x for x in streams if self.formats[x[0]][4] == use3d] or streams) + fmt_dict = dict([x for x in streams if self.formats[x[0]][4] is use3d] or streams) - self.logDebug("DESIRED STREAM: ITAG:%d (%s) %sfound, %sallowed" % + self.log_debug("DESIRED STREAM: ITAG:%d (%s) %sfound, %sallowed" % (desired_fmt, "%s %dx%d Q:%d 3D:%s" % self.formats[desired_fmt], "" if desired_fmt in fmt_dict else "NOT ", "" if allowed(desired_fmt) else "NOT ")) - #return fmt nearest to quality index + #: Return fmt nearest to quality index if desired_fmt in fmt_dict and allowed(desired_fmt): fmt = desired_fmt else: - sel = lambda x: self.formats[x][3] # select quality index + sel = lambda x: self.formats[x][3] #: Select quality index comp = lambda x, y: abs(sel(x) - sel(y)) - self.logDebug("Choosing nearest fmt: %s" % [(x, allowed(x), comp(x, desired_fmt)) for x in fmt_dict.keys()]) + self.log_debug("Choosing nearest fmt: %s" % [(x, allowed(x), comp(x, desired_fmt)) for x in fmt_dict.keys()]) fmt = reduce(lambda x, y: x if comp(x, desired_fmt) <= comp(y, desired_fmt) and sel(x) > sel(y) else y, fmt_dict.keys()) - self.logDebug("Chosen fmt: %s" % fmt) + self.log_debug("Chosen fmt: %s" % fmt) url = fmt_dict[fmt] - self.logDebug("URL: %s" % url) + self.log_debug("URL: %s" % url) - #set file name + #: Set file name file_suffix = self.formats[fmt][0] if fmt in self.formats else ".flv" file_name_pattern = '<meta name="title" content="(.+?)">' name = re.search(file_name_pattern, html).group(1).replace("/", "") - # Cleaning invalid characters from the file name + #: Cleaning invalid characters from the file name name = name.encode('ascii', 'replace') - for c in self.invalidChars: + for c in self.invalid_chars: name = name.replace(c, '_') pyfile.name = html_unescape(name) diff --git a/module/plugins/hoster/ZDF.py b/module/plugins/hoster/ZDF.py index 8d3de5b26..f0b85d11a 100644 --- a/module/plugins/hoster/ZDF.py +++ b/module/plugins/hoster/ZDF.py @@ -1,17 +1,17 @@ # -*- coding: utf-8 -*- import re +import xml.etree.ElementTree as etree -from xml.etree.ElementTree import fromstring - -from module.plugins.Hoster import Hoster +from module.plugins.internal.Hoster import Hoster # Based on zdfm by Roland Beermann (http://github.com/enkore/zdfm/) class ZDF(Hoster): __name__ = "ZDF Mediathek" __type__ = "hoster" - __version__ = "0.80" + __version__ = "0.84" + __status__ = "testing" __pattern__ = r'http://(?:www\.)?zdf\.de/ZDFmediathek/\D*(\d+)\D*' @@ -42,7 +42,7 @@ class ZDF(Hoster): def process(self, pyfile): - xml = fromstring(self.load(self.XML_API % self.get_id(pyfile.url))) + xml = etree.fromstring(self.load(self.XML_API % self.get_id(pyfile.url), decode=False)) status = xml.findtext("./status/statuscode") if status != "ok": @@ -51,7 +51,7 @@ class ZDF(Hoster): video = xml.find("video") title = video.findtext("information/title") - pyfile.name = title + pyfile.name = title.encode("Latin-1") target_url = sorted((v for v in video.iter("formitaet") if self.video_valid(v)), key=self.video_key)[-1].findtext("url") diff --git a/module/plugins/hoster/ZShareNet.py b/module/plugins/hoster/ZShareNet.py index 6e4508a18..b5dd66769 100644 --- a/module/plugins/hoster/ZShareNet.py +++ b/module/plugins/hoster/ZShareNet.py @@ -6,7 +6,8 @@ from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo class ZShareNet(DeadHoster): __name__ = "ZShareNet" __type__ = "hoster" - __version__ = "0.21" + __version__ = "0.22" + __status__ = "testing" __pattern__ = r'https?://(?:ww[2w]\.)?zshares?\.net/.+' __config__ = [] #@TODO: Remove in 0.4.10 diff --git a/module/plugins/hoster/ZahikiNet.py b/module/plugins/hoster/ZahikiNet.py new file mode 100644 index 000000000..f9ea995ba --- /dev/null +++ b/module/plugins/hoster/ZahikiNet.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo + + +class ZahikiNet(SimpleHoster): + __name__ = "ZahikiNet" + __type__ = "hoster" + __version__ = "0.02" + __status__ = "testing" + + __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.resume_download = True + self.multiDL = True + self.limitDL = 6 + + +getInfo = create_getInfo(ZahikiNet) diff --git a/module/plugins/hoster/ZeveraCom.py b/module/plugins/hoster/ZeveraCom.py index 617e00e58..ff3a43e6d 100644 --- a/module/plugins/hoster/ZeveraCom.py +++ b/module/plugins/hoster/ZeveraCom.py @@ -9,10 +9,12 @@ from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo class ZeveraCom(MultiHoster): __name__ = "ZeveraCom" __type__ = "hoster" - __version__ = "0.29" + __version__ = "0.32" + __status__ = "testing" __pattern__ = r'https?://(?:www\.)zevera\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+' - __config__ = [("use_premium", "bool", "Use premium account if available", True)] + __config__ = [("use_premium" , "bool", "Use premium account if available" , True), + ("revertfailed", "bool", "Revert to standard download if fails", True)] __description__ = """Zevera.com multi-hoster plugin""" __license__ = "GPLv3" @@ -20,15 +22,11 @@ class ZeveraCom(MultiHoster): ("Walter Purcaro", "vuolter@gmail.com")] - def handlePremium(self, pyfile): - self.link = "https://%s/getFiles.ashx?ourl=%s" % (self.account.HOSTER_DOMAIN, pyfile.url) - + FILE_ERRORS = [("Error", r'action="ErrorDownload.aspx')] - def checkFile(self, rules={}): - if self.checkDownload({"error": 'action="ErrorDownload.aspx'}): - self.fail(_("Error response received")) - return super(ZeveraCom, self).checkFile(rules) + def handle_premium(self, pyfile): + self.link = "https://%s/getFiles.ashx?ourl=%s" % (self.account.HOSTER_DOMAIN, pyfile.url) getInfo = create_getInfo(ZeveraCom) diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py index d776e5928..1b29948ce 100644 --- a/module/plugins/hoster/ZippyshareCom.py +++ b/module/plugins/hoster/ZippyshareCom.py @@ -3,18 +3,19 @@ import re import urllib -from BeautifulSoup import BeautifulSoup +import BeautifulSoup -from module.plugins.internal.ReCaptcha import ReCaptcha +from module.plugins.captcha.ReCaptcha import ReCaptcha from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo class ZippyshareCom(SimpleHoster): __name__ = "ZippyshareCom" __type__ = "hoster" - __version__ = "0.79" + __version__ = "0.82" + __status__ = "testing" - __pattern__ = r'http://www\d{0,2}\.zippyshare\.com/v(/|iew\.jsp.*key=)(?P<KEY>[\w^_]+)' + __pattern__ = r'http://www\d{0,3}\.zippyshare\.com/v(/|iew\.jsp.*key=)(?P<KEY>[\w^_]+)' __config__ = [("use_premium", "bool", "Use premium account if available", True)] __description__ = """Zippyshare.com hoster plugin""" @@ -33,12 +34,12 @@ class ZippyshareCom(SimpleHoster): def setup(self): - self.chunkLimit = -1 + self.chunk_limit = -1 self.multiDL = True - self.resumeDownload = True + self.resume_download = True - def handleFree(self, pyfile): + def handle_free(self, pyfile): recaptcha = ReCaptcha(self) captcha_key = recaptcha.detect_key() @@ -53,41 +54,41 @@ class ZippyshareCom(SimpleHoster): else: self.link = self.get_link() - if self.link and pyfile.name == 'file.html': + if self.link and pyfile.name == "file.html": pyfile.name = urllib.unquote(self.link.split('/')[-1]) def get_link(self): - # get all the scripts inside the html body - soup = BeautifulSoup(self.html) + #: Get all the scripts inside the html body + soup = BeautifulSoup.BeautifulSoup(self.html) scripts = (s.getText().strip() for s in soup.body.findAll('script', type='text/javascript')) - # meant to be populated with the initialization of all the DOM elements found in the scripts + #: Meant to be populated with the initialization of all the DOM elements found in the scripts initScripts = set() - def replElementById(element): - id = element.group(1) # id might be either 'x' (a real id) or x (a variable) - attr = element.group(4) # attr might be None + def repl_element_by_id(element): + id = element.group(1) #: Id might be either 'x' (a real id) or x (a variable) + attr = element.group(4) #: Attr might be None varName = re.sub(r'-', '', 'GVAR[%s+"_%s"]' %(id, attr)) realid = id.strip('"\'') - if id != realid: #id is not a variable, so look for realid.attr in the html + if id is not realid: #: Id is not a variable, so look for realid.attr in the html initValues = filter(None, [elt.get(attr, None) for elt in soup.findAll(id=realid)]) initValue = '"%s"' % initValues[-1] if initValues else 'null' initScripts.add('%s = %s;' % (varName, initValue)) return varName - # handle all getElementById + #: Handle all getElementById reVar = r'document.getElementById\(([\'"\w-]+)\)(\.)?(getAttribute\([\'"])?(\w+)?([\'"]\))?' - scripts = [re.sub(reVar, replElementById, script) for script in scripts if script] + scripts = [re.sub(reVar, repl_element_by_id, script) for script in scripts if script] - # add try/catch in JS to handle deliberate errors + #: Add try/catch in JS to handle deliberate errors scripts = ['\n'.join(('try{', script, '} catch(err){}')) for script in scripts] - # get the file's url by evaluating all the scripts - scripts = ['var GVAR = {}'] + list(initScripts) + scripts + ['GVAR["dlbutton_href"]'] + #: Get the file's url by evaluating all the scripts + scripts = ["var GVAR = {}"] + list(initScripts) + scripts + ['GVAR["dlbutton_href"]'] return self.js.eval('\n'.join(scripts)) diff --git a/module/plugins/internal/Account.py b/module/plugins/internal/Account.py new file mode 100644 index 000000000..2713e8da4 --- /dev/null +++ b/module/plugins/internal/Account.py @@ -0,0 +1,397 @@ +# -*- coding: utf-8 -*- + +import copy +import random +import time +import threading +import traceback + +from module.plugins.internal.Plugin import Plugin +from module.utils import compare_time, lock, parseFileSize as parse_size + + +class Account(Plugin): + __name__ = "Account" + __type__ = "account" + __version__ = "0.17" + __status__ = "testing" + + __description__ = """Base account plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + LOGIN_TIMEOUT = 10 * 60 #: After that time (in minutes) pyload will relogin the account + INFO_THRESHOLD = 30 * 60 #: After that time (in minutes) account data will be reloaded + + + def __init__(self, manager, accounts): + self._init(manager.core) + + self.lock = threading.RLock() + self.accounts = accounts #@TODO: Remove in 0.4.10 + + self.init() + self.init_accounts(accounts) + + + def init(self): + """ + Initialize additional data structures + """ + pass + + + def login(self, user, password, data, req): + """ + Login into account, the cookies will be saved so user can be recognized + """ + pass + + + @lock + def _login(self, user): + try: + info = self.info[user] + info['login']['timestamp'] = time.time() #: Set timestamp for login + + self.req = self.get_request(user) + self.login(user, info['login']['password'], info['data'], self.req) + + except Exception, e: + self.log_warning(_("Could not login user `%s`") % user, e) + res = info['login']['valid'] = False + self.accounts[user]['valid'] = False #@TODO: Remove in 0.4.10 + + if self.pyload.debug: + traceback.print_exc() + + else: + res = info['login']['valid'] = True + self.accounts[user]['valid'] = True #@TODO: Remove in 0.4.10 + + finally: + self.clean() + return res + + + def relogin(self, user): + self.log_info(_("Relogin user `%s`...") % user) + + req = self.get_request(user) + if req: + req.clearCookies() + self.clean() + + return self._login(user) + + + #@TODO: Rewrite in 0.4.10 + def init_accounts(self, accounts): + for user, data in accounts.items(): + self.add(user, data['password'], data['options']) + + + @lock + def add(self, user, password=None, options={}): + if user not in self.info: + self.info[user] = {'login': {'valid' : None, + 'password' : password or "", + 'timestamp': 0}, + 'data' : {'options' : options, + 'premium' : None, + 'validuntil' : None, + 'trafficleft': None, + 'maxtraffic' : None}} + + #@TODO: Remove in 0.4.10 + self.accounts[user] = self.info[user]['data'] + self.accounts[user].update({'login' : user, + 'type' : self.__name__, + 'valid' : self.info[user]['login']['valid'], + 'password': self.info[user]['login']['password']}) + + self.log_info(_("Login user `%s`...") % user) + self._login(user) + return True + + else: + self.log_error(_("Error adding user `%s`") % user, _("User already exists")) + + + @lock + def update(self, user, password=None, options={}): + """ + Updates account and return true if anything changed + """ + if not (password or options): + return + + if user not in self.info: + return self.add(user, password, options) + + else: + if password: + self.info[user]['login']['password'] = password + self.accounts[user]['password'] = password #@TODO: Remove in 0.4.10 + self.relogin(user) + + if options: + before = self.info[user]['data']['options'] + self.info[user]['data']['options'].update(options) + return self.info[user]['data']['options'] != before + + return True + + + #: Deprecated method, use `update` instead (Remove in 0.4.10) + def updateAccounts(self, *args, **kwargs): + return self.update(*args, **kwargs) + + + def remove(self, user=None): # -> def remove + if not user: + self.info.clear() + self.accounts.clear() #@TODO: Remove in 0.4.10 + + elif user in self.info: + self.info.pop(user, None) + self.accounts.pop(user, None) #@TODO: Remove in 0.4.10 + + + #: Deprecated method, use `remove` instead (Remove in 0.4.10) + def removeAccount(self, *args, **kwargs): + return self.remove(*args, **kwargs) + + + #@NOTE: Remove in 0.4.10? + def get_data(self, user, reload=False): + if not user: + return + + info = self.get_info(user, reload) + if info and 'data' in info: + return info['data'] + + + #: Deprecated method, use `get_data` instead (Remove in 0.4.10) + def getAccountData(self, *args, **kwargs): + if 'force' in kwargs: + kwargs['reload'] = kwargs['force'] + kwargs.pop('force', None) + + data = self.get_data(*args, **kwargs) or {} + if 'options' not in data: + data['options'] = {'limitdl': ['0']} + + return data + + + def get_info(self, user, reload=False): + """ + Retrieve account infos for an user, do **not** overwrite this method!\\ + just use it to retrieve infos in hoster plugins. see `parse_info` + + :param user: username + :param reload: reloads cached account information + :return: dictionary with information + """ + if user not in self.info: + self.log_error(_("User `%s` not found while retrieving account info") % user) + return + + elif reload: + self.log_info(_("Parsing account info for user `%s`...") % user) + info = self._parse_info(user) + + safe_info = copy.deepcopy(info) + safe_info['login']['password'] = "**********" + safe_info['data']['password'] = "**********" #@TODO: Remove in 0.4.10 + self.log_debug("Account info for user `%s`: %s" % (user, safe_info)) + + elif self.INFO_THRESHOLD > 0 and self.info[user]['login']['timestamp'] + self.INFO_THRESHOLD < time.time(): + self.log_debug("Reached data timeout for %s" % user) + info = self.get_info(user, True) + + else: + info = self.info[user] + + return info + + + def is_premium(self, user): + if not user: + return False + + info = self.get_info(user) + return info['data']['premium'] + + + def _parse_info(self, user): + info = self.info[user] + + if not info['login']['valid']: + return info + + try: + self.req = self.get_request(user) + extra_info = self.parse_info(user, info['login']['password'], info, self.req) + + if extra_info and isinstance(extra_info, dict): + info['data'].update(extra_info) + + except (Fail, Exception), e: + self.log_warning(_("Error loading info for user `%s`") % user, e) + + if self.pyload.debug: + traceback.print_exc() + + finally: + self.clean() + + self.info[user].update(info) + return info + + + def parse_info(self, user, password, info, req): + """ + This should be overwritten in account plugin + and retrieving account information for user + + :param user: + :param req: `Request` instance + :return: + """ + pass + + + #: Remove in 0.4.10 + def getAllAccounts(self, *args, **kwargs): + return [self.getAccountData(user, *args, **kwargs) for user, info in self.info.items()] + + + def login_fail(self, reason=_("Login handshake has failed")): + return self.fail(reason) + + + def get_request(self, user=None): + if not user: + user, info = self.select() + + return self.pyload.requestFactory.getRequest(self.__name__, user) + + + def get_cookies(self, user=None): + if not user: + user, info = self.select() + + return self.pyload.requestFactory.getCookieJar(self.__name__, user) + + + def select(self): + """ + Returns a valid account name and info + """ + free_accounts = {} + premium_accounts = {} + + for user, info in self.info.items(): + if not info['login']['valid']: + continue + + data = info['data'] + + if "time" in data['options'] and data['options']['time']: + time_data = "" + try: + time_data = data['options']['time'][0] + start, end = time_data.split("-") + + if not compare_time(start.split(":"), end.split(":")): + continue + + except Exception: + self.log_warning(_("Wrong time format `%s` for account `%s`, use 1:22-3:44") % (user, time_data)) + + if data['trafficleft'] == 0: + continue + + if time.time() > data['validuntil'] > 0: + continue + + if data['premium']: + premium_accounts[user] = info + + else: + free_accounts[user] = info + + account_list = (premium_accounts or free_accounts).items() + + if not account_list: + return None, None + + validuntil_list = [(user, info) for user, info in account_list if info['data']['validuntil']] + + if not validuntil_list: + return random.choice(account_list) #@TODO: Random account?! Recheck in 0.4.10 + + return sorted(validuntil_list, + key=lambda a: a[1]['data']['validuntil'], + reverse=True)[0] + + + def parse_traffic(self, value, unit=None): #: Return kilobytes + if not unit and not isinstance(value, basestring): + unit = "KB" + + return parse_size(value, unit) + + + def empty(self, user): + if user not in self.info: + return + + self.log_warning(_("Account `%s` has not enough traffic") % user, _("Checking again in 30 minutes")) + + self.info[user]['data']['trafficleft'] = 0 + self.schedule_refresh(user, 30 * 60) + + + def expired(self, user): + if user not in self.info: + return + + self.log_warning(_("Account `%s` is expired") % user, _("Checking again in 60 minutes")) + + self.info[user]['data']['validuntil'] = time.time() - 1 + self.schedule_refresh(user, 60 * 60) + + + def schedule_refresh(self, user, time=0): + """ + Add task to refresh account info to sheduler + """ + self.log_debug("Scheduled refresh for user `%s` in %s seconds" % (user, time)) + self.pyload.scheduler.addJob(time, self.get_info, [user, True]) + + + #: Deprecated method, use `schedule_refresh` instead (Remove in 0.4.10) + def scheduleRefresh(self, *args, **kwargs): + if 'force' in kwargs: + kwargs.pop('force', None) #@TODO: Recheck in 0.4.10 + return self.schedule_refresh(*args, **kwargs) + + + @lock + def is_logged(self, user, relogin=False): + """ + Checks if user is still logged in + """ + if user in self.info: + if self.LOGIN_TIMEOUT > 0 and self.info[user]['login']['timestamp'] + self.LOGIN_TIMEOUT < time.time(): + self.log_debug("Reached login timeout for %s" % user) + return self.relogin(user) if relogin else False + else: + return True + else: + return False diff --git a/module/plugins/internal/Addon.py b/module/plugins/internal/Addon.py new file mode 100644 index 000000000..45ca98eac --- /dev/null +++ b/module/plugins/internal/Addon.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- + +import traceback + +from module.plugins.internal.Plugin import Plugin + + +class Expose(object): + """ + Used for decoration to declare rpc services + """ + def __new__(cls, f, *args, **kwargs): + hookManager.addRPC(f.__module__, f.func_name, f.func_doc) + return f + + +def threaded(fn): + + def run(*args, **kwargs): + hookManager.startThread(fn, *args, **kwargs) + + return run + + +class Addon(Plugin): + __name__ = "Addon" + __type__ = "hook" #@TODO: Change to `addon` in 0.4.10 + __version__ = "0.04" + __status__ = "testing" + + __config__ = [] #: [("name", "type", "desc", "default")] + __threaded__ = [] #@TODO: Remove in 0.4.10 + + __description__ = """Base addon plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + def __init__(self, core, manager): + self._init(core) + + #: `HookManager` + self.manager = manager + + #: Automatically register event listeners for functions, attribute will be deleted dont use it yourself + self.event_map = {} + + #: Deprecated alternative to event_map + #: List of events the plugin can handle, name the functions exactly like eventname. + self.event_list = [] #@NOTE: dont make duplicate entries in event_map + + #: Callback of periodical job task, used by HookManager + self.cb = None + self.interval = 60 + + self.init() + self.init_events() + + + def init_events(self): + if self.event_map: + for event, funcs in self.event_map.items(): + if type(funcs) in (list, tuple): + for f in funcs: + self.manager.addEvent(event, getattr(self, f)) + else: + self.manager.addEvent(event, getattr(self, funcs)) + + #: Delete for various reasons + self.event_map = None + + if self.event_list: + self.log_debug("Deprecated method `event_list`, use `event_map` instead") + + for f in self.event_list: + self.manager.addEvent(f, getattr(self, f)) + + self.event_list = None + + + def init_periodical(self, delay=0, threaded=False): + self.cb = self.pyload.scheduler.addJob(max(0, delay), self._periodical, [threaded], threaded=threaded) + + + #: Deprecated method, use `init_periodical` instead (Remove in 0.4.10) + def initPeriodical(self, *args, **kwargs): + return self.init_periodical(*args, **kwargs) + + + def _periodical(self, threaded): + if self.interval < 0: + self.cb = None + return + + try: + self.periodical() + + except Exception, e: + self.log_error(_("Error executing periodical task: %s") % e) + if self.pyload.debug: + traceback.print_exc() + + self.cb = self.pyload.scheduler.addJob(self.interval, self._periodical, [threaded], threaded=threaded) + + + def periodical(self): + pass + + + def __repr__(self): + return "<Addon %s>" % self.__name__ + + + def is_activated(self): + """ + Checks if addon is activated + """ + return self.get_config("activated") + + + #: Deprecated method, use `is_activated` instead (Remove in 0.4.10) + def isActivated(self, *args, **kwargs): + return self.is_activated(*args, **kwargs) + + + def deactivate(self): + """ + Called when addon was deactivated + """ + pass + + + #: Deprecated method, use `deactivate` instead (Remove in 0.4.10) + def unload(self, *args, **kwargs): + return self.deactivate(*args, **kwargs) + + + def activate(self): + """ + Called when addon was activated + """ + pass + + + #: Deprecated method, use `activate` instead (Remove in 0.4.10) + def coreReady(self, *args, **kwargs): + return self.activate(*args, **kwargs) + + + def exit(self): + """ + Called by core.shutdown just before pyLoad exit + """ + pass + + + #: Deprecated method, use `exit` instead (Remove in 0.4.10) + def coreExiting(self, *args, **kwargs): + self.unload(*args, **kwargs) #@TODO: Fix in 0.4.10 + return self.exit(*args, **kwargs) + + + def download_preparing(self, pyfile): + pass + + + #: Deprecated method, use `download_preparing` instead (Remove in 0.4.10) + def downloadPreparing(self, pyfile): + if pyfile.plugin.req is not None: #@TODO: Remove in 0.4.10 + return self.download_preparing(pyfile) + + + def download_finished(self, pyfile): + pass + + + #: Deprecated method, use `download_finished` instead (Remove in 0.4.10) + def downloadFinished(self, *args, **kwargs): + return self.download_finished(*args, **kwargs) + + + def download_failed(self, pyfile): + pass + + + #: Deprecated method, use `download_failed` instead (Remove in 0.4.10) + def downloadFailed(self, *args, **kwargs): + return self.download_failed(*args, **kwargs) + + + def package_finished(self, pypack): + pass + + + #: Deprecated method, use `package_finished` instead (Remove in 0.4.10) + def packageFinished(self, *args, **kwargs): + return self.package_finished(*args, **kwargs) + + + def before_reconnect(self, ip): + pass + + + #: Deprecated method, use `before_reconnect` instead (Remove in 0.4.10) + def beforeReconnecting(self, *args, **kwargs): + return self.before_reconnect(*args, **kwargs) + + + def after_reconnect(self, ip, oldip): + pass + + + #: Deprecated method, use `after_reconnect` instead (Remove in 0.4.10) + def afterReconnecting(self, ip): + return self.after_reconnect(ip, None) + + + def captcha_task(self, task): + """ + New captcha task for the plugin, it MUST set the handler and timeout or will be ignored + """ + pass + + + #: Deprecated method, use `captcha_task` instead (Remove in 0.4.10) + def newCaptchaTask(self, *args, **kwargs): + return self.captcha_task(*args, **kwargs) + + + def captcha_correct(self, task): + pass + + + #: Deprecated method, use `captcha_correct` instead (Remove in 0.4.10) + def captchaCorrect(self, *args, **kwargs): + return self.captcha_correct(*args, **kwargs) + + + def captcha_invalid(self, task): + pass + + + #: Deprecated method, use `captcha_invalid` instead (Remove in 0.4.10) + def captchaInvalid(self, *args, **kwargs): + return self.captcha_invalid(*args, **kwargs) diff --git a/module/plugins/internal/Captcha.py b/module/plugins/internal/Captcha.py index b4af46493..c08050ee8 100644 --- a/module/plugins/internal/Captcha.py +++ b/module/plugins/internal/Captcha.py @@ -1,56 +1,141 @@ # -*- coding: utf-8 -*- -from module.plugins.Plugin import Base +from __future__ import with_statement +import os +import time +import traceback -#@TODO: Extend (new) Plugin class; remove all `html` args -class Captcha(Base): +from module.plugins.internal.Plugin import Plugin + + +class Captcha(Plugin): __name__ = "Captcha" __type__ = "captcha" - __version__ = "0.29" + __version__ = "0.42" + __status__ = "testing" - __description__ = """Base captcha service plugin""" + __description__ = """Base anti-captcha plugin""" __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - key = None #: last key detected + def __init__(self, plugin): #@TODO: Pass pyfile instead plugin, so store plugin's html in its associated pyfile as data + self._init(plugin.pyload) - def __init__(self, plugin): self.plugin = plugin - super(Captcha, self).__init__(plugin.core) + self.task = None #: captchaManager task + + self.init() + + + def init(self): + """ + Initialize additional data structures + """ + pass + + + def _log(self, level, plugintype, pluginname, messages): + return self.plugin._log(level, + plugintype, + self.plugin.__name__, + (self.__name__,) + messages) + + + def recognize(self, image): + """ + Extend to build your custom anti-captcha ocr + """ + pass + + + def decrypt(self, url, get={}, post={}, ref=False, cookies=False, decode=False, + input_type='jpg', output_type='textual', ocr=True, timeout=120): + img = self.load(url, get=get, post=post, ref=ref, cookies=cookies, decode=decode) + return self._decrypt(img, input_type, output_type, ocr, timeout) + + + #@TODO: Definitely choose a better name for this method! + def _decrypt(self, raw, input_type='jpg', output_type='textual', ocr=False, timeout=120): + """ + Loads a captcha and decrypts it with ocr, plugin, user input + + :param raw: image raw data + :param get: get part for request + :param post: post part for request + :param cookies: True if cookies should be enabled + :param input_type: Type of the Image + :param output_type: 'textual' if text is written on the captcha\ + or 'positional' for captcha where the user have to click\ + on a specific region on the captcha + :param ocr: if True, ocr is not used + + :return: result of decrypting + """ + result = "" + time_ref = ("%.2f" % time.time())[-6:].replace(".", "") + + with open(os.path.join("tmp", "captcha_image_%s_%s.%s" % (self.plugin.__name__, time_ref, input_type)), "wb") as tmp_img: + tmp_img.write(raw) + + if ocr: + if isinstance(ocr, basestring): + OCR = self.pyload.pluginManager.loadClass("captcha", ocr) #: Rename `captcha` to `ocr` in 0.4.10 + result = OCR(self.plugin).recognize(tmp_img.name) + else: + result = self.recognize(tmp_img.name) + + if not result: + captchaManager = self.pyload.captchaManager + + try: + self.task = captchaManager.newTask(raw, input_type, tmp_img.name, output_type) + + captchaManager.handleCaptcha(self.task) + + self.task.setWaiting(max(timeout, 50)) #@TODO: Move to `CaptchaManager` in 0.4.10 + while self.task.isWaiting(): + if self.plugin.pyfile.abort: + self.plugin.abort() + time.sleep(1) + + finally: + captchaManager.removeTask(self.task) + + if self.task.error: + self.fail(self.task.error) + elif not self.task.result: + self.invalid() + self.plugin.retry(reason=_("No captcha result obtained in appropiate time")) - #@TODO: Recheck in 0.4.10 - def fail(self, reason): - self.plugin.fail(reason) - raise AttributeError(reason) + result = self.task.result + if not self.pyload.debug: + try: + os.remove(tmp_img.name) - #@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__) + except OSError, e: + self.log_warning(_("Error removing: %s") % tmp_img.name, e) + traceback.print_exc() + self.log_info(_("Captcha result: ") + result) #@TODO: Remove from here? - #@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__) + return result - def detect_key(self, html=None): - raise NotImplementedError + def invalid(self): + if not self.task: + return + self.log_error(_("Invalid captcha")) + self.task.invalid() - def challenge(self, key=None, html=None): - raise NotImplementedError + def correct(self): + if not self.task: + return - def result(self, server, challenge): - raise NotImplementedError + self.log_info(_("Correct captcha")) + self.task.correct() diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py new file mode 100644 index 000000000..20dc60427 --- /dev/null +++ b/module/plugins/internal/CaptchaService.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.Captcha import Captcha + + +class CaptchaService(Captcha): + __name__ = "CaptchaService" + __type__ = "captcha" + __version__ = "0.32" + __status__ = "testing" + + __description__ = """Base anti-captcha service plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + def init(self): + self.key = None #: Last key detected + + + #@TODO: Recheck in 0.4.10 + def retrieve_key(self, data): + if self.detect_key(data): + return self.key + else: + self.fail(_("%s key not found") % self.__name__) + + + #@TODO: Recheck in 0.4.10, html is now pyfile.data + def retrieve_data(self): + if hasattr(self.plugin, "html") and self.plugin.html: + return self.plugin.html + else: + self.fail(_("%s data not found") % self.__name__) + + + def detect_key(self, data=None): + raise NotImplementedError + + + def challenge(self, key=None, data=None): + raise NotImplementedError + + + def result(self, server, challenge): + raise NotImplementedError diff --git a/module/plugins/internal/Container.py b/module/plugins/internal/Container.py new file mode 100644 index 000000000..729592a0d --- /dev/null +++ b/module/plugins/internal/Container.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement + +import os +import re +import traceback + +from module.plugins.internal.Crypter import Crypter +from module.plugins.internal.Plugin import exists +from module.utils import save_join as fs_join + + +class Container(Crypter): + __name__ = "Container" + __type__ = "container" + __version__ = "0.06" + __status__ = "testing" + + __pattern__ = r'^unmatchable$' + __config__ = [] #: [("name", "type", "desc", "default")] + + __description__ = """Base container decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("mkaay", "mkaay@mkaay.de")] + + + def process(self, pyfile): + """ + Main method + """ + self._load2disk() + + self.decrypt(pyfile) + + self.delete_tmp() + + if self.urls: + self._generate_packages() + + elif not self.packages: + self.error(_("No link grabbed"), "decrypt") + + self._create_packages() + + + #: Deprecated method, use `_load2disk` instead (Remove in 0.4.10) + def loadToDisk(self, *args, **kwargs): + return self._load2disk(*args, **kwargs) + + + def _load2disk(self): + """ + Loads container to disk if its stored remotely and overwrite url, + or check existent on several places at disk + """ + if self.pyfile.url.startswith("http"): + self.pyfile.name = re.findall("([^\/=]+)", self.pyfile.url)[-1] + content = self.load(self.pyfile.url) + self.pyfile.url = fs_join(self.pyload.config.get("general", "download_folder"), self.pyfile.name) + try: + with open(self.pyfile.url, "wb") as f: + f.write(content) + + except IOError, e: + self.fail(str(e)) #@TODO: Remove `str` in 0.4.10 + + else: + self.pyfile.name = os.path.basename(self.pyfile.url) + if not exists(self.pyfile.url): + if exists(fs_join(pypath, self.pyfile.url)): + self.pyfile.url = fs_join(pypath, self.pyfile.url) + else: + self.fail(_("File not exists")) + + + #: Deprecated method, use `delete_tmp` instead (Remove in 0.4.10) + def deleteTmp(self, *args, **kwargs): + return self.delete_tmp(*args, **kwargs) + + + def delete_tmp(self): + if not self.pyfile.name.startswith("tmp_"): + return + + try: + os.remove(self.pyfile.url) + except OSError, e: + self.log_warning(_("Error removing: %s") % self.pyfile.url, e) + if self.pyload.debug: + traceback.print_exc() diff --git a/module/plugins/internal/Crypter.py b/module/plugins/internal/Crypter.py new file mode 100644 index 000000000..d0e8eb1b4 --- /dev/null +++ b/module/plugins/internal/Crypter.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +import urlparse + +from module.plugins.internal.Hoster import Hoster, _fixurl +from module.utils import save_path as safe_filename + + +class Crypter(Hoster): + __name__ = "Crypter" + __type__ = "crypter" + __version__ = "0.07" + __status__ = "testing" + + __pattern__ = r'^unmatchable$' + __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides pyload.config.get("general", "folder_per_package") + ("subfolder_per_package", "bool", "Create a subfolder for each package", True)] + + __description__ = """Base decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + html = None #: Last html loaded #@TODO: Move to Hoster + + + def __init__(self, pyfile): + super(Crypter, self).__init__(pyfile) + + #: Put all packages here. It's a list of tuples like: ( name, [list of links], folder ) + self.packages = [] + + #: List of urls, pyLoad will generate packagenames + self.urls = [] + + + def process(self, pyfile): + """ + Main method + """ + self.decrypt(pyfile) + + if self.urls: + self._generate_packages() + + elif not self.packages: + self.error(_("No link grabbed"), "decrypt") + + self._create_packages() + + + def decrypt(self, pyfile): + raise NotImplementedError + + + def _generate_packages(self): + """ + Generate new packages from self.urls + """ + packages = [(name, links, None) for name, links in self.pyload.api.generatePackages(self.urls).items()] + self.packages.extend(packages) + + + def _create_packages(self): + """ + Create new packages from self.packages + """ + package_folder = self.pyfile.package().folder + package_password = self.pyfile.package().password + package_queue = self.pyfile.package().queue + + folder_per_package = self.pyload.config.get("general", "folder_per_package") + use_subfolder = self.get_config('use_subfolder', folder_per_package) + subfolder_per_package = self.get_config('subfolder_per_package', True) + + for name, links, folder in self.packages: + self.log_debug("Parsed package: %s" % name, + "%d links" % len(links), + "Saved to folder: %s" % folder if folder else "Saved to download folder") + + pid = self.pyload.api.addPackage(name, map(self.fixurl, links), package_queue) + + if package_password: + self.pyload.api.setPackageData(pid, {'password': package_password}) + + #: Workaround to do not break API addPackage method + set_folder = lambda x: self.pyload.api.setPackageData(pid, {'folder': x or ""}) + + if use_subfolder: + if not subfolder_per_package: + set_folder(package_folder) + self.log_debug("Set package %(name)s folder to: %(folder)s" % {'name': name, 'folder': folder}) + + elif not folder_per_package or name is not folder: + if not folder: + folder = urlparse.urlparse(_fixurl(name)).path.split("/")[-1] + + set_folder(safe_filename(folder)) + self.log_debug("Set package %(name)s folder to: %(folder)s" % {'name': name, 'folder': folder}) + + elif folder_per_package: + set_folder(None) diff --git a/module/plugins/internal/DeadCrypter.py b/module/plugins/internal/DeadCrypter.py index c93447164..e7cc6ff39 100644 --- a/module/plugins/internal/DeadCrypter.py +++ b/module/plugins/internal/DeadCrypter.py @@ -1,31 +1,30 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleCrypter import create_getInfo -from module.plugins.Crypter import Crypter as _Crypter +from module.plugins.internal.Crypter import Crypter, create_getInfo -class DeadCrypter(_Crypter): +class DeadCrypter(Crypter): __name__ = "DeadCrypter" __type__ = "crypter" - __version__ = "0.05" + __version__ = "0.09" + __status__ = "testing" __pattern__ = r'^unmatchable$' - __description__ = """ Crypter is no longer available """ + __description__ = """Crypter is no longer available""" __license__ = "GPLv3" __authors__ = [("stickell", "l.stickell@yahoo.it")] @classmethod - def apiInfo(cls, url): - api = super(DeadCrypter, cls).apiInfo(url) - api['status'] = 1 - return api + def get_info(cls, *args, **kwargs): + info = super(DeadCrypter, cls).get_info(*args, **kwargs) + info['status'] = 1 + return info def setup(self): - self.pyfile.error = "Crypter is no longer available" - self.offline() #@TODO: self.offline("Crypter is no longer available") + self.offline(_("Crypter is no longer available")) getInfo = create_getInfo(DeadCrypter) diff --git a/module/plugins/internal/DeadHoster.py b/module/plugins/internal/DeadHoster.py index f159ae5fa..250287d25 100644 --- a/module/plugins/internal/DeadHoster.py +++ b/module/plugins/internal/DeadHoster.py @@ -1,31 +1,30 @@ # -*- coding: utf-8 -*- -from module.plugins.internal.SimpleHoster import create_getInfo -from module.plugins.Hoster import Hoster as _Hoster +from module.plugins.internal.Hoster import Hoster, create_getInfo -class DeadHoster(_Hoster): +class DeadHoster(Hoster): __name__ = "DeadHoster" __type__ = "hoster" - __version__ = "0.15" + __version__ = "0.19" + __status__ = "testing" __pattern__ = r'^unmatchable$' - __description__ = """ Hoster is no longer available """ + __description__ = """Hoster is no longer available""" __license__ = "GPLv3" __authors__ = [("zoidberg", "zoidberg@mujmail.cz")] @classmethod - def apiInfo(cls, url): - api = super(DeadHoster, cls).apiInfo(url) - api['status'] = 1 - return api + def get_info(cls, *args, **kwargs): + info = super(DeadHoster, cls).get_info(*args, **kwargs) + info['status'] = 1 + return info def setup(self): - self.pyfile.error = "Hoster is no longer available" - self.offline() #@TODO: self.offline("Hoster is no longer available") + self.offline(_("Hoster is no longer available")) getInfo = create_getInfo(DeadHoster) diff --git a/module/plugins/internal/Extractor.py b/module/plugins/internal/Extractor.py index 159b65ffe..7f5212090 100644 --- a/module/plugins/internal/Extractor.py +++ b/module/plugins/internal/Extractor.py @@ -4,6 +4,7 @@ import os import re from module.PyFile import PyFile +from module.plugins.internal.Plugin import Plugin class ArchiveError(Exception): @@ -18,9 +19,11 @@ class PasswordError(Exception): pass -class Extractor: +class Extractor(Plugin): __name__ = "Extractor" - __version__ = "0.24" + __type__ = "extractor" + __version__ = "0.33" + __status__ = "testing" __description__ = """Base extractor plugin""" __license__ = "GPLv3" @@ -29,32 +32,34 @@ class Extractor: EXTENSIONS = [] - VERSION = "" REPAIR = False + VERSION = None @classmethod - def isArchive(cls, filename): + def is_archive(cls, filename): name = os.path.basename(filename).lower() return any(name.endswith(ext) for ext in cls.EXTENSIONS) @classmethod - def isMultipart(cls, filename): + def is_multipart(cls, filename): return False @classmethod - def isUsable(cls): - """ Check if system statisfy dependencies + def find(cls): + """ + Check if system statisfy dependencies :return: boolean """ - return None + pass @classmethod - def getTargets(cls, files_ids): - """ Filter suited targets from list of filename id tuple list + def get_targets(cls, files_ids): + """ + Filter suited targets from list of filename id tuple list :param files_ids: List of filepathes :return: List of targets, id tuple list """ @@ -62,15 +67,15 @@ class Extractor: processed = [] for fname, id, fout in files_ids: - if cls.isArchive(fname): - pname = re.sub(cls.re_multipart, '', fname) if cls.isMultipart(fname) else os.path.splitext(fname)[0] + if cls.is_archive(fname): + pname = re.sub(cls.re_multipart, "", fname) if cls.is_multipart(fname) else os.path.splitext(fname)[0] if pname not in processed: processed.append(pname) targets.append((fname, id, fout)) return targets - def __init__(self, manager, filename, out, + def __init__(self, plugin, filename, out, fullpath=True, overwrite=False, excludefiles=[], @@ -78,8 +83,12 @@ class Extractor: delete='No', keepbroken=False, fid=None): - """ Initialize extractor for specific file """ - self.manager = manager + """ + Initialize extractor for specific file + """ + self._init(plugin.pyload) + + self.plugin = plugin self.filename = filename self.out = out self.fullpath = fullpath @@ -90,17 +99,29 @@ class Extractor: self.keepbroken = keepbroken self.files = [] #: Store extracted files here - pyfile = self.manager.core.files.getFile(fid) if fid else None - self.notifyProgress = lambda x: pyfile.setProgress(x) if pyfile else lambda x: None + pyfile = self.pyload.files.getFile(fid) if fid else None + self.notify_progress = lambda x: pyfile.setProgress(x) if pyfile else lambda x: None + + self.init() def init(self): - """ Initialize additional data structures """ + """ + Initialize additional data structures + """ pass + def _log(self, level, plugintype, pluginname, messages): + return self.plugin._log(level, + plugintype, + self.plugin.__name__, + (self.__name__,) + messages) + + def check(self): - """Quick Check by listing content of archive. + """ + Quick Check by listing content of archive. Raises error if password is needed, integrity is questionable or else. :raises PasswordError @@ -109,8 +130,10 @@ class Extractor: """ raise NotImplementedError + def verify(self): - """Testing with Extractors buildt-in method + """ + Testing with Extractors buildt-in method Raises error if password is needed, integrity is questionable or else. :raises PasswordError @@ -125,7 +148,8 @@ class Extractor: def extract(self, password=None): - """Extract the archive. Raise specific errors in case of failure. + """ + Extract the archive. Raise specific errors in case of failure. :param progress: Progress function, call this to update status :param password password to use @@ -137,8 +161,9 @@ class Extractor: raise NotImplementedError - def getDeleteFiles(self): - """Return list of files to delete, do *not* delete them here. + def get_delete_files(self): + """ + Return list of files to delete, do *not* delete them here. :return: List with paths of files to delete """ @@ -146,5 +171,7 @@ class Extractor: def list(self, password=None): - """Populate self.files at some point while extracting""" + """ + Populate self.files at some point while extracting + """ return self.files diff --git a/module/plugins/internal/Hook.py b/module/plugins/internal/Hook.py new file mode 100644 index 000000000..1f566f824 --- /dev/null +++ b/module/plugins/internal/Hook.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.Addon import Addon, threaded + + +class Hook(Addon): + __name__ = "Hook" + __type__ = "hook" + __version__ = "0.13" + __status__ = "testing" + + __config__ = [] #: [("name", "type", "desc", "default")] + + __description__ = """Base hook plugin""" + __license__ = "GPLv3" + __authors__ = [("mkaay" , "mkaay@mkaay.de" ), + ("RaNaN" , "RaNaN@pyload.org" ), + ("Walter Purcaro", "vuolter@gmail.com")] + + + def __init__(self, core, manager): + super(Hook, self).__init__(core, manager) + self.init_periodical(10) + + + #@TODO: Remove in 0.4.10 + def _log(self, level, plugintype, pluginname, messages): + return super(Addon, self)._log(level, plugintype, pluginname.replace("Hook", ""), messages) diff --git a/module/plugins/internal/Hoster.py b/module/plugins/internal/Hoster.py new file mode 100644 index 000000000..a0cdb1e2e --- /dev/null +++ b/module/plugins/internal/Hoster.py @@ -0,0 +1,648 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement + +import inspect +import os +import random +import time +import traceback +import urlparse + +from module.plugins.internal.Captcha import Captcha +from module.plugins.internal.Plugin import (Plugin, Abort, Fail, Reconnect, Retry, Skip, + chunks, encode, exists, fixurl as _fixurl, replace_patterns, + seconds_to_midnight, set_cookie, set_cookies, parse_html_form, + parse_html_tag_attr_value, timestamp) +from module.utils import fs_decode, fs_encode, save_join as fs_join, save_path as safe_filename + + +#@TODO: Remove in 0.4.10 +def parse_fileInfo(klass, url="", html=""): + info = klass.get_info(url, html) + return info['name'], info['size'], info['status'], info['url'] + + +#@TODO: Remove in 0.4.10 +def getInfo(urls): + #: result = [ .. (name, size, status, url) .. ] + pass + + +#@TODO: Remove in 0.4.10 +def create_getInfo(klass): + def get_info(urls): + for url in urls: + if hasattr(klass, "URL_REPLACEMENTS"): + url = replace_patterns(url, klass.URL_REPLACEMENTS) + yield parse_fileInfo(klass, url) + + return get_info + + +class Hoster(Plugin): + __name__ = "Hoster" + __type__ = "hoster" + __version__ = "0.19" + __status__ = "testing" + + __pattern__ = r'^unmatchable$' + __config__ = [] #: [("name", "type", "desc", "default")] + + __description__ = """Base hoster plugin""" + __license__ = "GPLv3" + __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), + ("spoob" , "spoob@pyload.org" ), + ("mkaay" , "mkaay@mkaay.de" ), + ("Walter Purcaro", "vuolter@gmail.com")] + + + def __init__(self, pyfile): + self._init(pyfile.m.core) + + #: Engage wan reconnection + self.wantReconnect = False #@TODO: Change to `want_reconnect` in 0.4.10 + + #: Enable simultaneous processing of multiple downloads + self.multiDL = True #@TODO: Change to `multi_dl` in 0.4.10 + self.limitDL = 0 #@TODO: Change to `limit_dl` in 0.4.10 + + #: time.time() + wait in seconds + self.wait_until = 0 + self.waiting = False + + #: Account handler instance, see :py:class:`Account` + self.account = None + self.user = None + self.req = None #: Browser instance, see `network.Browser` + + #: Associated pyfile instance, see `PyFile` + self.pyfile = pyfile + + self.thread = None #: Holds thread in future + + #: Location where the last call to download was saved + self.last_download = "" + + #: Re match of the last call to `checkDownload` + self.last_check = None + + #: Js engine, see `JsEngine` + self.js = self.pyload.js + + #: Captcha stuff + self.captcha = Captcha(self) + + #: Some plugins store html code here + self.html = None + + #: Dict of the amount of retries already made + self.retries = {} + self.retry_free = False #@TODO: Recheck in 0.4.10 + + self._setup() + self.init() + + + @classmethod + def get_info(cls, url="", html=""): + url = _fixurl(url) + url_p = urlparse.urlparse(url) + return {'name' : (url_p.path.split('/')[-1] or + url_p.query.split('=', 1)[::-1][0].split('&', 1)[0] or + url_p.netloc.split('.', 1)[0]), + 'size' : 0, + 'status': 3 if url else 8, + 'url' : url} + + + def init(self): + """ + Initialize the plugin (in addition to `__init__`) + """ + pass + + + def setup(self): + """ + Setup for enviroment and other things, called before downloading (possibly more than one time) + """ + pass + + + def _setup(self): + if self.account: + self.req = self.pyload.requestFactory.getRequest(self.__name__, self.user) + self.chunk_limit = -1 #: -1 for unlimited + self.resume_download = True + self.premium = self.account.is_premium(self.user) + else: + self.req = self.pyload.requestFactory.getRequest(self.__name__) + self.chunk_limit = 1 + self.resume_download = False + self.premium = False + + + def load_account(self): + if self.req: + self.req.close() + + if not self.account: + self.account = self.pyload.accountManager.getAccountPlugin(self.__name__) + + if self.account: + if not self.user: + self.user = self.account.select()[0] + + if not self.user or not self.account.is_logged(self.user, True): + self.account = False + + + def preprocessing(self, thread): + """ + Handles important things to do before starting + """ + self.thread = thread + + if self.retry_free: + self.account = False + else: + self.load_account() #@TODO: Move to PluginThread in 0.4.10 + self.retry_free = False + + self._setup() + self.setup() + + self.pyload.hookManager.downloadPreparing(self.pyfile) #@TODO: Recheck in 0.4.10 + + if self.pyfile.abort: + self.abort() + + self.pyfile.setStatus("starting") + self.log_debug("PROCESS URL " + self.pyfile.url, "PLUGIN VERSION %s" % self.__version__) + + return self.process(self.pyfile) + + + def process(self, pyfile): + """ + The 'main' method of every plugin, you **have to** overwrite it + """ + raise NotImplementedError + + + def set_reconnect(self, reconnect): + reconnect = bool(reconnect) + + self.log_info(_("RECONNECT ") + ("enabled" if reconnect else "disabled")) + self.log_debug("Previous wantReconnect: %s" % self.wantReconnect) + + self.wantReconnect = reconnect + + + def set_wait(self, seconds, reconnect=None): + """ + Set a specific wait time later used with `wait` + + :param seconds: wait time in seconds + :param reconnect: True if a reconnect would avoid wait time + """ + wait_time = max(int(seconds), 1) + wait_until = time.time() + wait_time + 1 + + self.log_info(_("WAIT %d seconds") % wait_time) + self.log_debug("Previous waitUntil: %f" % self.pyfile.waitUntil) + + self.pyfile.waitUntil = wait_until + + if reconnect is not None: + self.set_reconnect(reconnect) + + + def wait(self, seconds=None, reconnect=None): + """ + Waits the time previously set + """ + pyfile = self.pyfile + + if seconds is not None: + self.set_wait(seconds) + + if reconnect is not None: + self.set_reconnect(reconnect) + + self.waiting = True + + status = pyfile.status #@NOTE: Remove in 0.4.10 + pyfile.setStatus("waiting") + + if not self.wantReconnect or self.account: + if self.account: + self.log_warning("Ignore reconnection due logged account") + + while pyfile.waitUntil > time.time(): + if pyfile.abort: + self.abort() + + time.sleep(2) + + else: + while pyfile.waitUntil > time.time(): + if pyfile.abort: + self.abort() + + if self.thread.m.reconnecting.isSet(): + self.waiting = False + self.wantReconnect = False + raise Reconnect + + self.thread.m.reconnecting.wait(2) + time.sleep(2) + + self.waiting = False + pyfile.status = status #@NOTE: Remove in 0.4.10 + + + def skip(self, reason=""): + """ + Skip and give reason + """ + raise Skip(encode(reason)) #@TODO: Remove `encode` in 0.4.10 + + + def abort(self, reason=""): + """ + Abort and give reason + """ + #@TODO: Remove in 0.4.10 + if reason: + self.pyfile.error = encode(reason) + + raise Abort + + + def offline(self, reason=""): + """ + Fail and indicate file is offline + """ + #@TODO: Remove in 0.4.10 + if reason: + self.pyfile.error = encode(reason) + + raise Fail("offline") + + + def temp_offline(self, reason=""): + """ + Fail and indicates file ist temporary offline, the core may take consequences + """ + #@TODO: Remove in 0.4.10 + if reason: + self.pyfile.error = encode(reason) + + raise Fail("temp. offline") + + + def retry(self, max_tries=5, wait_time=1, reason=""): + """ + Retries and begin again from the beginning + + :param max_tries: number of maximum retries + :param wait_time: time to wait in seconds + :param reason: reason for retrying, will be passed to fail if max_tries reached + """ + id = inspect.currentframe().f_back.f_lineno + if id not in self.retries: + self.retries[id] = 0 + + if 0 < max_tries <= self.retries[id]: + self.fail(reason or _("Max retries reached")) + + self.wait(wait_time, False) + + self.retries[id] += 1 + raise Retry(encode(reason)) #@TODO: Remove `encode` in 0.4.10 + + + def restart(self, reason=None, nopremium=False): + if not reason: + reason = _("Fallback to free download") if nopremium else _("Restart") + + if nopremium: + if self.premium: + self.retry_free = True + else: + self.fail("%s | %s" % (reason, _("Download was already free"))) + + raise Retry(encode(reason)) #@TODO: Remove `encode` in 0.4.10 + + + def fixurl(self, url): + url = _fixurl(url) + + if not urlparse.urlparse(url).scheme: + url_p = urlparse.urlparse(self.pyfile.url) + baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) + url = urlparse.urljoin(baseurl, url) + + return url + + + def download(self, url, get={}, post={}, ref=True, cookies=True, disposition=True): + """ + Downloads the content at url to download folder + + :param url: + :param get: + :param post: + :param ref: + :param cookies: + :param disposition: if True and server provides content-disposition header\ + the filename will be changed if needed + :return: The location where the file was saved + """ + if self.pyfile.abort: + self.abort() + + url = self.fixurl(url) + + if not url or not isinstance(url, basestring): + self.fail(_("No url given")) + + if self.pyload.debug: + self.log_debug("DOWNLOAD URL " + url, + *["%s=%s" % (key, val) for key, val in locals().items() if key not in ("self", "url")]) + + name = _fixurl(self.pyfile.name) + self.pyfile.name = urlparse.urlparse(name).path.split('/')[-1] or name + + self.captcha.correct() + self.check_for_same_files() + + self.pyfile.setStatus("downloading") + + download_folder = self.pyload.config.get("general", "download_folder") + download_location = fs_join(download_folder, self.pyfile.package().folder) + + if not exists(download_location): + try: + os.makedirs(download_location) + except Exception, e: + self.fail(e) + + self.set_permissions(download_location) + + location = fs_decode(download_location) + filename = os.path.join(location, safe_filename(self.pyfile.name)) #@TODO: Move `safe_filename` check to HTTPDownload in 0.4.10 + + self.pyload.hookManager.dispatchEvent("download_start", self.pyfile, url, filename) + + if self.pyfile.abort: + self.abort() + + try: + newname = self.req.httpDownload(url, filename, get=get, post=post, ref=ref, cookies=cookies, + chunks=self.get_chunk_count(), resume=self.resume_download, + progressNotify=self.pyfile.setProgress, disposition=disposition) + finally: + self.pyfile.size = self.req.size + + #@TODO: Recheck in 0.4.10 + if disposition and newname: + finalname = urlparse.urlparse(newname).path.split('/')[-1].split(' filename*=')[0] + + if finalname != newname != self.pyfile.name: + try: + os.rename(fs_join(location, newname), fs_join(location, finalname)) + + except OSError, e: + self.log_warning(_("Error renaming `%s` to `%s`") % (newname, finalname), e) + finalname = newname + + self.log_info(_("`%s` saved as `%s`") % (self.pyfile.name, finalname)) + self.pyfile.name = finalname + filename = os.path.join(location, finalname) + + self.set_permissions(fs_encode(filename)) + + self.last_download = filename + + return self.last_download + + + def check_download(self, rules, delete=False, file_size=0, size_tolerance=1024, read_size=1048576): + """ + Checks the content of the last downloaded file, re match is saved to `lastCheck` + + :param rules: dict with names and rules to match (compiled regexp or strings) + :param delete: delete if matched + :param file_size: expected file size + :param size_tolerance: size check tolerance + :param read_size: amount of bytes to read from files + :return: dictionary key of the first rule that matched + """ + do_delete = False + last_download = fs_encode(self.last_download) + + if not self.last_download or not exists(last_download): + self.last_download = "" + self.fail(self.pyfile.error or _("No file downloaded")) + + try: + download_size = os.stat(last_download).st_size + + if download_size < 1: + do_delete = True + self.fail(_("Empty file")) + + elif file_size > 0: + diff = abs(file_size - download_size) + + if diff > size_tolerance: + do_delete = True + self.fail(_("File size mismatch | Expected file size: %s | Downloaded file size: %s") + % (file_size, download_size)) + + elif diff != 0: + self.log_warning(_("File size is not equal to expected size")) + + with open(last_download, "rb") as f: + content = f.read(read_size) + + #: Produces encoding errors, better log to other file in the future? + # self.log_debug("Content: %s" % content) + for name, rule in rules.items(): + if isinstance(rule, basestring): + if rule in content: + do_delete = True + return name + + elif hasattr(rule, "search"): + m = rule.search(content) + if m: + do_delete = True + self.last_check = m + return name + finally: + if delete and do_delete: + try: + os.remove(last_download) + + except OSError, e: + self.log_warning(_("Error removing: %s") % last_download, e) + if self.pyload.debug: + traceback.print_exc() + + else: + self.last_download = "" + self.log_info(_("File deleted")) + + + def direct_link(self, url, follow_location=None): + link = "" + + if follow_location is None: + redirect = 1 + + elif type(follow_location) is int: + redirect = max(follow_location, 1) + + else: + redirect = self.get_config("maxredirs", 10, "UserAgentSwitcher") + + for i in xrange(redirect): + try: + self.log_debug("Redirect #%d to: %s" % (i, url)) + header = self.load(url, just_header=True) + + except Exception: #: Bad bad bad... rewrite this part in 0.4.10 + res = self.load(url, + just_header=True, + req=self.pyload.requestFactory.getRequest()) + + header = {'code': req.code} + for line in res.splitlines(): + line = line.strip() + if not line or ":" not in line: + continue + + key, none, value = line.partition(":") + key = key.lower().strip() + value = value.strip() + + if key in header: + if type(header[key]) is list: + header[key].append(value) + else: + header[key] = [header[key], value] + else: + header[key] = value + + if 'content-disposition' in header: + link = url + + elif 'location' in header and header['location']: + location = header['location'] + + if not urlparse.urlparse(location).scheme: + url_p = urlparse.urlparse(url) + baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) + location = urlparse.urljoin(baseurl, location) + + if 'code' in header and header['code'] == 302: + link = location + + if follow_location: + url = location + continue + + else: + extension = os.path.splitext(urlparse.urlparse(url).path.split('/')[-1])[-1] + + if 'content-type' in header and header['content-type']: + mimetype = header['content-type'].split(';')[0].strip() + + elif extension: + mimetype = mimetypes.guess_type(extension, False)[0] or "application/octet-stream" + + else: + mimetype = "" + + if mimetype and (link or 'html' not in mimetype): + link = url + else: + link = "" + + break + + else: + try: + self.log_error(_("Too many redirects")) + except Exception: + pass + + return link + + + def parse_html_form(self, attr_str="", input_names={}): + return parse_html_form(attr_str, self.html, input_names) + + + def check_traffic_left(self): + if not self.account: + return True + + traffic = self.account.get_data(self.user, True)['trafficleft'] + + if traffic is None: + return False + elif traffic == -1: + return True + else: + size = self.pyfile.size / 1024 + self.log_info(_("Filesize: %s KiB, Traffic left for user %s: %s KiB") % (size, self.user, traffic)) + return size <= traffic + + + def get_password(self): + """ + Get the password the user provided in the package + """ + return self.pyfile.package().password or "" + + + #: Deprecated method, use `check_for_same_files` instead (Remove in 0.4.10) + def checkForSameFiles(self, *args, **kwargs): + return self.check_for_same_files(*args, **kwargs) + + + def check_for_same_files(self, starting=False): + """ + Checks if same file was/is downloaded within same package + + :param starting: indicates that the current download is going to start + :raises Skip: + """ + pack = self.pyfile.package() + + for pyfile in self.pyload.files.cache.values(): + if pyfile != self.pyfile and pyfile.name is self.pyfile.name and pyfile.package().folder is pack.folder: + if pyfile.status in (0, 12): #: Finished or downloading + self.skip(pyfile.pluginname) + elif pyfile.status in (5, 7) and starting: #: A download is waiting/starting and was appenrently started before + self.skip(pyfile.pluginname) + + download_folder = self.pyload.config.get("general", "download_folder") + location = fs_join(download_folder, pack.folder, self.pyfile.name) + + if starting and self.pyload.config.get("download", "skip_existing") and exists(location): + size = os.stat(location).st_size + if size >= self.pyfile.size: + self.skip("File exists") + + pyfile = self.pyload.db.findDuplicates(self.pyfile.id, self.pyfile.package().folder, self.pyfile.name) + if pyfile: + if exists(location): + self.skip(pyfile[0]) + + self.log_debug("File %s not skipped, because it does not exists." % self.pyfile.name) diff --git a/module/plugins/internal/MultiCrypter.py b/module/plugins/internal/MultiCrypter.py new file mode 100644 index 000000000..ca7b03941 --- /dev/null +++ b/module/plugins/internal/MultiCrypter.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.SimpleCrypter import SimpleCrypter + + +class MultiCrypter(SimpleCrypter): + __name__ = "MultiCrypter" + __type__ = "hoster" + __version__ = "0.02" + __status__ = "testing" + + __pattern__ = r'^unmatchable$' + __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), + ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] + + __description__ = """Multi decrypter plugin""" + __license__ = "GPLv3" + __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + + + def init(self): + self.CRYPTER_NAME = self.pyload.pluginManager.crypterPlugins[self.__name__]['name'] + + + def _log(self, level, plugintype, pluginname, messages): + return super(MultiCrypter, self)._log(level, + plugintype, + pluginname, + (self.CRYPTER_NAME,) + messages) diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py index 01ff4b07d..42a1985b5 100644 --- a/module/plugins/internal/MultiHook.py +++ b/module/plugins/internal/MultiHook.py @@ -4,14 +4,15 @@ import re import time import traceback -from module.plugins.Hook import Hook +from module.plugins.internal.Hook import Hook from module.utils import decode, remove_chars class MultiHook(Hook): __name__ = "MultiHook" __type__ = "hook" - __version__ = "0.45" + __version__ = "0.54" + __status__ = "testing" __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"), ("pluginlist" , "str" , "Plugin list (comma separated)", "" ), @@ -54,9 +55,7 @@ class MultiHook(Hook): (r'^0' , "zero" )] - def setup(self): - self.info = {} #@TODO: Remove in 0.4.10 - + def init(self): self.plugins = [] self.supported = [] self.new_supported = [] @@ -67,76 +66,58 @@ class MultiHook(Hook): self.pluginname = None self.plugintype = None - self.initPlugin() + self.init_plugin() - def initPlugin(self): + def init_plugin(self): self.pluginname = self.__name__.rsplit("Hook", 1)[0] - plugin, self.plugintype = self.core.pluginManager.findPlugin(self.pluginname) + plugin, self.plugintype = self.pyload.pluginManager.findPlugin(self.pluginname) if plugin: - self.pluginmodule = self.core.pluginManager.loadModule(self.plugintype, self.pluginname) + self.pluginmodule = self.pyload.pluginManager.loadModule(self.plugintype, self.pluginname) self.pluginclass = getattr(self.pluginmodule, self.pluginname) else: - self.logWarning("Hook plugin will be deactivated due missing plugin reference") - self.setConfig('activated', False) + self.log_warning(_("Hook plugin will be deactivated due missing plugin reference")) + self.set_config('activated', False) - def loadAccount(self): - self.account = self.core.accountManager.getAccountPlugin(self.pluginname) + def load_account(self): + self.account = self.pyload.accountManager.getAccountPlugin(self.pluginname) - if self.account and not self.account.canUse(): - self.account = None + if self.account and not self.account.select()[0]: + self.account = False if not self.account and hasattr(self.pluginclass, "LOGIN_ACCOUNT") and self.pluginclass.LOGIN_ACCOUNT: - self.logWarning("Hook plugin will be deactivated due missing account reference") - self.setConfig('activated', False) - + self.log_warning(_("Hook plugin will be deactivated due missing account reference")) + self.set_config('activated', False) - def getURL(self, *args, **kwargs): #@TODO: Remove in 0.4.10 - """ see HTTPRequest for argument list """ - h = pyreq.getHTTPRequest(timeout=120) - try: - if not 'decode' in kwargs: - kwargs['decode'] = True - rep = h.load(*args, **kwargs) - finally: - h.close() - return rep + def activate(self): + self.init_periodical(threaded=True) - def getConfig(self, option, default=''): #@TODO: Remove in 0.4.10 - """getConfig with default value - sublass may not implements all config options""" - try: - return self.getConf(option) - - except KeyError: - return default - - - def pluginsCached(self): + def plugins_cached(self): if self.plugins: return self.plugins - for _i in xrange(2): + for _i in xrange(5): try: - pluginset = self._pluginSet(self.getHosters()) + pluginset = self._plugin_set(self.get_hosters()) break except Exception, e: - self.logDebug(e, "Waiting 1 minute and retry") + self.log_warning(e, _("Waiting 1 minute and retry")) time.sleep(60) else: - self.logWarning(_("Fallback to default reload interval due plugin parse error")) + self.log_error(_("No hoster list retrieved")) self.interval = self.MIN_RELOAD_INTERVAL return list() try: - configmode = self.getConfig("pluginmode", 'all') + configmode = self.get_config('pluginmode', 'all') if configmode in ("listed", "unlisted"): - pluginlist = self.getConfig("pluginlist", '').replace('|', ',').replace(';', ',').split(',') - configset = self._pluginSet(pluginlist) + pluginlist = self.get_config('pluginlist', '').replace('|', ',').replace(';', ',').split(',') + configset = self._plugin_set(pluginlist) if configmode == "listed": pluginset &= configset @@ -144,14 +125,14 @@ class MultiHook(Hook): pluginset -= configset except Exception, e: - self.logError(e) + self.log_error(e) self.plugins = list(pluginset) return self.plugins - def _pluginSet(self, plugins): + def _plugin_set(self, plugins): regexp = re.compile(r'^[\w\-.^_]{3,63}\.[a-zA-Z]{2,}$', re.U) plugins = [decode(p.strip()).lower() for p in plugins if regexp.match(p.strip())] @@ -163,39 +144,28 @@ class MultiHook(Hook): return set(plugins) - def getHosters(self): - """Load list of supported hoster + def get_hosters(self): + """ + Load list of supported hoster :return: List of domain names """ raise NotImplementedError - #: Threaded _periodical, remove in 0.4.10 and use built-in flag for that - def _periodical(self): - try: - if self.isActivated(): - self.periodical() - - except Exception, e: - self.core.log.error(_("Error executing hooks: %s") % str(e)) - if self.core.debug: - traceback.print_exc() - - self.cb = self.core.scheduler.addJob(self.interval, self._periodical) - - def periodical(self): - """reload plugin list periodically""" - self.loadAccount() + """ + Reload plugin list periodically + """ + self.load_account() - if self.getConfig("reload", True): - self.interval = max(self.getConfig("reloadinterval", 12) * 60 * 60, self.MIN_RELOAD_INTERVAL) + if self.get_config('reload', True): + self.interval = max(self.get_config('reloadinterval', 12) * 60 * 60, self.MIN_RELOAD_INTERVAL) else: - self.core.scheduler.removeJob(self.cb) + self.pyload.scheduler.removeJob(self.cb) self.cb = None - self.logInfo(_("Reloading supported %s list") % self.plugintype) + self.log_info(_("Reloading supported %s list") % self.plugintype) old_supported = self.supported @@ -203,27 +173,27 @@ class MultiHook(Hook): self.new_supported = [] self.plugins = [] - self.overridePlugins() + self.override_plugins() old_supported = [plugin for plugin in old_supported if plugin not in self.supported] if old_supported: - self.logDebug("Unload: %s" % ", ".join(old_supported)) + self.log_debug("Unload: %s" % ", ".join(old_supported)) for plugin in old_supported: - self.unloadPlugin(plugin) + self.unload_plugin(plugin) - def overridePlugins(self): + def override_plugins(self): excludedList = [] if self.plugintype == "hoster": - pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys()) - accountList = [account.type.lower() for account in self.core.api.getAccounts(False) if account.valid and account.premium] + pluginMap = dict((name.lower(), name) for name in self.pyload.pluginManager.hosterPlugins.keys()) + accountList = [account.type.lower() for account in self.pyload.api.getAccounts(False) if account.valid and account.premium] else: pluginMap = {} - accountList = [name[::-1].replace("Folder"[::-1], "", 1).lower()[::-1] for name in self.core.pluginManager.crypterPlugins.iterkeys()] + accountList = [name[::-1].replace("Folder"[::-1], "", 1).lower()[::-1] for name in self.pyload.pluginManager.crypterPlugins.keys()] - for plugin in self.pluginsCached(): + for plugin in self.plugins_cached(): name = remove_chars(plugin, "-.") if name in accountList: @@ -235,39 +205,39 @@ class MultiHook(Hook): self.new_supported.append(plugin) if not self.supported and not self.new_supported: - self.logError(_("No %s loaded") % self.plugintype) + self.log_error(_("No %s loaded") % self.plugintype) return - # inject plugin plugin - self.logDebug("Overwritten %ss: %s" % (self.plugintype, ", ".join(sorted(self.supported)))) + #: Inject plugin plugin + self.log_debug("Overwritten %ss: %s" % (self.plugintype, ", ".join(sorted(self.supported)))) for plugin in self.supported: - hdict = self.core.pluginManager.plugins[self.plugintype][plugin] + hdict = self.pyload.pluginManager.plugins[self.plugintype][plugin] hdict['new_module'] = self.pluginmodule hdict['new_name'] = self.pluginname if excludedList: - self.logInfo(_("%ss not overwritten: %s") % (self.plugintype.capitalize(), ", ".join(sorted(excludedList)))) + self.log_info(_("%ss not overwritten: %s") % (self.plugintype.capitalize(), ", ".join(sorted(excludedList)))) if self.new_supported: plugins = sorted(self.new_supported) - self.logDebug("New %ss: %s" % (self.plugintype, ", ".join(plugins))) + self.log_debug("New %ss: %s" % (self.plugintype, ", ".join(plugins))) - # create new regexp + #: Create new regexp regexp = r'.*(?P<DOMAIN>%s).*' % "|".join(x.replace('.', '\.') for x in plugins) - if hasattr(self.pluginclass, "__pattern__") and isinstance(self.pluginclass.__pattern__, basestring) and '://' in self.pluginclass.__pattern__: + if hasattr(self.pluginclass, "__pattern__") and isinstance(self.pluginclass.__pattern__, basestring) and "://" in self.pluginclass.__pattern__: regexp = r'%s|%s' % (self.pluginclass.__pattern__, regexp) - self.logDebug("Regexp: %s" % regexp) + self.log_debug("Regexp: %s" % regexp) - hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname] + hdict = self.pyload.pluginManager.plugins[self.plugintype][self.pluginname] hdict['pattern'] = regexp hdict['re'] = re.compile(regexp) - def unloadPlugin(self, plugin): - hdict = self.core.pluginManager.plugins[self.plugintype][plugin] + def unload_plugin(self, plugin): + hdict = self.pyload.pluginManager.plugins[self.plugintype][plugin] if "module" in hdict: hdict.pop('module', None) @@ -276,13 +246,15 @@ class MultiHook(Hook): hdict.pop('new_name', None) - def unload(self): - """Remove override for all plugins. Scheduler job is removed by hookmanager""" + def deactivate(self): + """ + Remove override for all plugins. Scheduler job is removed by hookmanager + """ for plugin in self.supported: - self.unloadPlugin(plugin) + self.unload_plugin(plugin) - # reset pattern - hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname] + #: Reset pattern + hdict = self.pyload.pluginManager.plugins[self.plugintype][self.pluginname] hdict['pattern'] = getattr(self.pluginclass, "__pattern__", r'^unmatchable$') hdict['re'] = re.compile(hdict['pattern']) diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py index ff4414034..c0c928a45 100644 --- a/module/plugins/internal/MultiHoster.py +++ b/module/plugins/internal/MultiHoster.py @@ -2,14 +2,15 @@ import re -from module.plugins.Plugin import Fail, Retry -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies +from module.plugins.internal.Plugin import Fail, encode +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookie, set_cookies class MultiHoster(SimpleHoster): __name__ = "MultiHoster" __type__ = "hoster" - __version__ = "0.40" + __version__ = "0.50" + __status__ = "testing" __pattern__ = r'^unmatchable$' __config__ = [("use_premium" , "bool", "Use premium account if available" , True), @@ -20,76 +21,90 @@ class MultiHoster(SimpleHoster): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + HOSTER_NAME = None + + LEECH_HOSTER = False LOGIN_ACCOUNT = True - def setup(self): - self.chunkLimit = 1 - self.multiDL = bool(self.account) - self.resumeDownload = self.premium + def init(self): + self.HOSTER_NAME = self.pyload.pluginManager.hosterPlugins[self.__name__]['name'] - def prepare(self): - self.info = {} - self.html = "" - self.link = "" #@TODO: Move to hoster class in 0.4.10 - self.directDL = False #@TODO: Move to hoster class in 0.4.10 + def _log(self, level, plugintype, pluginname, messages): + return super(MultiHoster, self)._log(level, + plugintype, + pluginname, + (self.HOSTER_NAME,) + messages) - if not self.getConfig('use_premium', True): - self.retryFree() - if self.LOGIN_ACCOUNT and not self.account: - self.fail(_("Required account not found")) + def setup(self): + self.chunk_limit = 1 + self.multiDL = bool(self.account) + self.resume_download = self.premium + - self.req.setOption("timeout", 120) + def prepare(self): + #@TODO: Recheck in 0.4.10 + plugin = self.pyload.pluginManager.hosterPlugins[self.__name__] + name = plugin['name'] + module = plugin['module'] + klass = getattr(module, name) - if isinstance(self.COOKIES, list): - set_cookies(self.req.cj, self.COOKIES) + self.get_info = klass.get_info if self.DIRECT_LINK is None: - self.directDL = self.__pattern__ != r'^unmatchable$' and re.match(self.__pattern__, self.pyfile.url) + direct_dl = self.__pattern__ != r'^unmatchable$' and re.match(self.__pattern__, self.pyfile.url) else: - self.directDL = self.DIRECT_LINK + direct_dl = self.DIRECT_LINK + + super(MultiHoster, self).prepare() - self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS) + self.direct_dl = direct_dl def process(self, pyfile): try: self.prepare() + self.check_info() #@TODO: Remove in 0.4.10 + + if self.direct_dl: + self.log_info(_("Looking for direct download link...")) + self.handle_direct(pyfile) - if self.directDL: - self.checkInfo() - self.logDebug("Looking for direct download link...") - self.handleDirect(pyfile) + if self.link or was_downloaded(): + self.log_info(_("Direct download link detected")) + else: + self.log_info(_("Direct download link not found")) - if not self.link and not self.lastDownload: + if not self.link and not self.last_download: self.preload() - self.checkErrors() - self.checkStatus(getinfo=False) + self.check_errors() + self.check_status(getinfo=False) - if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): - self.logDebug("Handled as premium download") - self.handlePremium(pyfile) + if self.premium and (not self.CHECK_TRAFFIC or self.check_traffic_left()): + self.log_info(_("Processing as premium download...")) + self.handle_premium(pyfile) - elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): - self.logDebug("Handled as free download") - self.handleFree(pyfile) + elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.check_traffic_left()): + self.log_info(_("Processing as free download...")) + self.handle_free(pyfile) - self.downloadLink(self.link, True) - self.checkFile() + if not self.last_download: + self.log_info(_("Downloading file...")) + self.download(self.link, disposition=self.DISPOSITION) - except Fail, e: #@TODO: Move to PluginThread in 0.4.10 - err = str(e) #@TODO: Recheck in 0.4.10 + self.check_file() + except Fail, e: #@TODO: Move to PluginThread in 0.4.10 if self.premium: - self.logWarning(_("Premium download failed")) - self.retryFree() + self.log_warning(_("Premium download failed")) + self.restart(nopremium=True) - elif self.getConfig("revertfailed", True) \ - and "new_module" in self.core.pluginManager.hosterPlugins[self.__name__]: - hdict = self.core.pluginManager.hosterPlugins[self.__name__] + elif self.get_config("revertfailed", True) \ + and "new_module" in self.pyload.pluginManager.hosterPlugins[self.__name__]: + hdict = self.pyload.pluginManager.hosterPlugins[self.__name__] tmp_module = hdict['new_module'] tmp_name = hdict['new_name'] @@ -101,17 +116,17 @@ class MultiHoster(SimpleHoster): hdict['new_module'] = tmp_module hdict['new_name'] = tmp_name - raise Retry(_("Revert to original hoster plugin")) + self.restart(_("Revert to original hoster plugin")) else: - raise Fail(err) + raise Fail(encode(e)) #@TODO: Remove `encode` in 0.4.10 - def handlePremium(self, pyfile): - return self.handleFree(pyfile) + def handle_premium(self, pyfile): + return self.handle_free(pyfile) - def handleFree(self, pyfile): + def handle_free(self, pyfile): if self.premium: raise NotImplementedError else: diff --git a/module/plugins/captcha/OCR.py b/module/plugins/internal/OCR.py index 1874ba07d..b24b3058b 100644 --- a/module/plugins/captcha/OCR.py +++ b/module/plugins/internal/OCR.py @@ -11,33 +11,54 @@ except ImportError: import logging import os import subprocess -#import tempfile +# import tempfile +import traceback -from module.utils import save_join +from module.plugins.internal.Plugin import Plugin +from module.utils import save_join as fs_join -class OCR(object): +class OCR(Plugin): __name__ = "OCR" __type__ = "ocr" - __version__ = "0.11" + __version__ = "0.19" + __status__ = "testing" __description__ = """OCR base plugin""" __license__ = "GPLv3" __authors__ = [("pyLoad Team", "admin@pyload.org")] - def __init__(self): - self.logger = logging.getLogger("log") + def __init__(self, plugin): + self._init(plugin.pyload) + self.plugin = plugin + self.init() + + + def init(self): + """ + Initialize additional data structures + """ + pass + + + def _log(self, level, plugintype, pluginname, messages): + return self.plugin._log(level, + plugintype, + self.plugin.__name__, + (self.__name__,) + messages) def load_image(self, image): self.image = Image.open(image) self.pixels = self.image.load() - self.result_captcha = '' + self.result_captcha = "" - def unload(self): - """delete all tmp images""" + def deactivate(self): + """ + Delete all tmp images + """ pass @@ -46,31 +67,32 @@ class OCR(object): def run(self, command): - """Run a command""" - - popen = subprocess.Popen(command, bufsize = -1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + """ + Run a command + """ + popen = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) popen.wait() - output = popen.stdout.read() +" | "+ popen.stderr.read() + output = popen.stdout.read() + " | " + popen.stderr.read() popen.stdout.close() popen.stderr.close() - self.logger.debug("Tesseract ReturnCode %s Output: %s" % (popen.returncode, output)) + self.pyload.log_debug("Tesseract ReturnCode " + popen.returncode, "Output: " + output) - def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True): - #tmpTif = tempfile.NamedTemporaryFile(suffix=".tif") + def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True, pagesegmode=None): + # tmpTif = tempfile.NamedTemporaryFile(suffix=".tif") try: - tmpTif = open(save_join("tmp", "tmpTif_%s.tif" % self.__name__), "wb") + tmpTif = open(fs_join("tmp", "tmpTif_%s.tif" % self.__name__), "wb") tmpTif.close() - #tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt") - tmpTxt = open(save_join("tmp", "tmpTxt_%s.txt" % self.__name__), "wb") + # tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt") + tmpTxt = open(fs_join("tmp", "tmpTxt_%s.txt" % self.__name__), "wb") tmpTxt.close() except IOError, e: - self.logError(e) + self.log_error(e) return - self.logger.debug("save tiff") + self.pyload.log_debug("Saving tiff...") self.image.save(tmpTif.name, 'TIFF') if os.name == "nt": @@ -78,11 +100,14 @@ class OCR(object): else: tessparams = ["tesseract"] - tessparams.extend( [os.path.abspath(tmpTif.name), os.path.abspath(tmpTxt.name).replace(".txt", "")] ) + tessparams.extend([os.path.abspath(tmpTif.name), os.path.abspath(tmpTxt.name).replace(".txt", "")]) + + if pagesegmode: + tessparams.extend(["-psm", str(pagesegmode)]) if subset and (digits or lowercase or uppercase): - #tmpSub = tempfile.NamedTemporaryFile(suffix=".subset") - with open(save_join("tmp", "tmpSub_%s.subset" % self.__name__), "wb") as tmpSub: + # tmpSub = tempfile.NamedTemporaryFile(suffix=".subset") + with open(fs_join("tmp", "tmpSub_%s.subset" % self.__name__), "wb") as tmpSub: tmpSub.write("tessedit_char_whitelist ") if digits: @@ -96,9 +121,9 @@ class OCR(object): tessparams.append("nobatch") tessparams.append(os.path.abspath(tmpSub.name)) - self.logger.debug("run tesseract") + self.pyload.log_debug("Running tesseract...") self.run(tessparams) - self.logger.debug("read txt") + self.pyload.log_debug("Reading txt...") try: with open(tmpTxt.name, 'r') as f: @@ -106,17 +131,19 @@ class OCR(object): except Exception: self.result_captcha = "" - self.logger.debug(self.result_captcha) + self.pyload.log_info(_("OCR result: ") + self.result_captcha) try: os.remove(tmpTif.name) os.remove(tmpTxt.name) if subset and (digits or lowercase or uppercase): os.remove(tmpSub.name) - except Exception: - pass + except OSError, e: + self.log_warning(e) + if self.pyload.debug: + traceback.print_exc() - def get_captcha(self, name): + def recognize(self, name): raise NotImplementedError @@ -147,15 +174,15 @@ class OCR(object): for y in xrange(h): if pixels[x, y] == 255: continue - # No point in processing white pixels since we only want to remove black pixel + #: No point in processing white pixels since we only want to remove black pixel count = 0 try: - if pixels[x-1, y-1] != 255: + if pixels[x - 1, y - 1] != 255: count += 1 - if pixels[x-1, y] != 255: + if pixels[x - 1, y] != 255: count += 1 - if pixels[x-1, y + 1] != 255: + if pixels[x - 1, y + 1] != 255: count += 1 if pixels[x, y + 1] != 255: count += 1 @@ -163,19 +190,19 @@ class OCR(object): count += 1 if pixels[x + 1, y] != 255: count += 1 - if pixels[x + 1, y-1] != 255: + if pixels[x + 1, y - 1] != 255: count += 1 - if pixels[x, y-1] != 255: + if pixels[x, y - 1] != 255: count += 1 except Exception: pass - # not enough neighbors are dark pixels so mark this pixel - # to be changed to white + #: Not enough neighbors are dark pixels so mark this pixel + #: To be changed to white if count < allowed: pixels[x, y] = 1 - # second pass: this time set all 1's to 255 (white) + #: Second pass: this time set all 1's to 255 (white) for x in xrange(w): for y in xrange(h): if pixels[x, y] == 1: @@ -185,8 +212,9 @@ class OCR(object): def derotate_by_average(self): - """rotate by checking each angle and guess most suitable""" - + """ + Rotate by checking each angle and guess most suitable + """ w, h = self.image.size pixels = self.pixels @@ -211,7 +239,6 @@ class OCR(object): if pixels[x, y] == 0: pixels[x, y] = 255 - count = {} for x in xrange(w): @@ -240,7 +267,7 @@ class OCR(object): hkey = 0 hvalue = 0 - for key, value in highest.iteritems(): + for key, value in highest.items(): if value > hvalue: hkey = key hvalue = value @@ -305,9 +332,9 @@ class OCR(object): else: result = self.result_captcha - for key, item in values.iteritems(): + for key, item in values.items(): - if key.__class__ == str: + if key.__class__ is str: result = result.replace(key, item) else: for expr in key: diff --git a/module/plugins/internal/Plugin.py b/module/plugins/internal/Plugin.py new file mode 100644 index 000000000..7b45c40a8 --- /dev/null +++ b/module/plugins/internal/Plugin.py @@ -0,0 +1,399 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement + +import datetime +import inspect +import os +import re +import urllib + +if os.name != "nt": + import grp + import pwd + +from module.plugins.Plugin import Abort, Fail, Reconnect, Retry, SkipDownload as Skip #@TODO: Remove in 0.4.10 +from module.utils import fs_encode, fs_decode, html_unescape, save_join as fs_join + + +#@TODO: Move to utils in 0.4.10 +def decode(string, encoding='utf8'): + """ Decode string to unicode with utf8 """ + if type(string) is str: + return string.decode(encoding, "replace") + else: + return string + + +#@TODO: Move to utils in 0.4.10 +def encode(string, encoding='utf8'): + """ Decode string to utf8 """ + if type(string) is unicode: + return string.encode(encoding, "replace") + else: + return string + + +#@TODO: Move to utils in 0.4.10 +def exists(path): + if os.path.exists(path): + if os.name == "nt": + dir, name = os.path.split(path) + return name in os.listdir(dir) + else: + return True + else: + return False + + +#@TODO: Move to utils in 0.4.10 +def fixurl(url): + return html_unescape(urllib.unquote(url.decode('unicode-escape'))).strip().rstrip('/') + + +#@TODO: Move to utils in 0.4.10 +def timestamp(): + return int(time.time() * 1000) + + +def seconds_to_midnight(gmt=0): + now = datetime.datetime.utcnow() + datetime.timedelta(hours=gmt) + + if now.hour == 0 and now.minute < 10: + midnight = now + else: + midnight = now + datetime.timedelta(days=1) + + td = midnight.replace(hour=0, minute=10, second=0, microsecond=0) - now + + if hasattr(td, 'total_seconds'): + res = td.total_seconds() + else: #@NOTE: work-around for python 2.5 and 2.6 missing datetime.timedelta.total_seconds + res = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 + + return int(res) + + +def replace_patterns(string, ruleslist): + for r in ruleslist: + rf, rt = r + string = re.sub(rf, rt, string) + return string + + +#@TODO: Remove in 0.4.10 and fix CookieJar.setCookie +def set_cookie(cj, domain, name, value): + return cj.setCookie(domain, name, encode(value)) + + +def set_cookies(cj, cookies): + for cookie in cookies: + if isinstance(cookie, tuple) and len(cookie) == 3: + set_cookie(cj, *cookie) + + +def parse_html_tag_attr_value(attr_name, tag): + m = re.search(r"%s\s*=\s*([\"']?)((?<=\")[^\"]+|(?<=')[^']+|[^>\s\"'][^>\s]*)\1" % attr_name, tag, re.I) + return m.group(2) if m else None + + +def parse_html_form(attr_str, html, input_names={}): + for form in re.finditer(r"(?P<TAG><form[^>]*%s[^>]*>)(?P<CONTENT>.*?)</?(form|body|html)[^>]*>" % attr_str, + html, re.S | re.I): + inputs = {} + action = parse_html_tag_attr_value("action", form.group('TAG')) + + for inputtag in re.finditer(r'(<(input|textarea)[^>]*>)([^<]*(?=</\2)|)', form.group('CONTENT'), re.S | re.I): + name = parse_html_tag_attr_value("name", inputtag.group(1)) + if name: + value = parse_html_tag_attr_value("value", inputtag.group(1)) + if not value: + inputs[name] = inputtag.group(3) or "" + else: + inputs[name] = value + + if input_names: + #: Check input attributes + for key, val in input_names.items(): + if key in inputs: + if isinstance(val, basestring) and inputs[key] is val: + continue + elif isinstance(val, tuple) and inputs[key] in val: + continue + elif hasattr(val, "search") and re.match(val, inputs[key]): + continue + break #: Attibute value does not match + else: + break #: Attibute name does not match + else: + return action, inputs #: Passed attribute check + else: + #: No attribute check + return action, inputs + + return {}, None #: No matching form found + + +#@TODO: Move to utils in 0.4.10 +def chunks(iterable, size): + it = iter(iterable) + item = list(islice(it, size)) + while item: + yield item + item = list(islice(it, size)) + + +class Plugin(object): + __name__ = "Plugin" + __type__ = "hoster" + __version__ = "0.30" + __status__ = "testing" + + __pattern__ = r'^unmatchable$' + __config__ = [] #: [("name", "type", "desc", "default")] + + __description__ = """Base plugin""" + __license__ = "GPLv3" + __authors__ = [("RaNaN" , "RaNaN@pyload.org" ), + ("spoob" , "spoob@pyload.org" ), + ("mkaay" , "mkaay@mkaay.de" ), + ("Walter Purcaro", "vuolter@gmail.com")] + + + def __init__(self, core): + self._init(core) + self.init() + + + def _init(self, core): + self.pyload = core + self.info = {} #: Provide information in dict here + self.req = None + + + def init(self): + """ + Initialize the plugin (in addition to `__init__`) + """ + pass + + + def _log(self, level, plugintype, pluginname, messages): + log = getattr(self.pyload.log, level) + msg = encode(" | ".join((a if isinstance(a, basestring) else str(a)).strip() for a in messages if a)) + log("%(plugintype)s %(pluginname)s%(id)s: %(msg)s" + % {'plugintype': plugintype.upper(), + 'pluginname': pluginname, + 'id' : ("[%s]" % self.pyfile.id) if hasattr(self, 'pyfile') else "", + 'msg' : msg}) + + + def log_debug(self, *args): + if self.pyload.debug: + return self._log("debug", self.__type__, self.__name__, args) + + + def log_info(self, *args): + return self._log("info", self.__type__, self.__name__, args) + + + def log_warning(self, *args): + return self._log("warning", self.__type__, self.__name__, args) + + + def log_error(self, *args): + return self._log("error", self.__type__, self.__name__, args) + + + def log_critical(self, *args): + return self._log("critical", self.__type__, self.__name__, args) + + + def set_permissions(self, path): + if not os.path.exists(path): + return + + try: + if self.pyload.config.get("permission", "change_file"): + if os.path.isfile(path): + os.chmod(path, int(self.pyload.config.get("permission", "file"), 8)) + + elif os.path.isdir(path): + os.chmod(path, int(self.pyload.config.get("permission", "folder"), 8)) + + except OSError, e: + self.log_warning(_("Setting path mode failed"), e) + + try: + if os.name != "nt" and self.pyload.config.get("permission", "change_dl"): + uid = pwd.getpwnam(self.pyload.config.get("permission", "user"))[2] + gid = grp.getgrnam(self.pyload.config.get("permission", "group"))[2] + os.chown(path, uid, gid) + + except OSError, e: + self.log_warning(_("Setting owner and group failed"), e) + + + def get_chunk_count(self): + if self.chunk_limit <= 0: + return self.pyload.config.get("download", "chunks") + return min(self.pyload.config.get("download", "chunks"), self.chunk_limit) + + + def set_config(self, option, value): + """ + Set config value for current plugin + + :param option: + :param value: + :return: + """ + self.pyload.config.setPlugin(self.__name__, option, value) + + + def get_config(self, option, default="", plugin=None): + """ + Returns config value for current plugin + + :param option: + :return: + """ + try: + return self.pyload.config.getPlugin(plugin or self.__name__, option) + + except KeyError: + self.log_debug("Config option `%s` not found, use default `%s`" % (option, default or None)) #@TODO: Restore to `log_warning` in 0.4.10 + return default + + + def store(self, key, value): + """ + Saves a value persistently to the database + """ + self.pyload.db.setStorage(self.__name__, key, value) + + + def retrieve(self, key, default=None): + """ + Retrieves saved value or dict of all saved entries if key is None + """ + return self.pyload.db.getStorage(self.__name__, key) or default + + + def delete(self, key): + """ + Delete entry in db + """ + self.pyload.db.delStorage(self.__name__, key) + + + def fail(self, reason): + """ + Fail and give reason + """ + raise Fail(encode(reason)) #@TODO: Remove `encode` in 0.4.10 + + + def error(self, reason="", type=_("Parse")): + if not reason: + type = _("Unknown") + + msg = _("%s error") % type.strip().capitalize() if type else _("Error") + msg += (": %s" % reason.strip()) if reason else "" + msg += _(" | Plugin may be out of date") + + raise Fail(encode(msg)) #@TODO: Remove `encode` in 0.4.10 + + + def load(self, url, get={}, post={}, ref=True, cookies=True, just_header=False, decode=True, multipart=False, req=None): + """ + Load content at url and returns it + + :param url: + :param get: + :param post: + :param ref: + :param cookies: + :param just_header: If True only the header will be retrieved and returned as dict + :param decode: Wether to decode the output according to http header, should be True in most cases + :return: Loaded content + """ + if hasattr(self, 'pyfile') and self.pyfile.abort: + self.abort() + + url = fixurl(url) + + if not url or not isinstance(url, basestring): + self.fail(_("No url given")) + + if self.pyload.debug: + self.log_debug("LOAD URL " + url, + *["%s=%s" % (key, val) for key, val in locals().items() if key not in ("self", "url")]) + + if req is None: + req = self.req or self.pyload.requestFactory.getRequest(self.__name__) + + #@TODO: Move to network in 0.4.10 + if isinstance(cookies, list): + set_cookies(req.cj, cookies) + + res = req.load(url, get, post, ref, bool(cookies), just_header, multipart, decode is True) #@TODO: Fix network multipart in 0.4.10 + + #@TODO: Move to network in 0.4.10 + if decode: + res = html_unescape(res) + + #@TODO: Move to network in 0.4.10 + if isinstance(decode, basestring): + res = decode(res, decode) + + if self.pyload.debug: + frame = inspect.currentframe() + framefile = fs_join("tmp", self.__name__, "%s_line%s.dump.html" % (frame.f_back.f_code.co_name, frame.f_back.f_lineno)) + try: + if not exists(os.path.join("tmp", self.__name__)): + os.makedirs(os.path.join("tmp", self.__name__)) + + with open(framefile, "wb") as f: + del frame #: Delete the frame or it wont be cleaned + f.write(encode(res)) + + except IOError, e: + self.log_error(e) + + if just_header: + #: Parse header + header = {'code': req.code} + for line in res.splitlines(): + line = line.strip() + if not line or ":" not in line: + continue + + key, none, value = line.partition(":") + key = key.strip().lower() + value = value.strip() + + if key in header: + if type(header[key]) is list: + header[key].append(value) + else: + header[key] = [header[key], value] + else: + header[key] = value + res = header + + return res + + + def clean(self): + """ + Clean everything and remove references + """ + try: + self.req.close() + except Exception: + pass + + for a in ("pyfile", "thread", "html", "req"): + if hasattr(self, a): + setattr(self, a, None) diff --git a/module/plugins/internal/SevenZip.py b/module/plugins/internal/SevenZip.py index 624f6c939..5811c28de 100644 --- a/module/plugins/internal/SevenZip.py +++ b/module/plugins/internal/SevenZip.py @@ -5,12 +5,13 @@ import re import subprocess from module.plugins.internal.UnRar import ArchiveError, CRCError, PasswordError, UnRar, renice -from module.utils import fs_encode, save_join +from module.utils import fs_encode, save_join as fs_join class SevenZip(UnRar): __name__ = "SevenZip" - __version__ = "0.11" + __version__ = "0.14" + __status__ = "testing" __description__ = """7-Zip extractor plugin""" __license__ = "GPLv3" @@ -18,9 +19,7 @@ class SevenZip(UnRar): ("Walter Purcaro", "vuolter@gmail.com")] - CMD = "7z" - VERSION = "" - + CMD = "7z" EXTENSIONS = [".7z", ".xz", ".zip", ".gz", ".gzip", ".tgz", ".bz2", ".bzip2", ".tbz2", ".tbz", ".tar", ".wim", ".swm", ".lzma", ".rar", ".cab", ".arj", ".z", ".taz", ".cpio", ".rpm", ".deb", ".lzh", ".lha", @@ -37,23 +36,27 @@ class SevenZip(UnRar): @classmethod - def isUsable(cls): - if os.name == "nt": - cls.CMD = os.path.join(pypath, "7z.exe") - p = subprocess.Popen([cls.CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = p.communicate() - else: + def find(cls): + try: + if os.name == "nt": + cls.CMD = os.path.join(pypath, "7z.exe") + p = subprocess.Popen([cls.CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() - m = cls.re_version.search(out) - cls.VERSION = m.group(1) if m else '(version unknown)' + except OSError: + return False + + else: + m = cls.re_version.search(out) + if m is not None: + cls.VERSION = m.group(1) - return True + return True def verify(self, password): - # 7z can't distinguish crc and pw error in test + #: 7z can't distinguish crc and pw error in test p = self.call_cmd("l", "-slt", fs_encode(self.filename)) out, err = p.communicate() @@ -72,7 +75,7 @@ class SevenZip(UnRar): p = self.call_cmd("l", "-slt", fs_encode(self.filename)) out, err = p.communicate() - # check if output or error macthes the 'wrong password'-Regexp + #: Check if output or error macthes the 'wrong password'-Regexp if self.re_wrongpwd.search(out): raise PasswordError @@ -91,7 +94,7 @@ class SevenZip(UnRar): renice(p.pid, self.renice) - # communicate and retrieve stderr + #: Communicate and retrieve stderr self._progress(p) err = p.stderr.read().strip() @@ -102,7 +105,7 @@ class SevenZip(UnRar): elif self.re_wrongcrc.search(err): raise CRCError(err) - else: #: raise error if anything is on stderr + else: #: Raise error if anything is on stderr raise ArchiveError(err) if p.returncode > 1: @@ -126,7 +129,7 @@ class SevenZip(UnRar): result = set() for groups in self.re_filelist.findall(out): f = groups[-1].strip() - result.add(save_join(self.out, f)) + result.add(fs_join(self.out, f)) return list(result) @@ -134,20 +137,20 @@ class SevenZip(UnRar): def call_cmd(self, command, *xargs, **kwargs): args = [] - #overwrite flag + #: Overwrite flag if self.overwrite: args.append("-y") - #set a password - if "password" in kwargs and kwargs["password"]: - args.append("-p%s" % kwargs["password"]) + #: Set a password + if "password" in kwargs and kwargs['password']: + args.append("-p%s" % kwargs['password']) else: args.append("-p-") #@NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue call = [self.CMD, command] + args + list(xargs) - self.manager.logDebug(" ".join(call)) + self.log_debug(" ".join(call)) p = subprocess.Popen(call, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return p diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py index b843a28f0..6a3f91a5b 100644 --- a/module/plugins/internal/SimpleCrypter.py +++ b/module/plugins/internal/SimpleCrypter.py @@ -1,27 +1,26 @@ # -*- coding: utf-8 -*- import re -import urlparse -from module.plugins.Crypter import Crypter -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies +from module.plugins.internal.Crypter import Crypter +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookie, set_cookies from module.utils import fixup, html_unescape class SimpleCrypter(Crypter, SimpleHoster): __name__ = "SimpleCrypter" __type__ = "crypter" - __version__ = "0.46" + __version__ = "0.60" + __status__ = "testing" __pattern__ = r'^unmatchable$' - __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides core.config['general']['folder_per_package'] + __config__ = [("use_subfolder" , "bool", "Save package to subfolder" , True), #: Overrides pyload.config['general']['folder_per_package'] ("subfolder_per_pack", "bool", "Create a subfolder for each package", True)] __description__ = """Simple decrypter plugin""" __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - """ Following patterns should be defined by each crypter: @@ -49,121 +48,93 @@ class SimpleCrypter(Crypter, SimpleHoster): and its loadPage method: - def loadPage(self, page_n): + def load_page(self, page_n): return the html of the page number page_n """ - 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 + DIRECT_LINK = True + LEECH_HOSTER = False #@TODO: Remove in 0.4.10 - def init(self): - account_name = (self.__name__ + ".py").replace("Folder.py", "").replace(".py", "") - account = self.pyfile.m.core.accountManager.getAccountPlugin(account_name) - - if account and account.canUse(): - self.user, data = account.selectAccount() - self.req = account.getAccountRequest(self.user) - self.premium = account.isPremium(self.user) + def _setup(self): + orig_name = self.__name__ + self.__name__ = (orig_name + ".py").replace("Folder.py", "").replace(".py", "") - self.account = account + super(SimpleCrypter, self)._setup() + self.__name__ = orig_name - def prepare(self): - self.pyfile.error = "" #@TODO: Remove in 0.4.10 - self.info = {} - self.html = "" - self.links = [] #@TODO: Move to hoster class in 0.4.10 + #@TODO: Remove in 0.4.10 + def load_account(self): + orig_name = self.__name__ + self.__name__ = (orig_name + ".py").replace("Folder.py", "").replace(".py", "") - if self.LOGIN_PREMIUM and not self.premium: - self.fail(_("Required premium account not found")) + super(SimpleCrypter, self).load_account() - if self.LOGIN_ACCOUNT and not self.account: - self.fail(_("Required account not found")) + self.__name__ = orig_name - self.req.setOption("timeout", 120) - if isinstance(self.COOKIES, list): - set_cookies(self.req.cj, self.COOKIES) + def handle_direct(self, pyfile): + for i in xrange(self.get_config("maxredirs", plugin="UserAgentSwitcher")): + redirect = self.link or pyfile.url + self.log_debug("Redirect #%d to: %s" % (i, redirect)) - self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS) + header = self.load(redirect, just_header=True) + if 'location' in header and header['location']: + self.link = header['location'] + else: + break + else: + self.log_error(_("Too many redirects")) def decrypt(self, pyfile): self.prepare() + self.check_info() #@TODO: Remove in 0.4.10 - self.preload() - self.checkInfo() - - self.links = self.getLinks() + if self.direct_dl: + self.log_debug(_("Looking for direct download link...")) + self.handle_direct(pyfile) - if hasattr(self, 'PAGES_PATTERN') and hasattr(self, 'loadPage'): - self.handlePages(pyfile) + if self.link or self.links or self.urls or self.packages: + self.log_info(_("Direct download link detected")) + else: + self.log_info(_("Direct download link not found")) - self.logDebug("Package has %d links" % len(self.links)) + if not (self.link or self.links or self.urls or self.packages): + self.preload() - if self.links: - self.packages = [(self.info['name'], self.links, self.info['folder'])] + self.links = self.get_links() or list() - elif not self.urls and not self.packages: #@TODO: Remove in 0.4.10 - self.fail(_("No link grabbed")) + if hasattr(self, 'PAGES_PATTERN') and hasattr(self, 'loadPage'): + self.handle_pages(pyfile) + self.log_debug("Package has %d links" % len(self.links)) - def checkNameSize(self, getinfo=True): - if not self.info or getinfo: - self.logDebug("File info (BEFORE): %s" % self.info) - self.info.update(self.getInfo(self.pyfile.url, self.html)) - self.logDebug("File info (AFTER): %s" % self.info) - - try: - url = self.info['url'].strip() - name = self.info['name'].strip() - if name and name != url: - self.pyfile.name = name + if self.link: + self.urls.append(self.link) - except Exception: - pass - - try: - folder = self.info['folder'] = self.pyfile.name - - except Exception: - pass - - self.logDebug("File name: %s" % self.pyfile.name, - "File folder: %s" % self.pyfile.name) + if self.links: + name = folder = pyfile.name + self.packages.append((name, self.links, folder)) - def getLinks(self): + def get_links(self): """ Returns the links extracted from self.html You should override this only if it's impossible to extract links using only the LINK_PATTERN. """ - url_p = urlparse.urlparse(self.pyfile.url) - baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) - - 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 re.findall(self.LINK_PATTERN, self.html) - def handlePages(self, pyfile): + def handle_pages(self, pyfile): try: pages = int(re.search(self.PAGES_PATTERN, self.html).group(1)) except Exception: pages = 1 for p in xrange(2, pages + 1): - self.html = self.loadPage(p) - self.links += self.getLinks() + self.html = self.load_page(p) + self.links += self.get_links() diff --git a/module/plugins/internal/SimpleDereferer.py b/module/plugins/internal/SimpleDereferer.py deleted file mode 100644 index 2e7e08321..000000000 --- a/module/plugins/internal/SimpleDereferer.py +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding: utf-8 -*- - -import re - -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.14" - - __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. - """ - - URL_REPLACEMENTS = [] - - 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.prepare() - - self.handleDirect(pyfile) - - if not self.link: - 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) - - self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS) - - - 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): - try: - link = re.search(self.LINK_PATTERN, self.html).group(1) - - except Exception, e: - self.logWarning(e) - - else: - 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..9c310ca27 100644 --- a/module/plugins/internal/SimpleHoster.py +++ b/module/plugins/internal/SimpleHoster.py @@ -1,245 +1,30 @@ # -*- coding: utf-8 -*- -import datetime +from __future__ import with_statement + import mimetypes import os import re import time -import urllib import urlparse from module.PyFile import statusMap as _statusMap -from module.network.CookieJar import CookieJar from module.network.HTTPRequest import BadHeader -from module.network.RequestFactory import getURL -from module.plugins.Hoster import Hoster -from module.plugins.Plugin import Fail, Retry -from module.utils import fixup, fs_encode, html_unescape, parseFileSize +from module.network.RequestFactory import getURL as get_url +from module.plugins.internal.Hoster import Hoster, create_getInfo, parse_fileInfo +from module.plugins.internal.Plugin import Fail, encode, fixurl, replace_patterns, seconds_to_midnight, set_cookie, set_cookies +from module.utils import fixup, fs_encode, parseFileSize as parse_size #@TODO: Adapt and move to PyFile in 0.4.10 -statusMap = dict((v, k) for k, v in _statusMap.iteritems()) - - -#@TODO: Remove in 0.4.10 and redirect to self.error instead -def _error(self, reason, type): - if not reason and not type: - type = "unknown" - - msg = _("%s error") % type.strip().capitalize() if type else _("Error") - msg += (": %s" % reason.strip()) if reason else "" - msg += _(" | Plugin may be out of date") - - raise Fail(msg) - - -#@TODO: Remove in 0.4.10 -def _wait(self, seconds, reconnect): - if seconds: - self.setWait(int(seconds) + 1) - - if reconnect is not None: - self.wantReconnect = reconnect - - super(SimpleHoster, self).wait() - - -def replace_patterns(string, ruleslist): - for r in ruleslist: - rf, rt = r - string = re.sub(rf, rt, string) - return string - - -def set_cookies(cj, cookies): - for cookie in cookies: - if isinstance(cookie, tuple) and len(cookie) == 3: - domain, name, value = cookie - cj.setCookie(domain, name, value) - - -def parseHtmlTagAttrValue(attr_name, tag): - m = re.search(r"%s\s*=\s*([\"']?)((?<=\")[^\"]+|(?<=')[^']+|[^>\s\"'][^>\s]*)\1" % attr_name, tag, re.I) - return m.group(2) if m else None - - -def parseHtmlForm(attr_str, html, input_names={}): - for form in re.finditer(r"(?P<TAG><form[^>]*%s[^>]*>)(?P<CONTENT>.*?)</?(form|body|html)[^>]*>" % attr_str, - html, re.S | re.I): - inputs = {} - action = parseHtmlTagAttrValue("action", form.group('TAG')) - - for inputtag in re.finditer(r'(<(input|textarea)[^>]*>)([^<]*(?=</\2)|)', form.group('CONTENT'), re.S | re.I): - name = parseHtmlTagAttrValue("name", inputtag.group(1)) - if name: - value = parseHtmlTagAttrValue("value", inputtag.group(1)) - if not value: - inputs[name] = inputtag.group(3) or "" - else: - inputs[name] = value - - if input_names: - # check input attributes - for key, val in input_names.iteritems(): - if key in inputs: - if isinstance(val, basestring) and inputs[key] == val: - continue - elif isinstance(val, tuple) and inputs[key] in val: - continue - elif hasattr(val, "search") and re.match(val, inputs[key]): - continue - break #: attibute value does not match - else: - break #: attibute name does not match - else: - return action, inputs #: passed attribute check - else: - # no attribute check - return action, inputs - - return {}, None #: no matching form found - - -#@TODO: Remove in 0.4.10 -def parseFileInfo(plugin, url="", html=""): - if hasattr(plugin, "getInfo"): - info = plugin.getInfo(url, html) - res = info['name'], info['size'], info['status'], info['url'] - else: - url = urllib.unquote(url) - url_p = urlparse.urlparse(url) - res = ((url_p.path.split('/')[-1] - or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0] - or url_p.netloc.split('.', 1)[0]), - 0, - 3 if url else 8, - url) - - return res - - -#@TODO: Remove in 0.4.10 -def create_getInfo(plugin): - def getInfo(urls): - for url in urls: - if hasattr(plugin, "URL_REPLACEMENTS"): - url = replace_patterns(url, plugin.URL_REPLACEMENTS) - yield parseFileInfo(plugin, url) - - return getInfo - - -def timestamp(): - return int(time.time() * 1000) - - -#@TODO: Move to hoster class in 0.4.10 -def getFileURL(self, url, follow_location=None): - link = "" - redirect = 1 - - if type(follow_location) is int: - redirect = max(follow_location, 1) - else: - redirect = 10 - - for i in xrange(redirect): - try: - self.logDebug("Redirect #%d to: %s" % (i, url)) - header = self.load(url, just_header=True, decode=True) - - except Exception: #: Bad bad bad... rewrite this part in 0.4.10 - req = pyreq.getHTTPRequest() - res = req.load(url, just_header=True, decode=True) - - req.close() - - header = {"code": req.code} - for line in res.splitlines(): - line = line.strip() - if not line or ":" not in line: - continue - - key, none, value = line.partition(":") - key = key.lower().strip() - value = value.strip() - - if key in header: - if type(header[key]) == list: - header[key].append(value) - else: - header[key] = [header[key], value] - else: - header[key] = value - - if 'content-disposition' in header: - link = url - - elif 'location' in header and header['location']: - location = header['location'] - - if not urlparse.urlparse(location).scheme: - url_p = urlparse.urlparse(url) - baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) - location = urlparse.urljoin(baseurl, location) - - if 'code' in header and header['code'] == 302: - link = location - - if follow_location: - url = location - continue - - else: - extension = os.path.splitext(urlparse.urlparse(url).path.split('/')[-1])[-1] - - if 'content-type' in header and header['content-type']: - mimetype = header['content-type'].split(';')[0].strip() - - elif extension: - mimetype = mimetypes.guess_type(extension, False)[0] or "application/octet-stream" - - else: - mimetype = "" - - if mimetype and (link or 'html' not in mimetype): - link = url - else: - link = "" - - break - - else: - try: - self.logError(_("Too many redirects")) - except Exception: - pass - - return link - - -def secondsToMidnight(gmt=0): - now = datetime.datetime.utcnow() + datetime.timedelta(hours=gmt) - - if now.hour is 0 and now.minute < 10: - midnight = now - else: - midnight = now + datetime.timedelta(days=1) - - td = midnight.replace(hour=0, minute=10, second=0, microsecond=0) - now - - if hasattr(td, 'total_seconds'): - res = td.total_seconds() - else: #@NOTE: work-around for python 2.5 and 2.6 missing datetime.timedelta.total_seconds - res = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 - - return int(res) +statusMap = dict((v, k) for k, v in _statusMap.items()) class SimpleHoster(Hoster): __name__ = "SimpleHoster" __type__ = "hoster" - __version__ = "1.50" + __version__ = "1.80" + __status__ = "testing" __pattern__ = r'^unmatchable$' __config__ = [("use_premium", "bool", "Use premium account if available" , True), @@ -249,7 +34,6 @@ class SimpleHoster(Hoster): __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - """ Info patterns: @@ -258,6 +42,7 @@ class SimpleHoster(Hoster): or NAME_PATTERN: (mandatory) Name that will be set for the file example: NAME_PATTERN = r'(?P<N>file_name)' + SIZE_PATTERN: (mandatory) Size that will be checked for the file example: SIZE_PATTERN = r'(?P<S>file_size) (?P<U>size_unit)' @@ -285,8 +70,8 @@ class SimpleHoster(Hoster): IP_BLOCKED_PATTERN: (optional) example: IP_BLOCKED_PATTERN = r'in your country' - DOWNLOAD_LIMIT_PATTERN: (optional) - example: DOWNLOAD_LIMIT_PATTERN = r'download limit' + DL_LIMIT_PATTERN: (optional) + example: DL_LIMIT_PATTERN = r'download limit' SIZE_LIMIT_PATTERN: (optional) example: SIZE_LIMIT_PATTERN = r'up to' @@ -295,49 +80,50 @@ class SimpleHoster(Hoster): example: ERROR_PATTERN = r'' - Instead overriding handleFree and handlePremium methods you may define the following patterns for basic link handling: + Instead overriding handle_free and handle_premium methods you may define the following patterns for basic link handling: - LINK_FREE_PATTERN: (optional) group(1) should be the direct link for free download - example: LINK_FREE_PATTERN = r'<div class="link"><a href="(.+?)"' + LINK_PATTERN: (optional) group(1) should be the direct link for free and premium download + example: LINK_PATTERN = r'<div class="link"><a href="(.+?)"' + or + LINK_FREE_PATTERN: (optional) group(1) should be the direct link for free download + example: LINK_FREE_PATTERN = r'<div class="link"><a href="(.+?)"' - LINK_PREMIUM_PATTERN: (optional) group(1) should be the direct link for premium download - example: LINK_PREMIUM_PATTERN = r'<div class="link"><a href="(.+?)"' + LINK_PREMIUM_PATTERN: (optional) group(1) should be the direct link for premium download + example: LINK_PREMIUM_PATTERN = r'<div class="link"><a href="(.+?)"' """ - NAME_REPLACEMENTS = [("&#?\w+;", fixup)] SIZE_REPLACEMENTS = [] URL_REPLACEMENTS = [] - TEXT_ENCODING = False #: Set to True or encoding name if encoding value in http header is not correct + FILE_ERRORS = [('Html error' , r'\A(?:\s*<.+>)?((?:[\w\s]*(?:[Ee]rror|ERROR)\s*\:?)?\s*\d{3})(?:\Z|\s+)'), + ('Request error', r'([Aa]n error occured while processing your request)' ), + ('Html file' , r'\A\s*<!DOCTYPE html' )] + + CHECK_FILE = True #: Set to False to not check the last downloaded file with declared error patterns + CHECK_TRAFFIC = False #: Set to True to reload checking traffic left for premium account 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 - 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 + DIRECT_LINK = None #: Set to True to looking for direct link (as defined in handle_direct method), set to None to do it if self.account is True else False 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 + LEECH_HOSTER = False #: Set to True to leech other hoster link (as defined in handle_multi method) + TEXT_ENCODING = True #: Set to encoding name if encoding value in http header is not correct - directLink = getFileURL #@TODO: Remove in 0.4.10 + LINK_PATTERN = None @classmethod - def apiInfo(cls, url): - url = urllib.unquote(url) - url_p = urlparse.urlparse(url) - return {'name' : (url_p.path.split('/')[-1] - or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0] - or url_p.netloc.split('.', 1)[0]), - 'size' : 0, - 'status': 3 if url else 8, - 'url' : url} + def api_info(cls, url): + return super(SimpleHoster, cls).get_info(url) @classmethod - def getInfo(cls, url="", html=""): - info = cls.apiInfo(url) - online = True if info['status'] is 2 else False + def get_info(cls, url="", html=""): + info = cls.api_info(url) + online = True if info['status'] == 2 else False try: - info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: pattern groups will be saved here + info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: Pattern groups will be saved here except Exception: info['pattern'] = {} @@ -347,20 +133,17 @@ class SimpleHoster(Hoster): info['error'] = "missing url" info['status'] = 1 - elif info['status'] is 3: + elif info['status'] == 3: try: - html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING) - - if isinstance(cls.TEXT_ENCODING, basestring): - html = unicode(html, cls.TEXT_ENCODING) + html = get_url(url, cookies=cls.COOKIES, decode=cls.TEXT_ENCODING) except BadHeader, e: info['error'] = "%d: %s" % (e.code, e.content) - if e.code is 404: + if e.code == 404: info['status'] = 1 - elif e.code is 503: + elif e.code == 503: info['status'] = 6 except Exception: @@ -392,17 +175,17 @@ class SimpleHoster(Hoster): info['status'] = 2 if 'N' in info['pattern']: - info['name'] = replace_patterns(urllib.unquote(info['pattern']['N'].strip()), + info['name'] = replace_patterns(fixurl(info['pattern']['N']), cls.NAME_REPLACEMENTS) if 'S' in info['pattern']: size = replace_patterns(info['pattern']['S'] + info['pattern']['U'] if 'U' in info['pattern'] else info['pattern']['S'], cls.SIZE_REPLACEMENTS) - info['size'] = parseFileSize(size) + info['size'] = parse_size(size) elif isinstance(info['size'], basestring): unit = info['units'] if 'units' in info else None - info['size'] = parseFileSize(info['size'], unit) + info['size'] = parse_size(info['size'], unit) if 'H' in info['pattern']: hashtype = info['pattern']['T'] if 'T' in info['pattern'] else "hash" @@ -415,156 +198,155 @@ class SimpleHoster(Hoster): def setup(self): - self.resumeDownload = self.multiDL = self.premium + self.resume_download = self.multiDL = self.premium def prepare(self): - self.pyfile.error = "" #@TODO: Remove in 0.4.10 + self.pyfile.error = "" #@TODO: Remove in 0.4.10 + self.html = "" #@TODO: Recheck in 0.4.10 + self.link = "" #@TODO: Recheck in 0.4.10 + self.last_download = "" + self.direct_dl = False + self.leech_dl = False - self.info = {} - self.html = "" - self.link = "" #@TODO: Move to hoster class in 0.4.10 - self.directDL = False #@TODO: Move to hoster class in 0.4.10 - self.multihost = False #@TODO: Move to hoster class in 0.4.10 + if not self.get_config('use_premium', True): + self.restart(nopremium=True) - if not self.getConfig('use_premium', True): - self.retryFree() + if self.LOGIN_PREMIUM and not self.premium: + self.fail(_("Required premium account not found")) + self.LOGIN_ACCOUNT = True if self.LOGIN_ACCOUNT and not self.account: self.fail(_("Required account not found")) self.req.setOption("timeout", 120) - if isinstance(self.COOKIES, list): - set_cookies(self.req.cj, self.COOKIES) + if self.LINK_PATTERN: + if not hasattr(self, 'LINK_FREE_PATTERN'): + self.LINK_FREE_PATTERN = self.LINK_PATTERN - if (self.MULTI_HOSTER - and (self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern'] - or re.match(self.__pattern__, self.pyfile.url) is None)): - self.multihost = True - return + if not hasattr(self, 'LINK_PREMIUM_PATTERN'): + self.LINK_PREMIUM_PATTERN = self.LINK_PATTERN + + if (self.LEECH_HOSTER + and (self.__pattern__ is not self.pyload.pluginManager.hosterPlugins[self.__name__]['pattern'] + and re.match(self.__pattern__, self.pyfile.url) is None)): + self.leech_dl = True + + if self.leech_dl: + self.direct_dl = False - if self.DIRECT_LINK is None: - self.directDL = bool(self.account) + elif self.DIRECT_LINK is None: + self.direct_dl = bool(self.account) else: - self.directDL = self.DIRECT_LINK + self.direct_dl = self.DIRECT_LINK - self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS) + if not self.leech_dl: + self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS) 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) + self.html = self.load(self.pyfile.url, + cookies=self.COOKIES, + ref=False, + decode=self.TEXT_ENCODING) def process(self, pyfile): try: self.prepare() - self.checkInfo() - - if self.directDL: - self.logDebug("Looking for direct download link...") - self.handleDirect(pyfile) + self.check_info() #@TODO: Remove in 0.4.10 - if self.multihost and not self.link and not self.lastDownload: - self.logDebug("Looking for leeched download link...") - self.handleMulti(pyfile) + if self.leech_dl: + self.log_info(_("Processing as debrid download...")) + self.handle_multi(pyfile) - if not self.link and not self.lastDownload: - self.MULTI_HOSTER = False - self.retry(1, reason="Multi hoster fails") + if not self.link and not was_downloaded(): + self.log_info(_("Failed to leech url")) - if not self.link and not self.lastDownload: - self.preload() - self.checkInfo() - - if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): - self.logDebug("Handled as premium download") - self.handlePremium(pyfile) - - elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()): - self.logDebug("Handled as free download") - self.handleFree(pyfile) - - self.downloadLink(self.link, self.DISPOSITION) - self.checkFile() + else: + if not self.link and self.direct_dl and not self.last_download: + self.log_info(_("Looking for direct download link...")) + self.handle_direct(pyfile) - except Fail, e: #@TODO: Move to PluginThread in 0.4.10 - err = str(e) #@TODO: Recheck in 0.4.10 + if self.link or self.last_download: + self.log_info(_("Direct download link detected")) + else: + self.log_info(_("Direct download link not found")) - if err == _("No captcha result obtained in appropiate time by any of the plugins."): #@TODO: Fix in 0.4.10 - self.checkFile() + if not self.link and not self.last_download: + self.preload() - elif self.getConfig('fallback', True) and self.premium: - self.logWarning(_("Premium download failed"), e) - self.retryFree() + if 'status' not in self.info or self.info['status'] is 3: #@TODO: Recheck in 0.4.10 + self.check_info() - else: - raise Fail(err) + if self.premium and (not self.CHECK_TRAFFIC or self.check_traffic_left()): + self.log_info(_("Processing as premium download...")) + self.handle_premium(pyfile) + elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.check_traffic_left()): + self.log_info(_("Processing as free download...")) + self.handle_free(pyfile) - def downloadLink(self, link, disposition=True): - if not link or not isinstance(link, basestring): - return + if not self.last_download: + self.log_info(_("Downloading file...")) + self.download(self.link, disposition=self.DISPOSITION) - self.correctCaptcha() + self.check_file() - link = html_unescape(link.strip().decode('unicode-escape')) #@TODO: Move this check to plugin `load` method in 0.4.10 + except Fail, e: #@TODO: Move to PluginThread in 0.4.10 + if self.get_config('fallback', True) and self.premium: + self.log_warning(_("Premium download failed"), e) + self.restart(nopremium=True) - if not urlparse.urlparse(link).scheme: - url_p = urlparse.urlparse(self.pyfile.url) - baseurl = "%s://%s" % (url_p.scheme, url_p.netloc) - link = urlparse.urljoin(baseurl, link) + else: + raise Fail(encode(e)) #@TODO: Remove `encode` in 0.4.10 - self.download(link, ref=False, disposition=disposition) + def check_file(self): + self.log_info(_("Checking file...")) - def checkFile(self, rules={}): - if self.cTask and not self.lastDownload: - self.invalidCaptcha() + if self.captcha.task and not self.last_download: + self.captcha.invalid() self.retry(10, reason=_("Wrong captcha")) - elif not self.lastDownload or not os.path.exists(fs_encode(self.lastDownload)): - self.lastDownload = "" - self.error(self.pyfile.error or _("No file downloaded")) + # 10485760 is 10MB, tolerance is used when comparing displayed size on the hoster website to real size + # For example displayed size can be 1.46GB for example, but real size can be 1.4649853GB + elif self.check_download({'Empty file': re.compile(r'\A((.|)(\2|\s)*)\Z')}, + file_size=self.info['size'] if 'size' in self.info else 0, + size_tolerance=10485760, + delete=True): + self.error(_("Empty file")) else: - errmsg = self.checkDownload({'Empty file': re.compile(r'\A\s*\Z'), - 'Html error': re.compile(r'\A(?:\s*<.+>)?((?:[\w\s]*(?:[Ee]rror|ERROR)\s*\:?)?\s*\d{3})(?:\Z|\s+)')}) - - if not errmsg: - for r, p in [('Html file' , re.compile(r'\A\s*<!DOCTYPE html') ), - ('Request error', re.compile(r'([Aa]n error occured while processing your request)'))]: - if r not in rules: - rules[r] = p - - for r, a in [('Error' , "ERROR_PATTERN" ), - ('Premium only', "PREMIUM_ONLY_PATTERN"), - ('Wait error' , "WAIT_PATTERN" )]: - if r not in rules and hasattr(self, a): - rules[r] = getattr(self, a) - - errmsg = self.checkDownload(rules) + self.log_debug("Using default check rules...") + for r, p in self.FILE_ERRORS: + errmsg = self.check_download({r: re.compile(p)}) + if errmsg is not None: + errmsg = errmsg.strip().capitalize() - if not errmsg: - return - - errmsg = errmsg.strip().capitalize() + try: + errmsg += " | " + self.last_check.group(1).strip() + except Exception: + pass - try: - errmsg += " | " + self.lastCheck.group(1).strip() - except Exception: - pass + self.log_warning(_("Check result: ") + errmsg, _("Waiting 1 minute and retry")) + self.wantReconnect = True + self.retry(wait_time=60, reason=errmsg) + else: + if self.CHECK_FILE: + self.log_debug("Using custom check rules...") + with open(fs_encode(self.last_download), "rb") as f: + self.html = f.read(1048576) #@TODO: Recheck in 0.4.10 + self.check_errors() - self.logWarning("Check result: " + errmsg, "Waiting 1 minute and retry") - self.retry(3, 60, errmsg) + self.log_info(_("No errors found")) + self.pyfile.error = "" - def checkErrors(self): + def check_errors(self): if not self.html: - self.logWarning(_("No html code to check")) + self.log_warning(_("No html code to check")) return if hasattr(self, 'IP_BLOCKED_PATTERN') and re.search(self.IP_BLOCKED_PATTERN, self.html): @@ -577,20 +359,20 @@ class SimpleHoster(Hoster): elif hasattr(self, 'SIZE_LIMIT_PATTERN') and re.search(self.SIZE_LIMIT_PATTERN, self.html): self.fail(_("File too large for free download")) - elif hasattr(self, 'DOWNLOAD_LIMIT_PATTERN') and re.search(self.DOWNLOAD_LIMIT_PATTERN, self.html): - m = re.search(self.DOWNLOAD_LIMIT_PATTERN, self.html) + elif hasattr(self, 'DL_LIMIT_PATTERN') and re.search(self.DL_LIMIT_PATTERN, self.html): + m = re.search(self.DL_LIMIT_PATTERN, self.html) try: errmsg = m.group(1).strip() except Exception: errmsg = m.group(0).strip() self.info['error'] = re.sub(r'<.*?>', " ", errmsg) - self.logWarning(self.info['error']) + self.log_warning(self.info['error']) if re.search('da(il)?y|today', errmsg, re.I): - wait_time = secondsToMidnight(gmt=2) + wait_time = seconds_to_midnight(gmt=2) else: - wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1, "": 1}[u.lower()] for v, u in + wait_time = sum(int(v) * {'hr': 3600, 'hour': 3600, 'min': 60, 'sec': 1, "": 1}[u.lower()] for v, u in re.findall(r'(\d+)\s*(hr|hour|min|sec|)', errmsg, re.I)) self.wantReconnect = wait_time > 300 @@ -608,13 +390,13 @@ class SimpleHoster(Hoster): errmsg = m.group(0).strip() self.info['error'] = re.sub(r'<.*?>', " ", errmsg) - self.logWarning(self.info['error']) + self.log_warning(self.info['error']) - if re.search('limit|wait', errmsg, re.I): + if re.search('limit|wait|slot', errmsg, re.I): if re.search("da(il)?y|today", errmsg): - wait_time = secondsToMidnight(gmt=2) + wait_time = seconds_to_midnight(gmt=2) else: - wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1, "": 1}[u.lower()] for v, u in + wait_time = sum(int(v) * {'hr': 3600, 'hour': 3600, 'min': 60, 'sec': 1, "": 1}[u.lower()] for v, u in re.findall(r'(\d+)\s*(hr|hour|min|sec|)', errmsg, re.I)) self.wantReconnect = wait_time > 300 @@ -624,20 +406,26 @@ class SimpleHoster(Hoster): self.fail(_("Connection from your current IP address is not allowed")) elif re.search('captcha|code', errmsg, re.I): - self.invalidCaptcha() + self.captcha.invalid() + self.retry(10, reason=_("Wrong captcha")) elif re.search('countdown|expired', errmsg, re.I): - self.retry(wait_time=60, reason=_("Link expired")) + self.retry(10, 60, _("Link expired")) elif re.search('maintenance|maintainance|temp', errmsg, re.I): - self.tempOffline() + self.temp_offline() - elif re.search('up to', errmsg, re.I): + elif re.search('up to|size', 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.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")) @@ -653,98 +441,102 @@ class SimpleHoster(Hoster): except Exception: waitmsg = m.group(0).strip() - wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1, "": 1}[u.lower()] for v, u in + wait_time = sum(int(v) * {'hr': 3600, 'hour': 3600, 'min': 60, 'sec': 1, "": 1}[u.lower()] for v, u in re.findall(r'(\d+)\s*(hr|hour|min|sec|)', waitmsg, re.I)) self.wait(wait_time, wait_time > 300) self.info.pop('error', None) - def checkStatus(self, getinfo=True): + def check_status(self, getinfo=True): if not self.info or getinfo: - self.logDebug("Update file info...") - self.logDebug("Previous file info: %s" % self.info) - self.info.update(self.getInfo(self.pyfile.url, self.html)) - self.logDebug("Current file info: %s" % self.info) + self.log_info(_("Updating file info...")) + old_info = self.info.copy() + self.info.update(self.get_info(self.pyfile.url, self.html)) + self.log_debug("File info: %s" % self.info) + self.log_debug("Previous file info: %s" % old_info) try: - status = self.info['status'] + status = self.info['status'] or None - if status is 1: + if status == 1: self.offline() - elif status is 6: - self.tempOffline() + elif status == 6: + self.temp_offline() - elif status is 8: - self.fail(self.info['error'] if 'error' in self.info else _("Failed")) + elif status == 8: + if 'error' in self.info: + self.fail(self.info['error']) + else: + self.fail(_("File status: " + statusMap[status])) finally: - self.logDebug("File status: %s" % statusMap[status]) + self.log_info(_("File status: ") + (statusMap[status] if status else _("Unknown"))) - def checkNameSize(self, getinfo=True): + def check_name_size(self, getinfo=True): if not self.info or getinfo: - self.logDebug("Update file info...") - self.logDebug("Previous file info: %s" % self.info) - self.info.update(self.getInfo(self.pyfile.url, self.html)) - self.logDebug("Current file info: %s" % self.info) + self.log_info(_("Updating file info...")) + old_info = self.info.copy() + self.info.update(self.get_info(self.pyfile.url, self.html)) + self.log_debug("File info: %s" % self.info) + self.log_debug("Previous file info: %s" % old_info) try: url = self.info['url'].strip() name = self.info['name'].strip() - if name and name != url: - self.pyfile.name = name - except Exception: + except KeyError: pass - try: - size = self.info['size'] - if size > 0: - self.pyfile.size = size + else: + if name and name is not url: + self.pyfile.name = name - except Exception: - pass + if 'size' in self.info and self.info['size'] > 0: + self.pyfile.size = int(self.info['size']) #@TODO: Fix int conversion in 0.4.10 + + # self.pyfile.sync() + + name = self.pyfile.name + size = self.pyfile.size + folder = self.info['folder'] = name - self.logDebug("File name: %s" % self.pyfile.name, - "File size: %s byte" % self.pyfile.size if self.pyfile.size > 0 else "File size: Unknown") + self.log_info(_("File name: ") + name) + self.log_info(_("File size: %s bytes") % size if size > 0 else _("File size: Unknown")) + # self.log_info("File folder: " + folder) - def checkInfo(self): - self.checkNameSize() + #@TODO: Rewrite in 0.4.10 + def check_info(self): + self.check_name_size() if self.html: - self.checkErrors() - self.checkNameSize() + self.check_errors() + self.check_name_size() - self.checkStatus(getinfo=False) + self.check_status(getinfo=False) - #: Deprecated - def getFileInfo(self): + #: Deprecated method (Remove in 0.4.10) + def get_fileInfo(self): self.info = {} - self.checkInfo() + self.check_info() return self.info - def handleDirect(self, pyfile): - link = self.directLink(pyfile.url, self.resumeDownload) - - if link: - self.logInfo(_("Direct download link detected")) - self.link = link - else: - self.logDebug("Direct download link not found") + def handle_direct(self, pyfile): + self.link = self.direct_link(pyfile.url, self.resume_download) - def handleMulti(self, pyfile): #: Multi-hoster handler + def handle_multi(self, pyfile): #: Multi-hoster handler pass - def handleFree(self, pyfile): + def handle_free(self, pyfile): if not hasattr(self, 'LINK_FREE_PATTERN'): - self.logError(_("Free download not implemented")) + self.log_error(_("Free download not implemented")) m = re.search(self.LINK_FREE_PATTERN, self.html) if m is None: @@ -753,77 +545,14 @@ class SimpleHoster(Hoster): self.link = m.group(1) - def handlePremium(self, pyfile): + def handle_premium(self, pyfile): if not hasattr(self, 'LINK_PREMIUM_PATTERN'): - self.logError(_("Premium download not implemented")) - self.logDebug("Handled as free download") - self.handleFree(pyfile) + self.log_error(_("Premium download not implemented")) + self.log_info(_("Processing as free download...")) + self.handle_free(pyfile) m = re.search(self.LINK_PREMIUM_PATTERN, self.html) if m is None: self.error(_("Premium download link not found")) else: self.link = m.group(1) - - - def longWait(self, wait_time=None, max_tries=3): - if wait_time and isinstance(wait_time, (int, long, float)): - time_str = "%dh %dm" % divmod(wait_time / 60, 60) - else: - wait_time = 900 - time_str = _("(unknown time)") - max_tries = 100 - - self.logInfo(_("Download limit reached, reconnect or wait %s") % time_str) - - self.wait(wait_time, True) - self.retry(max_tries=max_tries, reason=_("Download limit reached")) - - - def parseHtmlForm(self, attr_str="", input_names={}): - return parseHtmlForm(attr_str, self.html, input_names) - - - def checkTrafficLeft(self): - if not self.account: - return True - - traffic = self.account.getAccountInfo(self.user, True)['trafficleft'] - - if traffic is None: - return False - elif traffic == -1: - return True - else: - size = self.pyfile.size / 1024 - self.logInfo(_("Filesize: %i KiB, Traffic left for user %s: %i KiB") % (size, self.user, traffic)) - return size <= traffic - - - #@TODO: Remove in 0.4.10 - def getConfig(self, option, default=''): - """getConfig with default value - sublass may not implements all config options""" - try: - return self.getConf(option) - - except KeyError: - return default - - - def retryFree(self): - if not self.premium: - return - self.premium = False - self.account = None - self.req = self.core.requestFactory.getRequest(self.__name__) - self.retries = -1 - raise Retry(_("Fallback to free download")) - - - #@TODO: Remove in 0.4.10 - def wait(self, seconds=0, reconnect=None): - return _wait(self, seconds, reconnect) - - - def error(self, reason="", type="parse"): - return _error(self, reason, type) diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py index 5b9f2e1c3..0386991d9 100644 --- a/module/plugins/internal/UnRar.py +++ b/module/plugins/internal/UnRar.py @@ -8,7 +8,7 @@ from glob import glob from string import digits from module.plugins.internal.Extractor import Extractor, ArchiveError, CRCError, PasswordError -from module.utils import fs_decode, fs_encode, save_join +from module.utils import fs_decode, fs_encode, save_join as fs_join def renice(pid, value): @@ -22,7 +22,8 @@ def renice(pid, value): class UnRar(Extractor): __name__ = "UnRar" - __version__ = "1.20" + __version__ = "1.25" + __status__ = "testing" __description__ = """Rar extractor plugin""" __license__ = "GPLv3" @@ -31,12 +32,10 @@ class UnRar(Extractor): ("Immenz" , "immenz@gmx.net" )] - CMD = "unrar" - VERSION = "" + CMD = "unrar" EXTENSIONS = [".rar"] - - re_multipart = re.compile(r'\.(part|r)(\d+)(?:\.rar)?(\.rev|\.bad)?',re.I) + re_multipart = re.compile(r'\.(part|r)(\d+)(?:\.rar)?(\.rev|\.bad)?', re.I) re_filefixed = re.compile(r'Building (.+)') re_filelist = re.compile(r'^(.)(\s*[\w\.\-]+)\s+(\d+\s+)+(?:\d+\%\s+)?[\d\-]{8}\s+[\d\:]{5}', re.M|re.I) @@ -48,38 +47,40 @@ class UnRar(Extractor): @classmethod - def isUsable(cls): - if os.name == "nt": - try: + def find(cls): + try: + if os.name == "nt": cls.CMD = os.path.join(pypath, "RAR.exe") - p = subprocess.Popen([cls.CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = p.communicate() - cls.__name__ = "RAR" - cls.REPAIR = True + else: + cls.CMD = "rar" - except OSError: - cls.CMD = os.path.join(pypath, "UnRAR.exe") - p = subprocess.Popen([cls.CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = p.communicate() - else: + p = subprocess.Popen([cls.CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + # cls.__name__ = "RAR" + cls.REPAIR = True + + except OSError: try: - p = subprocess.Popen(["rar"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = p.communicate() - cls.__name__ = "RAR" - cls.REPAIR = True + if os.name == "nt": + cls.CMD = os.path.join(pypath, "UnRAR.exe") + else: + cls.CMD = "unrar" - except OSError: #: fallback to unrar p = subprocess.Popen([cls.CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() + except OSError: + return False + m = cls.re_version.search(out) - cls.VERSION = m.group(1) if m else '(version unknown)' + if m is not None: + cls.VERSION = m.group(1) return True @classmethod - def isMultipart(cls, filename): + def is_multipart(cls, filename): return True if cls.re_multipart.search(filename) else False @@ -105,7 +106,7 @@ class UnRar(Extractor): if self.re_wrongcrc.search(err): raise CRCError(err) - # output only used to check if passworded files are present + #: Output only used to check if passworded files are present for attr in self.re_filelist.findall(out): if attr[0].startswith("*"): raise PasswordError @@ -114,7 +115,7 @@ class UnRar(Extractor): def repair(self): p = self.call_cmd("rc", fs_encode(self.filename)) - # communicate and retrieve stderr + #: Communicate and retrieve stderr self._progress(p) err = p.stderr.read().strip() if err or p.returncode: @@ -126,17 +127,17 @@ class UnRar(Extractor): s = "" while True: c = process.stdout.read(1) - # quit loop on eof + #: Quit loop on eof if not c: break - # reading a percentage sign -> set progress and restart - if c == '%': - self.notifyProgress(int(s)) + #: Reading a percentage sign -> set progress and restart + if c == "%": + self.notify_progress(int(s)) s = "" - # not reading a digit -> therefore restart + #: Not reading a digit -> therefore restart elif c not in digits: s = "" - # add digit to progressstring + #: Add digit to progressstring else: s += c @@ -148,7 +149,7 @@ class UnRar(Extractor): renice(p.pid, self.renice) - # communicate and retrieve stderr + #: Communicate and retrieve stderr self._progress(p) err = p.stderr.read().strip() @@ -159,7 +160,7 @@ class UnRar(Extractor): elif self.re_wrongcrc.search(err): raise CRCError(err) - else: #: raise error if anything is on stderr + else: #: Raise error if anything is on stderr raise ArchiveError(err) if p.returncode: @@ -168,15 +169,15 @@ class UnRar(Extractor): self.files = self.list(password) - def getDeleteFiles(self): + def get_delete_files(self): dir, name = os.path.split(self.filename) - # actually extracted file + #: Actually extracted file files = [self.filename] - # eventually Multipart Files - files.extend(save_join(dir, os.path.basename(file)) for file in filter(self.isMultipart, os.listdir(dir)) - if re.sub(self.re_multipart,".rar",name) == re.sub(self.re_multipart,".rar",file)) + #: eventually Multipart Files + files.extend(fs_join(dir, os.path.basename(file)) for file in filter(self.is_multipart, os.listdir(dir)) + if re.sub(self.re_multipart, ".rar", name) == re.sub(self.re_multipart, ".rar", file)) return files @@ -190,20 +191,19 @@ class UnRar(Extractor): if "Cannot open" in err: raise ArchiveError(_("Cannot open file")) - if err.strip(): #: only log error at this point - self.manager.logError(err.strip()) + if err.strip(): #: Only log error at this point + self.log_error(err.strip()) result = set() if not self.fullpath and self.VERSION.startswith('5'): - # NOTE: Unrar 5 always list full path + #@NOTE: Unrar 5 always list full path for f in fs_decode(out).splitlines(): - f = save_join(self.out, os.path.basename(f.strip())) + f = fs_join(self.out, os.path.basename(f.strip())) if os.path.isfile(f): - result.add(save_join(self.out, os.path.basename(f))) + result.add(fs_join(self.out, os.path.basename(f))) else: for f in fs_decode(out).splitlines(): - f = f.strip() - result.add(save_join(self.out, f)) + result.add(fs_join(self.out, f.strip())) return list(result) @@ -211,7 +211,7 @@ class UnRar(Extractor): def call_cmd(self, command, *xargs, **kwargs): args = [] - # overwrite flag + #: Overwrite flag if self.overwrite: args.append("-o+") else: @@ -222,10 +222,10 @@ class UnRar(Extractor): for word in self.excludefiles: args.append("-x'%s'" % word.strip()) - # assume yes on all queries + #: Assume yes on all queries args.append("-y") - # set a password + #: Set a password if "password" in kwargs and kwargs['password']: args.append("-p%s" % kwargs['password']) else: @@ -234,10 +234,10 @@ class UnRar(Extractor): if self.keepbroken: args.append("-kb") - # NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue + #@NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue call = [self.CMD, command] + args + list(xargs) - self.manager.logDebug(" ".join(call)) + self.log_debug(" ".join(call)) p = subprocess.Popen(call, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return p diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py index 8d3fec370..9a01611bf 100644 --- a/module/plugins/internal/UnZip.py +++ b/module/plugins/internal/UnZip.py @@ -12,19 +12,20 @@ from module.utils import fs_encode class UnZip(Extractor): __name__ = "UnZip" - __version__ = "1.12" + __version__ = "1.15" + __status__ = "testing" __description__ = """Zip extractor plugin""" __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] + VERSION = "%s.%s.%s" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]) EXTENSIONS = [".zip", ".zip64"] - VERSION ="(python %s.%s.%s)" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]) @classmethod - def isUsable(cls): + def find(cls): return sys.version_info[:2] >= (2, 6) diff --git a/module/plugins/internal/XFSAccount.py b/module/plugins/internal/XFSAccount.py index e619cb038..e0f6b1ee8 100644 --- a/module/plugins/internal/XFSAccount.py +++ b/module/plugins/internal/XFSAccount.py @@ -4,14 +4,15 @@ import re import time import urlparse -from module.plugins.Account import Account -from module.plugins.internal.SimpleHoster import parseHtmlForm, set_cookies +from module.plugins.internal.Account import Account +from module.plugins.internal.Plugin import parse_html_form, set_cookie class XFSAccount(Account): __name__ = "XFSAccount" __type__ = "account" - __version__ = "0.37" + __version__ = "0.42" + __status__ = "testing" __description__ = """XFileSharing account plugin""" __license__ = "GPLv3" @@ -30,34 +31,15 @@ class XFSAccount(Account): VALID_UNTIL_PATTERN = r'Premium.[Aa]ccount expire:.*?(\d{1,2} [\w^_]+ \d{4})' TRAFFIC_LEFT_PATTERN = r'Traffic available today:.*?<b>\s*(?P<S>[\d.,]+|[Uu]nlimited)\s*(?:(?P<U>[\w^_]+)\s*)?</b>' - TRAFFIC_LEFT_UNIT = "MB" #: used only if no group <U> was found + TRAFFIC_LEFT_UNIT = "MB" #: Used only if no group <U> was found LEECH_TRAFFIC_PATTERN = r'Leech Traffic left:<b>.*?(?P<S>[\d.,]+|[Uu]nlimited)\s*(?:(?P<U>[\w^_]+)\s*)?</b>' - LEECH_TRAFFIC_UNIT = "MB" #: used only if no group <U> was found + LEECH_TRAFFIC_UNIT = "MB" #: Used only if no group <U> was found LOGIN_FAIL_PATTERN = r'Incorrect Login or Password|account was banned|Error<' - def __init__(self, manager, accounts): #@TODO: remove in 0.4.10 - self.init() - return super(XFSAccount, self).__init__(manager, accounts) - - - def init(self): - if not self.HOSTER_DOMAIN: - self.logError(_("Missing HOSTER_DOMAIN")) - self.COOKIES = False - - else: - if not self.HOSTER_URL: - self.HOSTER_URL = "http://www.%s/" % self.HOSTER_DOMAIN - - if isinstance(self.COOKIES, list): - self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) - set_cookies(req.cj, self.COOKIES) - - - def loadAccountInfo(self, user, req): + def parse_info(self, user, password, data, req): validuntil = None trafficleft = None leechtraffic = None @@ -69,32 +51,34 @@ class XFSAccount(Account): 'leechtraffic': leechtraffic, 'premium' : premium} - html = req.load(self.HOSTER_URL, get={'op': "my_account"}, decode=True) + html = self.load(self.HOSTER_URL, + get={'op': "my_account"}, + cookies=self.COOKIES) premium = True if re.search(self.PREMIUM_PATTERN, html) else False m = re.search(self.VALID_UNTIL_PATTERN, html) if m: expiredate = m.group(1).strip() - self.logDebug("Expire date: " + expiredate) + self.log_debug("Expire date: " + expiredate) try: validuntil = time.mktime(time.strptime(expiredate, "%d %B %Y")) except Exception, e: - self.logError(e) + self.log_error(e) else: - self.logDebug("Valid until: %s" % validuntil) + self.log_debug("Valid until: %s" % validuntil) if validuntil > time.mktime(time.gmtime()): premium = True trafficleft = -1 else: premium = False - validuntil = None #: registered account type (not premium) + validuntil = None #: Registered account type (not premium) else: - self.logDebug("VALID_UNTIL_PATTERN not found") + self.log_debug("VALID_UNTIL_PATTERN not found") m = re.search(self.TRAFFIC_LEFT_PATTERN, html) if m: @@ -114,12 +98,12 @@ class XFSAccount(Account): else: unit = "" - trafficleft = self.parseTraffic(size + unit) + trafficleft = self.parse_traffic(size + unit) except Exception, e: - self.logError(e) + self.log_error(e) else: - self.logDebug("TRAFFIC_LEFT_PATTERN not found") + self.log_debug("TRAFFIC_LEFT_PATTERN not found") leech = [m.groupdict() for m in re.finditer(self.LEECH_TRAFFIC_PATTERN, html)] if leech: @@ -141,12 +125,12 @@ class XFSAccount(Account): else: unit = "" - leechtraffic += self.parseTraffic(size + unit) + leechtraffic += self.parse_traffic(size + unit) except Exception, e: - self.logError(e) + self.log_error(e) else: - self.logDebug("LEECH_TRAFFIC_PATTERN not found") + self.log_debug("LEECH_TRAFFIC_PATTERN not found") return {'validuntil' : validuntil, 'trafficleft' : trafficleft, @@ -154,28 +138,39 @@ class XFSAccount(Account): 'premium' : premium} - def login(self, user, data, req): - if not self.HOSTER_URL: #@TODO: Remove in 0.4.10 - raise Exception(_("Missing HOSTER_DOMAIN")) + def login(self, user, password, data, req): + if self.HOSTER_DOMAIN: + if not self.HOSTER_URL: + self.HOSTER_URL = "http://www.%s/" % self.HOSTER_DOMAIN + + if self.COOKIES: + if isinstance(self.COOKIES, list) and not self.COOKIES.count((self.HOSTER_DOMAIN, "lang", "english")): + self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) + else: + set_cookie(self.req.cj, self.HOSTER_DOMAIN, "lang", "english") + + if not self.HOSTER_URL: + self.login_fail(_("Missing HOSTER_URL")) if not self.LOGIN_URL: self.LOGIN_URL = urlparse.urljoin(self.HOSTER_URL, "login.html") - html = req.load(self.LOGIN_URL, decode=True) - action, inputs = parseHtmlForm('name="FL"', html) + html = self.load(self.LOGIN_URL, cookies=self.COOKIES) + + action, inputs = parse_html_form('name="FL"', html) if not inputs: inputs = {'op' : "login", 'redirect': self.HOSTER_URL} inputs.update({'login' : user, - 'password': data['password']}) + 'password': password}) if action: url = urlparse.urljoin("http://", action) else: url = self.HOSTER_URL - html = req.load(url, post=inputs, decode=True) + html = self.load(url, post=inputs, cookies=self.COOKIES) if re.search(self.LOGIN_FAIL_PATTERN, html): - self.wrongPassword() + self.login_fail() diff --git a/module/plugins/internal/XFSCrypter.py b/module/plugins/internal/XFSCrypter.py index 80eff53ea..4c059d647 100644 --- a/module/plugins/internal/XFSCrypter.py +++ b/module/plugins/internal/XFSCrypter.py @@ -1,12 +1,14 @@ # -*- coding: utf-8 -*- +from module.plugins.internal.Plugin import set_cookie from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo class XFSCrypter(SimpleCrypter): __name__ = "XFSCrypter" __type__ = "crypter" - __version__ = "0.09" + __version__ = "0.13" + __status__ = "testing" __pattern__ = r'^unmatchable$' @@ -19,10 +21,10 @@ 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)' + OFFLINE_PATTERN = r'>\s*(No such user|\w+ (Not Found|file (was|has been) removed|no longer available)' TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)' @@ -32,14 +34,17 @@ class XFSCrypter(SimpleCrypter): account = self.account else: account_name = (self.__name__ + ".py").replace("Folder.py", "").replace(".py", "") - account = self.pyfile.m.core.accountManager.getAccountPlugin(account_name) + account = self.pyload.accountManager.getAccountPlugin(account_name) if account and hasattr(account, "HOSTER_DOMAIN") and account.HOSTER_DOMAIN: self.HOSTER_DOMAIN = account.HOSTER_DOMAIN else: self.fail(_("Missing HOSTER_DOMAIN")) - if isinstance(self.COOKIES, list): - self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) + if self.COOKIES: + if isinstance(self.COOKIES, list) and not self.COOKIES.count((self.HOSTER_DOMAIN, "lang", "english")): + self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) + else: + set_cookie(self.req.cj, self.HOSTER_DOMAIN, "lang", "english") return super(XFSCrypter, self).prepare() diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py index 34e319500..5e0830dc6 100644 --- a/module/plugins/internal/XFSHoster.py +++ b/module/plugins/internal/XFSHoster.py @@ -3,18 +3,19 @@ import pycurl import random import re -import urlparse -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.plugins.captcha.ReCaptcha import ReCaptcha +from module.plugins.captcha.SolveMedia import SolveMedia +from module.plugins.internal.Plugin import set_cookie +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, seconds_to_midnight from module.utils import html_unescape class XFSHoster(SimpleHoster): __name__ = "XFSHoster" __type__ = "hoster" - __version__ = "0.52" + __version__ = "0.57" + __status__ = "testing" __pattern__ = r'^unmatchable$' @@ -27,14 +28,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... + LEECH_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+).*?"' @@ -43,7 +42,6 @@ class XFSHoster(SimpleHoster): ERROR_PATTERN = r'(?:class=["\']err["\'].*?>|<[Cc]enter><b>|>Error</td>|>\(ERROR:)(?:\s*<.+?>\s*)*(.+?)(?:["\']|<|\))' LINK_LEECH_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)' - LINK_PATTERN = None #: final download url pattern CAPTCHA_PATTERN = r'(https?://[^"\']+?/captchas?/[^"\']+)' CAPTCHA_BLOCK_PATTERN = r'>Enter code.*?<div.*?>(.+?)</div>' @@ -51,29 +49,34 @@ class XFSHoster(SimpleHoster): SOLVEMEDIA_PATTERN = None FORM_PATTERN = None - FORM_INPUTS_MAP = None #: dict passed as input_names to parseHtmlForm + FORM_INPUTS_MAP = None #: Dict passed as input_names to parse_html_form def setup(self): - self.chunkLimit = -1 if self.premium else 1 - self.resumeDownload = self.multiDL = self.premium + self.chunk_limit = -1 if self.premium else 1 + self.resume_download = self.multiDL = self.premium def prepare(self): - """ Initialize important variables """ + """ + Initialize important variables + """ if not self.HOSTER_DOMAIN: if self.account: account = self.account else: - account = self.pyfile.m.core.accountManager.getAccountPlugin(self.__name__) + account = self.pyload.accountManager.getAccountPlugin(self.__name__) if account and hasattr(account, "HOSTER_DOMAIN") and account.HOSTER_DOMAIN: self.HOSTER_DOMAIN = account.HOSTER_DOMAIN else: self.fail(_("Missing HOSTER_DOMAIN")) - if isinstance(self.COOKIES, list): - self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) + if self.COOKIES: + if isinstance(self.COOKIES, list) and not self.COOKIES.count((self.HOSTER_DOMAIN, "lang", "english")): + self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english")) + else: + set_cookie(self.req.cj, self.HOSTER_DOMAIN, "lang", "english") if not self.LINK_PATTERN: pattern = r'(?:file: "(.+?)"|(https?://(?:www\.)?([^/]*?%s|\d+\.\d+\.\d+\.\d+)(\:\d+)?(/d/|(/files)?/\d+/\w+/).+?)["\'<])' @@ -82,24 +85,24 @@ class XFSHoster(SimpleHoster): super(XFSHoster, self).prepare() if self.DIRECT_LINK is None: - self.directDL = self.premium + self.direct_dl = self.premium - def handleFree(self, pyfile): + def handle_free(self, pyfile): for i in xrange(1, 6): - self.logDebug("Getting download link #%d" % i) + self.log_debug("Getting download link #%d" % i) - self.checkErrors() + self.check_errors() m = re.search(self.LINK_PATTERN, self.html, re.S) if m: break - data = self.getPostParameters() + data = self.get_post_parameters() self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0) - self.html = self.load(pyfile.url, post=data, decode=True) + self.html = self.load(pyfile.url, post=data) self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 1) @@ -111,24 +114,24 @@ class XFSHoster(SimpleHoster): if m: break else: - self.logError(data['op'] if 'op' in data else _("UNKNOWN")) - return "" + if 'op' in data: + self.error(_("Missing OP data after: ") + data['op']) - self.link = m.group(1).strip() #@TODO: Remove .strip() in 0.4.10 + self.link = m.group(1) - def handlePremium(self, pyfile): - return self.handleFree(pyfile) + def handle_premium(self, pyfile): + return self.handle_free(pyfile) - def handleMulti(self, pyfile): + def handle_multi(self, pyfile): if not self.account: self.fail(_("Only registered or premium users can use url leech feature")) - #only tested with easybytez.com + #: Only tested with easybytez.com self.html = self.load("http://www.%s/" % self.HOSTER_DOMAIN) - action, inputs = self.parseHtmlForm() + action, inputs = self.parse_html_form() upload_id = "%012d" % int(random.random() * 10 ** 12) action += upload_id + "&js_on=1&utype=prem&upload_type=url" @@ -137,19 +140,19 @@ class XFSHoster(SimpleHoster): inputs['url_mass'] = pyfile.url inputs['up1oad_type'] = 'url' - self.logDebug(action, inputs) + self.log_debug(action, inputs) - self.req.setOption("timeout", 600) #: wait for file to upload to easybytez.com + self.req.setOption("timeout", 600) #: Wait for file to upload to easybytez.com self.html = self.load(action, post=inputs) - self.checkErrors() + self.check_errors() - action, inputs = self.parseHtmlForm('F1') + action, inputs = self.parse_html_form('F1') if not inputs: self.retry(reason=self.info['error'] if 'error' in self.info else _("TEXTAREA F1 not found")) - self.logDebug(inputs) + self.log_debug(inputs) stmsg = inputs['st'] @@ -160,38 +163,38 @@ class XFSHoster(SimpleHoster): self.retry(20, 3 * 60, _("Can not leech file")) elif 'today' in stmsg: - self.retry(wait_time=secondsToMidnight(gmt=2), reason=_("You've used all Leech traffic today")) + self.retry(wait_time=seconds_to_midnight(gmt=2), reason=_("You've used all Leech traffic today")) else: self.fail(stmsg) - #get easybytez.com link for uploaded file + #: Get easybytez.com link for uploaded file m = re.search(self.LINK_LEECH_PATTERN, self.html) if m is None: self.error(_("LINK_LEECH_PATTERN not found")) - header = self.load(m.group(1), just_header=True, decode=True) + header = self.load(m.group(1), just_header=True) if 'location' in header: #: Direct download link self.link = header['location'] - def getPostParameters(self): + def get_post_parameters(self): if self.FORM_PATTERN or self.FORM_INPUTS_MAP: - action, inputs = self.parseHtmlForm(self.FORM_PATTERN or "", self.FORM_INPUTS_MAP or {}) + action, inputs = self.parse_html_form(self.FORM_PATTERN or "", self.FORM_INPUTS_MAP or {}) else: - action, inputs = self.parseHtmlForm(input_names={'op': re.compile(r'^download')}) + action, inputs = self.parse_html_form(input_names={'op': re.compile(r'^download')}) if not inputs: - action, inputs = self.parseHtmlForm('F1') + action, inputs = self.parse_html_form('F1') if not inputs: self.retry(reason=self.info['error'] if 'error' in self.info else _("TEXTAREA F1 not found")) - self.logDebug(inputs) + self.log_debug(inputs) if 'op' in inputs: if "password" in inputs: - password = self.getPassword() + password = self.get_password() if password: inputs['password'] = password else: @@ -201,9 +204,9 @@ class XFSHoster(SimpleHoster): m = re.search(self.WAIT_PATTERN, self.html) if m: wait_time = int(m.group(1)) - self.setWait(wait_time, False) + self.set_wait(wait_time, False) - self.handleCaptcha(inputs) + self.handle_captcha(inputs) self.wait() else: inputs['referer'] = self.pyfile.url @@ -218,11 +221,11 @@ class XFSHoster(SimpleHoster): return inputs - def handleCaptcha(self, inputs): + def handle_captcha(self, inputs): m = re.search(self.CAPTCHA_PATTERN, self.html) if m: captcha_url = m.group(1) - inputs['code'] = self.decryptCaptcha(captcha_url) + inputs['code'] = self.captcha.decrypt(captcha_url) return m = re.search(self.CAPTCHA_BLOCK_PATTERN, self.html, re.S) @@ -230,11 +233,11 @@ class XFSHoster(SimpleHoster): captcha_div = m.group(1) numerals = re.findall(r'<span.*?padding-left\s*:\s*(\d+).*?>(\d)</span>', html_unescape(captcha_div)) - self.logDebug(captcha_div) + self.log_debug(captcha_div) inputs['code'] = "".join(a[1] for a in sorted(numerals, key=lambda num: int(num[0]))) - self.logDebug("Captcha code: %s" % inputs['code'], numerals) + self.log_debug("Captcha code: %s" % inputs['code'], numerals) return recaptcha = ReCaptcha(self) @@ -245,7 +248,7 @@ class XFSHoster(SimpleHoster): captcha_key = recaptcha.detect_key() else: - self.logDebug("ReCaptcha key: %s" % captcha_key) + self.log_debug("ReCaptcha key: %s" % captcha_key) if captcha_key: inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge(captcha_key) @@ -259,7 +262,7 @@ class XFSHoster(SimpleHoster): captcha_key = solvemedia.detect_key() else: - self.logDebug("SolveMedia key: %s" % captcha_key) + self.log_debug("SolveMedia key: %s" % captcha_key) if captcha_key: inputs['adcopy_response'], inputs['adcopy_challenge'] = solvemedia.challenge(captcha_key) |