示例#1
0
    async def xp(self, context, who='me'):
        """
        Checks your Experience Points and Level. Use the 'top' flag to see the top 10 on this server.
        Examples:
            !xp - Shows your level/xp
            !xp top - Shows the top 10 users on this server
        """

        guild_id = context.guild.id
        user_id = context.message.author.id

        if who == 'top':

            guild = Guild(context.guild)
            users = guild.get_top_xp()
            output = ':trophy: **' + lib.get_string(
                'xp:leaderboard', guild_id) + '** :trophy: \n\n'
            for key in range(len(users)):
                user = users[key]
                output += str(key + 1) + '. ' + user.get_name(
                ) + ' - ' + user.get_xp_bar() + '\n'

        else:
            user = User(user_id, guild_id)
            xp = user.get_xp()

            # Either display a message saying they have no XP, or display the XP bar for the user
            if xp is None:
                output = context.message.author.mention + ', ' + lib.get_string(
                    'xp:noxp', guild_id)
            else:
                output = context.message.author.mention + ', ' + lib.get_string(
                    'youare', guild_id) + ' ' + user.get_xp_bar()

        await context.send(output)
    async def reassure(self, context, who=None):
        """
        Reassures you that everything will be okay.

        Examples: !reassure
        """
        if not Guild(context.guild).is_command_enabled('reassure'):
            return await context.send(lib.get_string('err:disabled', context.guild.id))

        guild_id = context.guild.id

        # If no name passed through, default to the author of the command
        if who is None:
            mention = context.message.author.mention
        else:

            # We must now mention the user directly, as we can't easily lookup users any more
            if not who.startswith('<@!') or not who.endswith('>'):
                return await context.send( lib.get_string('reassure:nomention', guild_id) )

            mention = who

        # Load the JSON file with the quotes
        messages = lib.get_asset('reassure', guild_id)

        max = len(messages) - 1
        quote = messages[random.randint(1, max)]

        # Send the message
        await context.send( mention + ', ' + format(quote) )
    async def remind(self, context, *opts):
        """
        Set or configure a reminder
        @param opts:
        @param context:
        @return:
        """
        if not Guild(context.guild).is_command_enabled('remind'):
            return await context.send(lib.get_string('err:disabled', context.guild.id))

        user = User(context.message.author.id, context.guild.id, context)

        # Does the user have a timezone setup? If not, can't do anything.
        if not lib.is_valid_timezone(user.get_setting('timezone')):
            return await context.send(user.get_mention() + ', ' + lib.get_string('err:notimezone', user.get_guild()))

        # Convert the natural language of the command into variables.
        cmd = ' '.join(opts)

        # Check what we are trying to do with reminders.
        if cmd.lower() == 'list':
            return await self.run_list(context, user)
        elif cmd.lower() == 'delete':
            return await self.run_delete(context, user)
        else:
            return await self.run_remind(context, user, cmd)
