# -*- coding: utf-8 -*- 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.14" __status__ = "stable" __threaded__ = [] #@TODO: Remove in 0.4.10 __description__ = """Base addon plugin""" __license__ = "GPLv3" __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] PERIODICAL_INTERVAL = None 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 self.info['ip'] = None #@TODO: Remove in 0.4.10 #: Callback of periodical job task, used by HookManager self.cb = None self.interval = None self.init() self.init_events() @property def activated(self): """ Checks if addon is activated """ return self.get_config("activated") #@TODO: Remove in 0.4.10 def _log(self, level, plugintype, pluginname, messages): plugintype = "addon" if plugintype is "hook" else plugintype return super(Addon, self)._log(level, plugintype, pluginname, messages) 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 set_interval(self, value): newinterval = max(0, self.PERIODICAL_INTERVAL, value) if newinterval != value: return False if newinterval != self.interval: self.interval = newinterval return True def start_periodical(self, interval=None, threaded=False, delay=None): if interval is not None and self.set_interval(interval) is False: return False else: self.cb = self.pyload.scheduler.addJob(max(1, delay), self._periodical, [threaded], threaded=threaded) return True def restart_periodical(self, *args, **kwargs): self.stop_periodical() return self.start_periodical(*args, **kwargs) def stop_periodical(self): try: return self.pyload.scheduler.removeJob(self.cb) finally: self.cb = None def _periodical(self, threaded): try: self.periodical() except Exception, e: self.log_error(_("Error performing periodical task"), e) self.restart_periodical(threaded=threaded, delay=self.interval) def periodical(self): raise NotImplementedError #: Deprecated method, use `activated` property instead (Remove in 0.4.10) def isActivated(self, *args, **kwargs): return self.activated def deactivate(self): """ Called when addon was deactivated """ pass #: Deprecated method, use `deactivate` instead (Remove in 0.4.10) def unload(self, *args, **kwargs): self.store("info", self.info) 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): self.retrieve("info", self.info) if self.PERIODICAL_INTERVAL: self.start_periodical(self.PERIODICAL_INTERVAL, delay=5) 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): self.after_reconnect(ip, self.info['ip']) self.info['ip'] = ip 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)