diff options
Diffstat (limited to 'pyload/plugins/addons/UpdateManager.py')
-rw-r--r-- | pyload/plugins/addons/UpdateManager.py | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/pyload/plugins/addons/UpdateManager.py b/pyload/plugins/addons/UpdateManager.py new file mode 100644 index 000000000..b30289287 --- /dev/null +++ b/pyload/plugins/addons/UpdateManager.py @@ -0,0 +1,201 @@ +# -*- 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: RaNaN +""" + +import sys +import re +from os import stat +from os.path import join, exists +from time import time + +from module.ConfigParser import IGNORE +from module.network.RequestFactory import getURL +from module.plugins.Hook import threaded, Expose, Hook + +class UpdateManager(Hook): + __name__ = "UpdateManager" + __version__ = "0.15" + __description__ = """checks for updates""" + __config__ = [("activated", "bool", "Activated", "True"), + ("interval", "int", "Check interval in minutes", "480"), + ("debug", "bool", "Check for plugin changes when in debug mode", False)] + __author_name__ = ("RaNaN") + __author_mail__ = ("ranan@pyload.org") + + URL = "http://get.pyload.org/check2/%s/" + MIN_TIME = 3 * 60 * 60 # 3h minimum check interval + + @property + def debug(self): + return self.core.debug and self.getConfig("debug") + + def setup(self): + if self.debug: + self.logDebug("Monitoring file changes") + self.interval = 4 + self.last_check = 0 #timestamp of updatecheck + self.old_periodical = self.periodical + self.periodical = self.checkChanges + self.mtimes = {} #recordes times + else: + self.interval = max(self.getConfig("interval") * 60, self.MIN_TIME) + + self.updated = False + self.reloaded = True + self.version = "None" + + self.info = {"pyload": False, "plugins": False} + + @threaded + def periodical(self): + + updates = self.checkForUpdate() + if updates: + self.checkPlugins(updates) + + if self.updated and not self.reloaded: + self.info["plugins"] = True + self.logInfo(_("*** Plugins have been updated, please restart pyLoad ***")) + elif self.updated and self.reloaded: + self.logInfo(_("Plugins updated and reloaded")) + self.updated = False + elif self.version == "None": + self.logInfo(_("No plugin updates available")) + + @Expose + def recheckForUpdates(self): + """recheck if updates are available""" + self.periodical() + + def checkForUpdate(self): + """checks if an update is available, return result""" + + try: + if self.version == "None": # No updated known + version_check = getURL(self.URL % self.core.api.getServerVersion()).splitlines() + self.version = version_check[0] + + # Still no updates, plugins will be checked + if self.version == "None": + self.logInfo(_("No Updates for pyLoad")) + return version_check[1:] + + + self.info["pyload"] = True + self.logInfo(_("*** New pyLoad Version %s available ***") % self.version) + self.logInfo(_("*** Get it here: http://pyload.org/download ***")) + + except: + self.logWarning(_("Not able to connect server for updates")) + + return None # Nothing will be done + + + def checkPlugins(self, updates): + """ checks for plugins updates""" + + # plugins were already updated + if self.info["plugins"]: return + + reloads = [] + + vre = re.compile(r'__version__.*=.*("|\')([0-9.]+)') + url = updates[0] + schema = updates[1].split("|") + updates = updates[2:] + + for plugin in updates: + info = dict(zip(schema, plugin.split("|"))) + filename = info["name"] + prefix = info["type"] + version = info["version"] + + if filename.endswith(".pyc"): + name = filename[:filename.find("_")] + else: + name = filename.replace(".py", "") + + #TODO: obsolete in 0.5.0 + if prefix.endswith("s"): + type = prefix[:-1] + else: + type = prefix + + plugins = getattr(self.core.pluginManager, "%sPlugins" % type) + + if name in plugins: + if float(plugins[name]["v"]) >= float(version): + continue + + if name in IGNORE or (type, name) in IGNORE: + continue + + self.logInfo(_("New version of %(type)s|%(name)s : %(version).2f") % { + "type": type, + "name": name, + "version": float(version) + }) + + try: + content = getURL(url % info) + except Exception, e: + self.logWarning(_("Error when updating %s") % filename, str(e)) + continue + + m = vre.search(content) + if not m or m.group(2) != version: + self.logWarning(_("Error when updating %s") % name, _("Version mismatch")) + continue + + f = open(join("userplugins", prefix, filename), "wb") + f.write(content) + f.close() + self.updated = True + + reloads.append((prefix, name)) + + self.reloaded = self.core.pluginManager.reloadPlugins(reloads) + + def checkChanges(self): + + if self.last_check + max(self.getConfig("interval") * 60, self.MIN_TIME) < time(): + self.old_periodical() + self.last_check = time() + + modules = filter( + lambda m: m and (m.__name__.startswith("module.plugins.") or m.__name__.startswith("userplugins.")) and m.__name__.count(".") >= 2, + sys.modules.itervalues()) + + reloads = [] + + for m in modules: + root, type, name = m.__name__.rsplit(".", 2) + id = (type, name) + if type in self.core.pluginManager.plugins: + f = m.__file__.replace(".pyc", ".py") + if not exists(f): continue + + mtime = stat(f).st_mtime + + if id not in self.mtimes: + self.mtimes[id] = mtime + elif self.mtimes[id] < mtime: + reloads.append(id) + self.mtimes[id] = mtime + + self.core.pluginManager.reloadPlugins(reloads) |