<commit_before>import random
from lazysusan.helpers import (display_exceptions, admin_or_moderator_required,
                               no_arg_command, single_arg_command)
from lazysusan.plugins import CommandPlugin


def best_match(selection, options):
    """Return a single item or a list of possible options."""
    if selection in options:
        return selection
    possibles = [x for x in options if x.startswith(selection)]
    if not possibles:
        return [x for x in options if selection in x]
    elif len(possibles) == 1:
        return possibles[0]
    else:
        return possibles


class Dj(CommandPlugin):
    COMMANDS = {'/autoskip': 'auto_skip',
                '/djdown': 'stop',
                '/djup': 'play',
                '/skip': 'skip_song'}

    @property
    def should_step_down(self):
        return self.is_dj and (len(self.bot.listener_ids) <= 1
                               or len(self.bot.dj_ids) >= self.bot.max_djs)

    @property
    def should_step_up(self):
        return (not self.is_dj and len(self.bot.listener_ids) > 1
                and len(self.bot.dj_ids) < min(2, self.bot.max_djs - 1))

    @property
    def is_dj(self):
        return self.bot.bot_id in self.bot.dj_ids

    @property
    def is_playing(self):
        return self.bot.bot_id == self.bot.api.currentDjId

    def __init__(self, *args, **kwargs):
        super(Dj, self).__init__(*args, **kwargs)
        self.end_song_step_down = False
        self.should_auto_skip = False
        self.register('add_dj', self.dj_update)
        self.register('deregistered', self.dj_update)
        self.register('endsong', self.end_song)
        self.register('newsong', self.new_song)
        self.register('registered', self.dj_update)
        self.register('rem_dj', self.dj_update)

    @no_arg_command
    def auto_skip(self, data):
        """Toggle whether the bot should play anything."""
        self.should_auto_skip = not self.should_auto_skip
        if self.should_auto_skip:
            self.bot.reply('I\'ll just keep this seat warm for you.', data)
            if self.is_playing and len(self.bot.dj_ids) > 1:
                self.bot.api.skip()
        else:
            self.bot.reply('I\'m back baby!', data)

    @display_exceptions
    def dj_update(self, data):
        for user in data['user']:
            if self.bot.bot_id == user['userid']:
                if data['command'] == 'rem_dj':
                    self.should_auto_skip = False
                return  # Ignore updates from the bot

        if self.should_step_down:
            if self.is_playing:
                self.end_song_step_down = True
            else:
                print('Leaving the table')
                self.bot.api.remDj()
        elif self.should_step_up:
            print('Stepping up to DJ')
            self.bot.api.addDj()

    def end_song(self, _):
        if self.end_song_step_down:
            if self.should_step_down:
                print('Delayed leaving the table.')
                self.bot.api.remDj()
            self.end_song_step_down = False

    @display_exceptions
    def new_song(self, _):
        """Called when a new song starts playing."""
        num_djs = len(self.bot.dj_ids)
        if self.is_playing and self.should_auto_skip and num_djs > 1:
            self.bot.api.skip()

    @admin_or_moderator_required
    @no_arg_command
    def play(self, data):
        """Attempt to have the bot dj."""
        if self.is_dj:
            return self.bot.reply('I am already a dj.', data)
        if len(self.bot.dj_ids) < self.bot.max_djs:
            return self.bot.api.addDj()
        self.bot.reply('I can not do that right now.', data)

    @no_arg_command
    def skip_song(self, data):
        """Ask the bot to skip the current song"""
        if not self.is_playing:
            self.bot.reply('I am not currently playing.', data)
        else:
            self.bot.api.skip()
            self.bot.reply(':poop: I was just getting into it.', data)

    @admin_or_moderator_required
    @no_arg_command
    def stop(self, data):
        """Have the bot step down as a dj."""
        if not self.is_dj:
            return self.bot.reply('I am not currently DJing.', data)
        self.bot.api.remDj()


class Playlist(CommandPlugin):
    COMMANDS = {'/pladd': 'add',
                '/plavailable': 'available',
                '/playlists': 'list_playlists',
                '/plclear': 'clear',
                '/plcreate': 'create',
                '/pldelete': 'delete',
                '/pllist': 'list',
                '/plload': 'load',
                '/plshuffle': 'shuffle',
                '/plskip': 'skip_next',
                '/plswitch': 'switch',
                '/plupdate': 'update_playlist'}<commit_msg>Add additional docstrings to botdj plugin.<commit_after>"""A set of LazySusan plugins that control the bot as a dj."""

import random
from lazysusan.helpers import (display_exceptions, admin_or_moderator_required,
                               no_arg_command, single_arg_command)
from lazysusan.plugins import CommandPlugin


