Source code for csbot.plugins.topic

from collections import defaultdict, deque

from csbot.plugin import Plugin


[docs]class Topic(Plugin): PLUGIN_DEPENDS = ['auth'] CONFIG_DEFAULTS = { 'history': 5, 'start': '', 'sep': '|', 'end': '', }
[docs] def setup(self): super(Topic, self).setup() self.topics = defaultdict(deque)
[docs] def config_get(self, key, channel=None): """A special implementation of :meth:`Plugin.config_get` which looks at a channel-based configuration subsection before the plugin's configuration section. """ default = super(Topic, self).config_get(key) if channel is None: return default else: return self.subconfig(channel).get(key, default)
def _get_delimiters(self, channel): """Get the delimiters for a channel. """ # Start of topic, with a space for padding start = self.config_get('start', channel) if len(start) > 0: start = start + ' ' # Topic element separator, with spaces for padding sep = ' ' + self.config_get('sep', channel) + ' ' # End of topic, with a space for padding end = self.config_get('end', channel) if len(end) > 0: end = ' ' + end return start, sep, end @staticmethod def _split_topic(delim, topic): """Split *topic* according to *delim* (a ``(start, sep, end)`` tuple). """ start, sep, end = delim if len(start) > 0 and topic.startswith(start): topic = topic[len(start):] if len(end) > 0 and topic.endswith(end): topic = topic[:-len(end)] return [s.strip() for s in topic.split(sep)] @staticmethod def _build_topic(delim, parts): """Join *parts* according to *delim* (a ``(start, sep, end)`` tuple). """ start, sep, end = delim return start + sep.join(parts) + end def _get_topic(self, channel): """Get the most recent topic for *channel*. """ return self.topics[channel][-1] def _set_topic(self, e, topic): if not self.bot.plugins['auth'].check_or_error(e, 'topic', e['channel']): return False e.bot.set_topic(e['channel'], topic) return True
[docs] @Plugin.hook('core.channel.topic') def topic_changed(self, e): topics = self.topics[e['channel']] if len(topics) == 0 or e['topic'] != topics[-1]: topics.append(e['topic']) if len(topics) > int(self.config_get('history', e['channel'])): topics.popleft()
[docs] @Plugin.command('topic', help='topic: show current topic as list of parts') def topic(self, e): topic = self._get_topic(e['channel']) delim = self._get_delimiters(e['channel']) parts = self._split_topic(delim, topic) e.reply(repr(parts))
[docs] @Plugin.command('topic.history', help='topic.history: show recent topics') def topic_history(self, e): e.reply(repr(list(self.topics[e['channel']])))
[docs] @Plugin.command('topic.undo', help=('topic.undo: revert to previous topic ' 'see topic.history)')) def topic_undo(self, e): topics = self.topics[e['channel']] if len(topics) < 2: e.reply('error: no history to revert to') return # Attempt to set the topic, and if it was allowed, drop the most recent if self._set_topic(e, topics[-2]): topics.pop()
[docs] @Plugin.command('topic.append', help=('topic.append <text>: append an ' 'element to the topic')) @Plugin.command('topic.push', help=('topic.push <text>: alias ' 'of topic.append')) def topic_append(self, e): delim = self._get_delimiters(e['channel']) parts = self._split_topic(delim, self._get_topic(e['channel'])) parts.append(e['data']) self._set_topic(e, self._build_topic(delim, parts))
[docs] @Plugin.command('topic.pop', help=('topic.pop [position]: remove a ' '0-indexed element from the topic. ' 'Negative positions count from the end, ' 'with -1 being the last.. Default ' 'position is -1 if omitted.')) def topic_pop(self, e): delim = self._get_delimiters(e['channel']) parts = self._split_topic(delim, self._get_topic(e['channel'])) if e['data']: # Try and use provided position, error if it's not an integer try: position = int(e['data']) except ValueError: e.reply('error: invalid topic position') return else: # Default to removing the last item position = -1 # Pop the specified item, error if tho position was invalid try: parts.pop(position) except IndexError: e.reply('error: invalid topic position') return # Update with new topic self._set_topic(e, self._build_topic(delim, parts))
[docs] @Plugin.command('topic.replace', help=('topic.replace <position> <text>: ' 'replace a 0-indexed element in the ' 'topic. Negative positions count ' 'from the end, with -1 being the ' 'last.')) def topic_replace(self, e): delim = self._get_delimiters(e['channel']) parts = self._split_topic(delim, self._get_topic(e['channel'])) # Check number of arguments data_parts = e['data'].split(None, 1) if len(data_parts) != 2: e.reply('error: missing argument') return # Parse position number try: position = int(data_parts[0]) except ValueError: e.reply('error: invalid topic position') return # Set topic part try: parts[position] = data_parts[1] except IndexError: e.reply('error: invalid topic position') return # Update with new topic self._set_topic(e, self._build_topic(delim, parts))
[docs] @Plugin.command('topic.insert', help=('topic.insert <position> <text>: ' 'insert an element at a 0-indexed ' 'position in the title. Negative ' 'positions count from the end')) def topic_insert(self, e): delim = self._get_delimiters(e['channel']) parts = self._split_topic(delim, self._get_topic(e['channel'])) # Check number of arguments data_parts = e['data'].split(None, 1) if len(data_parts) != 2: e.reply('error: missing argument') return # Parse position number try: position = int(data_parts[0]) except ValueError: e.reply('error: invalid topic position') return # Insert topic part try: parts.insert(position, data_parts[1]) except IndexError: e.reply('error: invalid topic position') return # Update with new topic self._set_topic(e, self._build_topic(delim, parts))