示例#4
0
    async def ask(self, context, type=None):
        """
        Asks you a random question about your character or your world, to get the creative juices flowing.
        Initial questions taken from (novel-software).

        Examples:
            !ask c(haracter) - Asks you a question about your character
            !ask w(orld) - Asks you a question about your world
        """
        if not Guild(context.guild).is_command_enabled('ask'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        user = User(context.message.author.id, context.guild.id, context)

        # Check the arguments were all supplied and get a dict list of them and their values, after any prompts
        args = await self.check_arguments(context, type=type)
        if not args:
            return

        # Overwrite the variables passed in, with the values from the prompt and convert to lowercase
        type = args['type'].lower()

        if type in ('c', 'char', 'character'):
            options = lib.get_asset('q_char', user.get_guild())
        elif type in ('w', 'world'):
            options = lib.get_asset('q_world', user.get_guild())

        max = len(options) - 1
        rand = random.randint(1, max)
        question = options[rand]
        await context.send(f'[{rand}] {question}')
示例#5
0
    async def xp(self, context, who='me'):
        """
        Checks your Experience Points and Level. Use the 'top' flag to see the top 10 on this server.
        Examples:
            !xp - Shows your level/xp
            !xp top - Shows the top 10 users on this server
        """
        if not Guild(context.guild).is_command_enabled('xp'):
            return await context.send(lib.get_string('err:disabled', context.guild.id))

        guild_id = context.guild.id
        user_id = context.message.author.id

        if who == 'top':

            title = context.guild.name + ' - ' + lib.get_string('xp:leaderboard', guild_id)
            embed = discord.Embed(title=title, color=discord.Color.red(), description=None)
            embed.add_field(name=lib.get_string('xp:leaderboard', guild_id), value='Leaderboard temporarily disabled until a fix can be implemented', inline=False)
            return await context.send(embed=embed)

        else:
            user = User(user_id, guild_id)
            xp = user.get_xp()

            # Either display a message saying they have no XP, or display the XP bar for the user
            if xp is None:
                output = context.message.author.mention + ', ' + lib.get_string('xp:noxp', guild_id)
            else:
                output = context.message.author.mention + ', ' + lib.get_string('youare', guild_id) + ' ' + user.get_xp_bar()

        await context.send(output)
    async def end(self, context=None, bot=None):
        """
        Mark the 'end' time of the sprint as 0 in the database and ask for final word counts
        :return:
        """

        # End the sprint in the database
        self.set_ended()

        if bot is None:
            bot = self.bot

        # Get the sprinting users to notify
        notify = self.get_notifications(self.get_users())

        # Check for a guild setting for the delay time, otherwise use the default
        guild = Guild.get_from_bot(bot, self._guild)
        delay = guild.get_setting('sprint_delay_end')
        if delay is None:
            delay = self.DEFAULT_POST_DELAY

        # Post the ending message
        message = lib.get_string('sprint:end', self._guild).format(delay)
        message = message + ', '.join(notify)
        await self.say(message, context, bot)

        # Convert the minutes to seconds
        delay = int(delay) * 60
        task_time = int(time.time()) + delay

        # Schedule the cron task
        Task.schedule(self.TASKS['complete'], task_time, 'sprint', self._id)
示例#7
0
    async def _8ball(self, context, question=None):
        """
        Ask the magic 8-ball a question. Your question will be routed to a text-processing AI in order to properly analyze the content of the question and provide a meaningful answer.

        Examples: !8ball Should I do some writing?
        """
        if not Guild(context.guild).is_command_enabled('8ball'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        guild_id = context.guild.id

        # Check the arguments were all supplied and get a dict list of them and their values, after any prompts
        args = await self.check_arguments(context, question=question)
        if not args:
            return

        # Overwrite variable from check_arguments()
        question = args['question']

        # Create array of possible answers to choose from
        answers = []

        # Load all 21 possible answers into an array to pick from
        for i in range(21):
            answers.append(lib.get_string('8ball:' + format(i), guild_id))

        # Pick a random answer
        answer = random.choice(answers)

        # Send the message
        await context.send(context.message.author.mention + ', ' +
                           format(answer))
示例#8
0
    async def setting(self, context, setting=None, value=None):
        """
        Lets you update a setting for the server, if you have the permissions to manage_guild

        Examples:
            !setting lang en - Set the language to be used. Available language packs: en
            !setting sprint_delay_end 5 - Set the timer delay between the sprint finishing and the final word counts being tallied. Max time: 15 mins. Default: 2 mins.
            !setting list - Displays a list of all the custom server settings
        """
        user = User(context.message.author.id, context.guild.id, context)
        guild = Guild(context.guild)

        # If we want to list the setting, do that instead.
        if setting is not None and setting.lower() == 'list':
            settings = guild.get_settings()
            output = '```ini\n'
            if settings:
                for setting, value in settings.items():
                    output += setting + '=' + str(value) + '\n'
            else:
                output += lib.get_string('setting:none', guild.get_id())
            output += '```'
            return await context.send(output)

        # Otherwise, continue on as we must be trying to set a setting value
        # Check the arguments are valid
        args = await self.check_arguments(context,
                                          setting=setting,
                                          value=value)
        if not args:
            return

        setting = args['setting'].lower()
        value = args['value']

        # Check that the value is valid for the setting they are updating
        if setting == 'sprint_delay_end' and (not lib.is_number(value)
                                              or int(value) < 1):
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('setting:err:sprint_delay_end', guild.get_id()))

        if setting == 'lang' and not lib.is_supported_language(value):
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('setting:err:lang', guild.get_id()).format(
                    ', '.join(lib.get_supported_languages())))

        guild.update_setting(setting, value)
        return await context.send(user.get_mention() + ', ' + lib.get_string(
            'setting:updated', guild.get_id()).format(setting, value))
