From f5aa3f5257d678aa005dffa527f22a1a578058d1 Mon Sep 17 00:00:00 2001 From: Andrei Date: Fri, 7 Oct 2016 06:14:44 -0500 Subject: [PATCH] Add plugin schedules (repeating functions) and Message.member prop --- disco/bot/plugin.py | 33 +++++++++++++++++++++++++++++++++ disco/types/message.py | 10 ++++++++++ 2 files changed, 43 insertions(+) diff --git a/disco/bot/plugin.py b/disco/bot/plugin.py index 3139c87..d37406b 100644 --- a/disco/bot/plugin.py +++ b/disco/bot/plugin.py @@ -1,5 +1,6 @@ import inspect import functools +import gevent from holster.emitter import Priority @@ -83,6 +84,16 @@ class PluginDeco(object): 'type': 'post_listener', }) + @classmethod + def schedule(cls, interval=60): + """ + Runs a function repeatedly, waiting for a specified interval + """ + return cls.add_meta_deco({ + 'type': 'schedule', + 'interval': interval, + }) + class Plugin(LoggingClass, PluginDeco): """ @@ -115,6 +126,7 @@ class Plugin(LoggingClass, PluginDeco): self.listeners = [] self.commands = {} + self.schedules = {} self._pre = {'command': [], 'listener': []} self._post = {'command': [], 'listener': []} @@ -126,6 +138,8 @@ class Plugin(LoggingClass, PluginDeco): self.register_listener(member, meta['event_name'], meta['priority']) elif meta['type'] == 'command': self.register_command(member, *meta['args'], **meta['kwargs']) + elif meta['type'] == 'schedule': + self.register_schedule(member, meta['interval']) elif meta['type'].startswith('pre_') or meta['type'].startswith('post_'): when, typ = meta['type'].split('_', 1) self.register_trigger(typ, when, member) @@ -193,6 +207,25 @@ class Plugin(LoggingClass, PluginDeco): wrapped = functools.partial(self._dispatch, 'command', func) self.commands[func.__name__] = Command(self, wrapped, *args, **kwargs) + def register_schedule(self, func, interval): + """ + Registers a function to be called repeatedly, waiting for an interval + duration. + + Args + ---- + func : function + The function to be registered. + interval : int + Interval (in seconds) to repeat the function on. + """ + def repeat(): + while True: + func() + gevent.sleep(interval) + + self.schedules[func.__name__] = gevent.spawn(repeat) + def destroy(self): """ Destroys the plugin (removing all listeners) diff --git a/disco/types/message.py b/disco/types/message.py index d3aa2e6..de6d96e 100644 --- a/disco/types/message.py +++ b/disco/types/message.py @@ -136,6 +136,16 @@ class Message(Model): """ return self.channel.guild + @cached_property + def member(self): + """ + Returns + ------- + :class:`disco.types.guild.GuildMember` + The guild member (if applicable) that sent this message. + """ + return self.channel.guild.get_member(self.author) + @cached_property def channel(self): """