def best_match(selection, options):
    """Return the best match from a set of options if possible.

    Return a list when there is not a single viable option.

    """
    if selection in options:
        return selection
    possibles = [x for x in options if x.startswith(selection)]
    if not possibles:
        return [x for x in options if selection in x]
    elif len(possibles) == 1:
        return possibles[0]
    else:
        return possibles


class Dj(CommandPlugin):

    """A plugin that controls whether or not the bot is dj-ing."""

    COMMANDS = {'/autoskip': 'auto_skip',
                '/djdown': 'stop',
                '/djup': 'play',
                '/skip': 'skip_song'}

    @property
    def should_step_down(self):
        """Return true if the bot should stop dj-ing."""
        return self.is_dj and (len(self.bot.listener_ids) <= 1
                               or len(self.bot.dj_ids) >= self.bot.max_djs)

    @property
    def should_step_up(self):
        """Return true if the bot should begin dj-ing."""
        return (not self.is_dj and len(self.bot.listener_ids) > 1
                and len(self.bot.dj_ids) < min(2, self.bot.max_djs - 1))

    @property
    def is_dj(self):
        """Return true if the bot is currently dj-ing."""
        return self.bot.bot_id in self.bot.dj_ids

    @property
    def is_playing(self):
        """Return true if the bot is currently playing a song."""
        return self.bot.bot_id == self.bot.api.currentDjId

    def __init__(self, *args, **kwargs):
        super(Dj, self).__init__(*args, **kwargs)
        self.end_song_step_down = False
        self.should_auto_skip = False
        self.register('add_dj', self.dj_update)
        self.register('deregistered', self.dj_update)
        self.register('endsong', self.end_song)
        self.register('newsong', self.new_song)
        self.register('registered', self.dj_update)
        self.register('rem_dj', self.dj_update)

    @no_arg_command
    def auto_skip(self, data):
        """Toggle whether the bot should play anything."""
        self.should_auto_skip = not self.should_auto_skip
        if self.should_auto_skip:
            self.bot.reply('I\'ll just keep this seat warm for you.', data)
            if self.is_playing and len(self.bot.dj_ids) > 1:
                self.bot.api.skip()
        else:
            self.bot.reply('I\'m back baby!', data)

    @display_exceptions
    def dj_update(self, data):
        """Handle callbacks affecting the users in the room and at the table.

        As a result, the bot may begin or stop dj-ing.

        """
        for user in data['user']:
            if self.bot.bot_id == user['userid']:
                if data['command'] == 'rem_dj':
                    self.should_auto_skip = False
                return  # Ignore updates from the bot

        if self.should_step_down:
            if self.is_playing:
                self.end_song_step_down = True
            else:
                print('Leaving the table')
                self.bot.api.remDj()
        elif self.should_step_up:
            print('Stepping up to dj')
            self.bot.api.addDj()

    def end_song(self, _):
        """Conditionally stop dj-ing at the end of a song."""
        if self.end_song_step_down:
            if self.should_step_down:
                print('Delayed leaving the table.')
                self.bot.api.remDj()
            self.end_song_step_down = False

    @display_exceptions
    def new_song(self, _):
        """Called when a new song starts playing."""
        num_djs = len(self.bot.dj_ids)
        if self.is_playing and self.should_auto_skip and num_djs > 1:
            self.bot.api.skip()

    @admin_or_moderator_required
    @no_arg_command
    def play(self, data):
        """Attempt to have the bot dj."""
        if self.is_dj:
            return self.bot.reply('I am already a dj.', data)
        if len(self.bot.dj_ids) < self.bot.max_djs:
            return self.bot.api.addDj()
        self.bot.reply('I can not do that right now.', data)

    @no_arg_command
    def skip_song(self, data):
        """Ask the bot to skip the current song"""
        if not self.is_playing:
            self.bot.reply('I am not currently playing.', data)
        else:
            self.bot.api.skip()
            self.bot.reply(':poop: I was just getting into it.', data)

    @admin_or_moderator_required
    @no_arg_command
    def stop(self, data):
        """Have the bot step down as a dj."""
        if not self.is_dj:
            return self.bot.reply('I am not currently dj-ing.', data)
        self.bot.api.remDj()


class Playlist(CommandPlugin):
    COMMANDS = {'/pladd': 'add',
                '/plavailable': 'available',
                '/playlists': 'list_playlists',
                '/plclear': 'clear',
                '/plcreate': 'create',
                '/pldelete': 'delete',
                '/pllist': 'list',
                '/plload': 'load',
                '/plshuffle': 'shuffle',
                '/plskip': 'skip_next',
                '/plswitch': 'switch',
                '/plupdate': 'update_playlist'}
{'fraction_non_alphanumeric': 0.11392651788324724, 'fraction_numerical': 0.0015593022122600136, 'mean_word_length': 1.9684697714781603, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2329836', 'n_tokens_mistral': 3260, 'n_tokens_neox': 3075, 'n_words': 818}