示例#9
0
    async def event(self, context, cmd=None, *opts):
        """
        event create My Event Title - Create an event called "My Event Title" | Permissions required: [MANAGE_MESSAGES],
        event rename My New Event Title - Rename event to "My New Event Title" | Permissions required: [MANAGE_MESSAGES],
        event description This is the description - Set the description of the event to "This is the description" | Permissions required: [MANAGE_MESSAGES],
        event image https://i.imgur.com/tJtAdNs.png - Set the thumbnail image for the event to the image URL specified | Permissions required: [MANAGE_MESSAGES],
        event delete - Deletes the current event | Permissions required: [MANAGE_MESSAGES],
        event schedule - Starts the event scheduling wizard. Please pay attention to the date/time formats, they must be entered exactly as the bot expects | Permissions required: [MANAGE_MESSAGES],
        event unschedule - Removes the schedule from the event
        event start - Manually starts the current event | Permissions required: [MANAGE_MESSAGES],
        event end - Manually ends the current event | Permissions required: [MANAGE_MESSAGES],
        event time - Checks how long until the event ends or starts,
        event update 500 - Updates your event word count to 500 total words,
        event me - Checks your current event word count,
        event top - Checks the word count leaderboard for the current event
        event info - Checks the information/status of the event
        """
        if not Guild(context.guild).is_command_enabled('event'):
            return await context.send(lib.get_string('err:disabled', context.guild.id))

        # Check the arguments were all supplied and get a dict list of them and their values, after any prompts
        args = await self.check_arguments(context, cmd=cmd)
        if not args:
            return

        # Overwrite the variables passed in, with the values from the prompt and convert to lowercase
        cmd = args['cmd'].lower()

        if cmd == 'create':
            return await self.run_create(context, opts)
        elif cmd == 'delete':
            return await self.run_delete(context)
        elif cmd == 'rename':
            return await self.run_rename(context, opts)
        elif cmd == 'desc' or cmd == 'description':
            return await self.run_set(context, 'description', opts)
        elif cmd == 'img' or cmd == 'image':
            return await self.run_set(context, 'image', opts)
        elif cmd == 'colour' or cmd == 'color':
            return await self.run_set(context, 'colour', opts)
        elif cmd == 'start':
            return await self.run_start(context)
        elif cmd == 'end':
            return await self.run_end(context)
        elif cmd == 'time' or cmd == 'left':
            return await self.run_time(context)
        elif cmd == 'update':
            return await self.run_update(context, opts)
        elif cmd == 'me':
            return await self.run_me(context)
        elif cmd == 'schedule':
            return await self.run_schedule(context)
        elif cmd == 'unschedule':
            return await self.run_unschedule(context)
        elif cmd == 'info':
            return await self.run_info(context)
        elif cmd == 'top' or cmd == 'leaderboard':
            return await self.run_top(context)
    async def generate(self, context, type=None, amount=None):
        """
        Random generator for various things (character names, place names, land names, book titles, story ideas, prompts).
        Define the type of item you wanted generated and then optionally, the amount of items to generate.

        Examples:
            !generate char - generates 10 character names
            !generate place 20 - generates 20 fantasy place names
            !generate land - generates 10 fantasy land/world names
            !generate book - generates 10 general fiction book titles
            !generate book_fantasy - generates 10 fantasy book titles
            !generate book_sf - generates 10 sci-fi book titles
            !generate book_horror - generates 10 horror book titles
            !generate book_rom - generates 10 romance/erotic book titles
            !generate book_mystery - generates 10 mystery book titles
            !generate book_hp - generates 10 Harry Potter book title
            !generate idea - generates a random story idea
            !generate prompt - generates a story prompt
            !generate face - generates a random person's face
        """
        if not Guild(context.guild).is_command_enabled('generate'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        user = User(context.message.author.id, context.guild.id, context)

        # If no amount specified, use the default
        if amount is None:
            amount = NameGenerator.DEFAULT_AMOUNT

        # Check the arguments are valid
        args = await self.check_arguments(context, type=type, amount=amount)
        if not args:
            return

        type = args['type'].lower()
        amount = int(args['amount'])

        # For faces, we want to just call an API url.
        if type == 'face':
            return await context.send(self._urls['face'] + '?t=' +
                                      str(int(time.time())))

        generator = NameGenerator(type, context)
        results = generator.generate(amount)
        join = '\n'

        # For prompts, add an extra line between them.
        if type == 'prompt':
            join += '\n'

        names = join.join(results['names'])

        return await context.send(user.get_mention() + ', ' +
                                  results['message'] + names)
示例#11
0
    async def reset(self, context, what=None, confirm=None):
        """
        Lets you reset your statistics/records.

        Examples:
            !reset pb: Resets your wpm personal best
            !reset wc: Resets your total word count
            !reset xp: Resets your xp/level to 0
            !reset all: Resets your xp/levels, stats, records, goals and challenges
        """
        if not Guild(context.guild).is_command_enabled('reset'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        user = User(context.message.author.id, context.guild.id, context)

        # Check the arguments are valid
        args = await self.check_arguments(context, what=what, confirm=confirm)
        if not args:
            return

        what = args['what'].lower()
        confirm = args['confirm'].lower()

        # Make sure they confirmed it, otherwise just stop and display an OK message
        if confirm not in ('y', 'yes'):
            output = 'OK'
            return await context.send(user.get_mention() + ', ' + output)

        # Personal Best
        if what == 'pb':
            user.update_record('wpm', 0)
            output = lib.get_string('reset:pb', user.get_guild())

        elif what == 'wc':
            user.update_stat('total_words_written', 0)
            output = lib.get_string('reset:wc', user.get_guild())

        elif what == 'xp':
            await user.update_xp(0)
            output = lib.get_string('reset:xp', user.get_guild())

        elif what == 'projects':
            user.reset_projects()
            output = lib.get_string('reset:projects', user.get_guild())

        elif what == 'all':
            user.reset()
            output = lib.get_string('reset:done', user.get_guild())

        return await context.send(user.get_mention() + ', ' + output)
示例#12
0
    async def flip(self, context):
        """
        Flips a coin.

        Examples: !flip
        """
        if not Guild(context.guild).is_command_enabled('flip'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        guild_id = context.guild.id
        rand = random.randrange(2)
        side = 'heads' if rand == 0 else 'tails'

        await context.send(lib.get_string('flip:' + side, guild_id))
示例#13
0
    async def roll(self, context, roll='1d6'):
        """
        Rolls a dice between 1-6, or 1 and a specified number (max 100). Can also roll multiple dice at once (max 100) and get the total.
        Examples:
            !roll - Rolls one 6-sided die.
            !roll 1d8 - Rolls one 8-sided die.
            !roll 3d20 - Rolls three 20-sided dice.
            !roll 100d100 - Rolls the maximum, one-hundred 100-sided dice.
        """
        if not Guild(context.guild).is_command_enabled('roll'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        guild_id = context.guild.id

        # Make sure the format is correct (1d6)
        try:
            sides = int(roll.split('d')[1])
            rolls = int(roll.split('d')[0])
        except Exception as e:
            await context.send(lib.get_string('roll:format', guild_id))
            return

        if sides < 1:
            sides = 1
        elif sides > self.MAX_SIDES:
            sides = self.MAX_SIDES

        if rolls < 1:
            rolls = 1
        elif rolls > self.MAX_ROLLS:
            rolls = self.MAX_ROLLS

        total = 0
        output = ''

        # Roll the dice {rolls} amount of times
        for x in range(rolls):

            val = random.randint(1, sides)
            total += val
            output += ' [ ' + str(val) + ' ] '

        # Now print out the total
        output += '\n**' + lib.get_string('roll:total',
                                          guild_id) + str(total) + '**'

        await context.send(output)
示例#14
0
    async def profile(self, context):
        """
        Displays your Writer-Bot profile information and statistics.
        """

        if not Guild(context.guild).is_command_enabled('profile'):
            return await context.send(lib.get_string('err:disabled', context.guild.id))

        user = User(context.message.author.id, context.guild.id, context)
        goals = {
            'daily': user.get_goal_progress('daily')
        }
        profile = {
            'lvlxp': user.get_xp_bar(),
            'words': user.get_stat('total_words_written'),
            'words_sprints': user.get_stat('sprints_words_written'),
            'sprints_started': user.get_stat('sprints_started'),
            'sprints_completed': user.get_stat('sprints_completed'),
            'sprints_won': user.get_stat('sprints_won'),
            'challenges_completed': user.get_stat('challenges_completed'),
            'daily_goals_completed': user.get_stat('daily_goals_completed'),
            'weekly_goals_completed': user.get_stat('weekly_goals_completed'),
            'monthly_goals_completed': user.get_stat('monthly_goals_completed'),
            'yearly_goals_completed': user.get_stat('yearly_goals_completed'),
        }

        embed = discord.Embed(title=user.get_name(), color=3066993)

        embed.add_field(name=lib.get_string('profile:lvlxp', user.get_guild()), value=profile['lvlxp'], inline=True)
        embed.add_field(name=lib.get_string('profile:words', user.get_guild()), value=profile['words'], inline=True)
        embed.add_field(name=lib.get_string('profile:wordssprints', user.get_guild()), value=profile['words_sprints'], inline=True)
        embed.add_field(name=lib.get_string('profile:sprintsstarted', user.get_guild()), value=profile['sprints_started'], inline=True)
        embed.add_field(name=lib.get_string('profile:sprintscompleted', user.get_guild()), value=profile['sprints_completed'], inline=True)
        embed.add_field(name=lib.get_string('profile:sprintswon', user.get_guild()), value=profile['sprints_won'], inline=True)
        embed.add_field(name=lib.get_string('profile:challengescompleted', user.get_guild()), value=profile['challenges_completed'], inline=True)
        embed.add_field(name=lib.get_string('profile:dailygoalscompleted', user.get_guild()), value=profile['daily_goals_completed'], inline=True)
        embed.add_field(name=lib.get_string('profile:weeklygoalscompleted', user.get_guild()), value=profile['weekly_goals_completed'], inline=True)
        embed.add_field(name=lib.get_string('profile:monthlygoalscompleted', user.get_guild()), value=profile['monthly_goals_completed'], inline=True)
        embed.add_field(name=lib.get_string('profile:yearlygoalscompleted', user.get_guild()), value=profile['yearly_goals_completed'], inline=True)


        # Send the message
        await context.send(embed=embed)
示例#15
0
    async def ask(self, context, flag=None, flag2=None):
        """
        Generates a random writing challenge for you. e.g. "Write 400 words in 15 minutes".
        You can add the flags "easy", "normal", "hard", "hardcore", or "insane" to choose a pre-set wpm,
        or add your chosen wpm (words per minute) as the flag, suffixed with "wpm", eg. "30wpm",
        or you can specify a time instead by adding a the time in minutes, suffixed with a "m", e.g. "15m".

        If you do not specify any flags with the command, the challenge will be completely random.

        Examples:
            !challenge - Generates an entirely random writing challenge,
            !challenge easy - Generates a random writing challenge, at 5 wpm (20xp).
            !challenge normal - Generates a random writing challenge, at 10 wpm (40xp).
            !challenge hard - Generates a random writing challenge, at 20 wpm (75xp).
            !challenge hardcore - Generates a random writing challenge, at 40 wpm (100xp).
            !challenge insane - Generates a random writing challenge, at 60 wpm (150xp).
            !challenge 10wpm - Generates a random writing challenge, at 10 wpm.
            !challenge 15m - Generates a random writing challenge, with a duration of 15 minutes.
            !challenge normal 18m - Generates a writing challenge, at normal difficulty, for 18 minutes.
            !challenge cancel - Cancels your current challenge.
            !challenge done|complete - Completes your current challenge.
        """
        if not Guild(context.guild).is_command_enabled('challenge'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        # Check the arguments are valid
        args = await self.check_arguments(context, flag=flag, flag2=flag2)
        if not args:
            return

        if flag is not None:
            flag = args['flag'].lower()

        if flag2 is not None:
            flag2 = args['flag2'].lower()

        if flag == 'cancel':
            await self.run_cancel(context)
        elif flag == 'done' or flag == 'complete':
            await self.run_complete(context)
        else:
            await self.run_challenge(context, flag, flag2)
示例#16
0
    async def quote(self, context):
        """
        A random motivational quote to inspire you.

        Examples: !quote
        """
        if not Guild(context.guild).is_command_enabled('quote'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        guild_id = context.guild.id

        # Load the JSON file with the quotes
        quotes = lib.get_asset('quotes', guild_id)

        max = len(quotes) - 1
        quote = quotes[random.randint(1, max)]

        # Send the message
        await context.send(
            format(quote['quote'] + ' - *' + quote['name'] + '*'))
示例#17
0
    async def goal(self, context, option=None, type=None, value=None):
        """
        Sets a daily goal which resets every 24 hours at midnight in your timezone.

        Examples:
            !goal - Print a table of all your goals, with their progress and next reset time.
            !goal check daily - Checks how close you are to your daily goal
            !goal set weekly 500 - Sets your weekly goal to be 500 words per day
            !goal cancel monthly - Deletes your monthly goal
            !goal time daily - Checks how long until your daily goal resets
        """
        if not Guild(context.guild).is_command_enabled('goal'):
            return await context.send(lib.get_string('err:disabled', context.guild.id))

        user = User(context.message.author.id, context.guild.id, context)

        # If no option is sent and we just do `goal` then display a table of all their goals.
        if option is None:
            return await self.run_check_all(context)

        # Otherwise, we must specify a type.
        if type is None or type not in self.types:
            return await context.send(user.get_mention() + ', ' + lib.get_string('goal:invalidtype', user.get_guild()))

        if option == 'set':
            return await self.run_set(context, type, value)
        elif option == 'cancel' or option == 'delete' or option == 'reset':
            return await self.run_cancel(context, type)
        elif option == 'time':
            return await self.run_time(context, type)
        elif option == 'check':
            return await self.run_check(context, type)
        elif option == 'history':
            return await self.run_history(context, type)
        elif option == 'update':
            return await self.run_update(context, type, value)
        else:
            return await context.send(user.get_mention() + ', ' + lib.get_string('goal:invalidoption', user.get_guild()))
示例#18
0
    async def wrote(self, context, amount=None, shortname=None):
        """
        Adds to your total words written statistic.

        Examples:
            !wrote 250 - Adds 250 words to your total words written
            !wrote 200 sword - Adds 200 words to your Project with the shortname "sword". (See: Projects for more info).
        """
        user = User(context.message.author.id, context.guild.id, context)

        if not Guild(context.guild).is_command_enabled('wrote'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        # Check the arguments are valid
        args = await self.check_arguments(context,
                                          amount=amount,
                                          shortname=shortname)
        if not args:
            return

        amount = args['amount']
        shortname = args['shortname']
        message = None

        # If they were writing in a Project, update its word count.
        if shortname is not None:

            project = user.get_project(shortname.lower())

            # Make sure the project exists.
            if not project:
                return await context.send(
                    user.get_mention() +
                    ', ' + lib.get_string('project:err:noexists',
                                          user.get_guild()).format(shortname))

            project.add_words(amount)

            written_stat = user.get_stat('total_words_written')
            if written_stat is None:
                written_stat = 0
            total = int(written_stat) + int(amount)

            message = lib.get_string('wrote:addedtoproject',
                                     user.get_guild()).format(
                                         str(amount), project.get_title(),
                                         project.get_words(), total)

        # # Is there an Event running?
        event = Event.get_by_guild(user.get_guild())
        if event and event.is_running():
            event.add_words(user.get_id(), amount)

        # Increment their words written statistic
        user.add_stat('total_words_written', amount)

        # Update their words towards their goals
        await user.add_to_goals(amount)

        # Output message
        if message is None:
            total = user.get_stat('total_words_written')
            message = lib.get_string('wrote:added', user.get_guild()).format(
                str(amount), str(total))

        await context.send(user.get_mention() + ', ' + message)
示例#19
0
    async def sprint(self, context, cmd=None, opt1=None, opt2=None, opt3=None):
        """
        Write with your friends and see who can write the most in the time limit!
        When choosing a length and start delay, there are maximums of 60 minutes length of sprint, and 24 hours delay until sprint begins.
        NOTE: The bot checks for sprint changes every 30 seconds, so your start/end times might be off by +-30 seconds or so.

        Run `help sprint` for more extra information, including any custom server settings related to sprints.

        Examples:
            `sprint start` - Quickstart a sprint with the default settings.
            `sprint for 20 in 3` - Schedules a sprint for 20 minutes, to start in 3 minutes.
            `sprint cancel` - Cancels the current sprint. This can only be done by the person who created the sprint, or any users with the MANAGE_MESSAGES permission.
            `sprint join` - Joins the current sprint.
            `sprint join 100` - Joins the current sprint, with a starting word count of 100.
            `sprint join 100 sword` - Joins the current sprint, with a starting word count of 100 and sets your sprint to count towards your Project with the shortname "sword" (See: Projects for more info).
            `sprint join same` - Use the keyword `same` to join the sprint using the same Project and Final Word Count from your most recent sprint.
            `sprint leave` - Leaves the current sprint.
            `sprint project sword` - Sets your sprint to count towards your Project with the shortname "sword" (See: Projects for more info).
            `sprint wc 250` - Declares your final word count at 250.
            `sprint time` - Displays the time left in the current sprint.
            `sprint pb` - Displays your personal best wpm from sprints on this server. Run sprint pb reset to reset your personal best to 0 on the current server.
            `sprint notify` - You will be notified when someone starts a new sprint.
            `sprint forget` - You will no longer be notified when someone starts a new sprint.
            `sprint status` - Shows you your current word count on the sprint.

        **Sprint Tips**
        If you join the sprint with a starting word count, remember to declare your total word count at the end, not just the amount of words you wrote in the sprint.
        e.g. If you joined with 1000 words, and during the sprint you wrote another 500 words, the final word count you should declare would be 1500
        """
        user = User(context.message.author.id, context.guild.id, context)

        if not Guild(context.guild).is_command_enabled('sprint'):
            return await context.send(lib.get_string('err:disabled', context.guild.id))

        # Check the arguments are valid
        args = await self.check_arguments(context, cmd=cmd, opt1=opt1, opt2=opt2, opt3=opt3)
        if not args:
            return

        # Convert cmd to lowercase
        cmd = args['cmd'].lower()

        # Start a sprint
        if cmd == 'start':
            return await self.run_start(context)

        elif cmd == 'for':

            length = opt1

            # If the second option is invalid, display an error message
            if opt2 is not None and opt2.lower() not in ['now', 'in', 'at']:
                return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:for:unknown', user.get_guild()))

            # If they left off the last argument and just said `sprint for 20` then assume they mean now.
            if opt2 is None:
                opt2 = 'now'

            # Get the delay they want before starting the sprint.
            if opt2.lower() == 'now':
                delay = 0
            elif opt2.lower() == 'in':
                delay = opt3
            elif opt2.lower() == 'at':

                # Make sure the user has set their timezone, otherwise we can't calculate it.
                timezone = user.get_setting('timezone')
                user_timezone = lib.get_timezone(timezone)
                if not user_timezone:
                    return await context.send(user.get_mention() + ', ' + lib.get_string('err:notimezone', user.get_guild()))

                # If they are doing `sprint for 20 at :15` for example, then opt3 must be set in the format '.00'.
                start = int(opt3[1:]) if (isinstance(opt3, str) and opt3.startswith('.') and len(opt3) == 3) else opt3
                if not isinstance(start, int) or start < 0 or start >= 60:
                    return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:for:at', user.get_guild()))

                # Now using their timezone and the minute they requested, calculate when that should be.
                user_timezone = lib.get_timezone(timezone)
                delay = (60 + start - datetime.now(user_timezone).minute) % 60

            return await self.run_start(context, length, delay)

        elif cmd == "in":

            delay = opt1

            # If the second option is invalid, display an error message
            if opt2 is not None and opt2.lower() != "for":
                return await context.send(
                    user.get_mention()
                    + ", "
                    + lib.get_string("sprint:err:in:unknown", user.get_guild())
                )

            # Get the length they want before starting the sprint.
            # If they left off the last argument and just said `sprint for 20` then assume they mean now.
            if opt2 is None:
                length = self.DEFAULT_LENGTH
            elif opt2.lower() == "for":
               length = opt3

            return await self.run_start(context, length, delay)

        elif cmd == 'cancel':
            return await self.run_cancel(context)

        elif cmd == 'notify':
            return await self.run_notify(context)

        elif cmd == 'forget':
            return await self.run_forget(context)

        elif cmd == 'time':
            return await self.run_time(context)

        elif cmd == 'leave':
            return await self.run_leave(context)

        elif cmd == 'join':
            return await self.run_join(context, opt1, opt2)

        elif cmd == 'pb':
            return await self.run_pb(context)

        elif cmd == 'status':
            return await self.run_status(context)

        elif cmd == 'wc' or cmd == 'declare':
            return await self.run_declare(context, opt1)

        elif cmd == 'end':
            return await self.run_end(context)

        elif cmd == 'project':
            return await self.run_project(context, opt1)

        elif cmd == 'purge':
            return await self.run_purge(context)
示例#20
0
    async def project(self, context, cmd=None, *opts):
        """
        The project command allows you to create different projects and store word counts against them separately. They also integrate with the `wrote` and `sprint` commands, allowing you to define words written against a chosen project. (See the help information for those commands for more info).

        Examples:
            `project create sword The Sword in the Stone` - Creates a new project with the shortname "sword" (used to reference the project when you want to update it), and the full title "The Sword in the Stone".
            `project delete sword` - Deletes the project with the shortname "sword"
            `project rename sword sword2 The Sword in the Stone Two` - Renames the project with the shortname "sword" to - shortname:sword2, title:The Sword in the Stone Two (If you want to keep the same shortname but change the title, just put the same shortname, e.g. `project rename sword sword The Sword in the Stone Two`.
            `project update sword 65000` - Sets the word count for the project with the shortname "sword" to 65000.
            `project list` - Views a list of all your projects.
            `project list status published` - Views a list of all your projects with the `published` status.
            `project list genre fantasy` - Views a list of all your projects with the `fantasy` genre.
            `project view sword` - Views the information about the project with the shortname "sword".
            `project status sword published` - Sets the status of the project to `published`.
            `project genre sword fantasy` - Sets the genre of the project to `fantasy`.
            `project description sword Young boy finds sword, becomes king` - Sets the description/blurb of the project.
            `project link sword http://website.com/your-book` - Sets the hyperlink for your project's web/store page.
            `project img sword http://website.com/picture.png` - Sets the thumbnail picture to use for this project.
        """
        if not Guild(context.guild).is_command_enabled('project'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        user = User(context.message.author.id, context.guild.id, context)

        # Check the arguments were all supplied and get a dict list of them and their values, after any prompts
        args = await self.check_arguments(context, cmd=cmd)
        if not args:
            return

        # Overwrite the variables passed in, with the values from the prompt and convert to lowercase
        cmd = args['cmd'].lower()

        # Make sure some options have been sent through
        if len(opts) == 0 and cmd != 'view' and cmd != 'list':
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('project:err:options', user.get_guild()))

        # Check which command is being run and run it.
        # Since the options can have spaces in them, we need to send the whole thing through as a list and then work out what is what in the command.
        if cmd == 'create':
            return await self.run_create(context, opts)
        elif cmd == 'delete':
            return await self.run_delete(context, opts)
        elif cmd == 'rename':
            return await self.run_rename(context, opts)
        elif cmd == 'update':
            return await self.run_update(context, opts)
        elif cmd == 'view':
            return await self.run_view(context, opts)
        elif cmd == 'list':
            return await self.run_list(context, opts)
        elif cmd == 'status':
            return await self.run_status(context, opts)
        elif cmd == 'genre':
            return await self.run_genre(context, opts)
        elif cmd == 'description':
            return await self.run_description(context, opts)
        elif cmd == 'link':
            return await self.run_link(context, opts)
        elif cmd == 'image' or cmd == 'img':
            return await self.run_image(context, opts)
示例#21
0
    async def about(self, context):
        """
        Displays information and statistics about the bot.
        Aliases: !info
        Examples: !about
        """

        if not Guild(context.guild).is_command_enabled('info'):
            return await context.send(
                lib.get_string('err:disabled', context.guild.id))

        now = time.time()
        uptime = int(round(now - self.bot.start_time))
        guild_id = context.guild.id
        config = self.bot.config
        sprints = self.__db.get('sprints', {'completed': 0},
                                ['COUNT(id) as cnt'])['cnt']

        # Begin the embedded message
        embed = discord.Embed(title=lib.get_string('info:bot', guild_id),
                              color=3447003)
        embed.add_field(name=lib.get_string('info:version', guild_id),
                        value=config.version,
                        inline=True)
        embed.add_field(name=lib.get_string('info:uptime', guild_id),
                        value=str(datetime.timedelta(seconds=uptime)),
                        inline=True)
        embed.add_field(name=lib.get_string('info:owner', guild_id),
                        value=str(self.bot.app_info.owner),
                        inline=True)

        # Statistics
        stats = []
        stats.append('• ' + lib.get_string('info:servers', guild_id) + ': ' +
                     format(len(self.bot.guilds)))
        stats.append('• ' + lib.get_string('info:members', guild_id) + ': ' +
                     format(self.count_members(self.bot.guilds)))
        stats.append('• ' + lib.get_string('info:sprints', guild_id) + ': ' +
                     str(sprints))
        stats.append('• ' + lib.get_string('info:helpserver', guild_id) +
                     ': ' + config.help_server)
        stats = '\n'.join(stats)

        embed.add_field(name=lib.get_string('info:generalstats', guild_id),
                        value=stats,
                        inline=False)

        # Developer Info
        git = {}
        git['branch'] = os.popen(
            r'git rev-parse --abbrev-ref HEAD').read().strip()
        git['rev'] = os.popen(
            r'git log --pretty=format:"%h | %ad | %s" --date=short -n 1').read(
            ).strip()

        dev = []
        dev.append(
            lib.get_string('info:dev:branch', guild_id) + ': ' +
            format(git['branch']))
        dev.append(
            lib.get_string('info:dev:repo', guild_id) + ': ' +
            format(config.src))
        dev.append(
            lib.get_string('info:dev:patch', guild_id) + ': ' +
            format(config.patch_notes))
        dev.append(
            lib.get_string('info:dev:change', guild_id) + ':\n\t' +
            format(git['rev']))
        dev = '\n'.join(dev)

        embed.add_field(name=lib.get_string('info:dev', guild_id),
                        value=dev,
                        inline=False)

        # Send the message
        await context.send(embed=embed)