예제 #1
0
    async def run_rename(self, context, opts):
        """
        Rename a project
        :param context:
        :param opts:
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)

        original_shortname = opts[0].lower()
        new_shortname = opts[1].lower()
        new_title = " ".join(opts[2:])

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

        # Make sure they don't already have one with that new shortname.
        project_with_new_shortname = user.get_project(new_shortname)
        if project_with_new_shortname is not None and project_with_new_shortname.get_id() != project.get_id():
            return await context.send(user.get_mention() + ', ' + lib.get_string('project:err:exists', user.get_guild()).format(new_shortname))

        # Get the original title.
        original_title = project.get_name()

        # Rename it.
        project.rename(new_shortname, new_title)
        return await context.send(user.get_mention() + ', ' + lib.get_string('project:renamed', user.get_guild()).format(original_title, original_shortname, new_title, new_shortname))
예제 #2
0
    async def run_image(self, context, opts):
        """
        Update the image link of a project
        @param context:
        @param opts:
        @return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        shortname = opts[0].lower() if opts else None
        img = opts[1] if len(opts) > 1 else None

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

        # Check it's a valid image link.
        if not checkers.is_url(img) and img is not None:
            return await context.send(
                user.get_mention() + ', ' + lib.get_string(
                    'project:err:link', user.get_guild()).format(img))

        project.set_image(img)
        return await context.send(
            user.get_mention() + ', ' +
            lib.get_string('project:image', user.get_guild()))
예제 #3
0
    async def run_update(self, context, opts):
        """
        Update a project's word count
        :param context:
        :param opts:
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)

        shortname = opts[0].lower()
        amount = opts[1] if len(opts) > 1 else None

        # Make sure the amount is valid.
        amount = lib.is_number(amount)
        if not amount:
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('project:err:amount', user.get_guild()))

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

        # Update the word count.
        project.update(amount)
        return await context.send(
            user.get_mention() + ', ' +
            lib.get_string('project:updated', user.get_guild()).format(
                amount, project.get_name(), project.get_shortname()))
예제 #4
0
    async def run_genre(self, context, opts):
        """
        Update the genre of a project
        @param context:
        @param opts:
        @return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        shortname = opts[0].lower() if opts else None
        genre = opts[1].lower() if len(opts) > 1 else None

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

        # Make sure the genre is valid.
        if not genre in self._genres:
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('project:err:genre', user.get_guild()).format(
                    genre, ', '.join(self._genres)))

        project.set_genre(genre)
        return await context.send(
            user.get_mention() + ', ' +
            lib.get_string('project:genre', user.get_guild()).format(
                lib.get_string('project:genre:' + genre, user.get_guild())))
예제 #5
0
    async def run_description(self, context, opts):
        """
        Update the description of a project
        @param context:
        @param opts:
        @return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        shortname = opts[0].lower()
        description = " ".join(opts[1:])

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

        # Description cannot be longer than 200 words.
        words = description.split(' ')
        if len(words) > 200:
            return await context.send(
                user.get_mention() +
                ', ' + lib.get_string('project:err:desc:length',
                                      user.get_guild()).format(len(words)))

        project.set_description(description)
        return await context.send(
            user.get_mention() + ', ' +
            lib.get_string('project:description', user.get_guild()))
예제 #6
0
    async def run_project(self, context, shortname):
        """
        Set the project the user wants to sprint in.
        :param context:
        :param shortname:
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        sprint = Sprint(user.get_guild())

        # If there is no active sprint, then just display an error
        if not sprint.exists():
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('sprint:err:noexists', user.get_guild()))

        # If the user is not sprinting, then again, just display that error
        if not sprint.is_user_sprinting(user.get_id()):
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('sprint:err:notjoined', user.get_guild()))

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

        sprint.set_project(project.get_id(), user.get_id())
        return await context.send(user.get_mention() + ', ' + lib.get_string(
            'sprint:project', user.get_guild()).format(project.get_title()))
예제 #7
0
    async def run_complete(self, context, opts):
        """
        Mark a project as completed
        :param context:
        :param opts:
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        shortname = opts[0].lower()

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

        already_completed = project.is_completed()
        project.complete()

        # Was this the first time they completed it?
        if already_completed == 0:

            # Calculate how much XP to give them (1xp per 100 words). Min 10. Max 5000.
            xp = math.ceil(project.get_words() / 100)
            if xp < 10:
                xp = 10
            elif xp > 5000:
                xp = 5000

            # Give them the xp and print the message.
            await user.add_xp(xp)
            return await context.send(user.get_mention() + ', ' + lib.get_string('project:completed', user.get_guild()).format(project.get_title(), xp))

        else:
            return await context.send(user.get_mention() + ', ' + lib.get_string('project:recompleted', user.get_guild()))
예제 #8
0
    async def run_create(self, context, opts):
        """
        Try to create a project with the given names
        :param context:
        :param shortname:
        :param title:
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)

        # Get the shortname and title out of the argument list.
        shortname = opts[0].lower()
        title = " ".join(opts[1:]) # Every argument after the first one, joined with spaces.

        # Make sure the shortname and title are set.
        if len(shortname) == 0 or len(title) == 0:
            return await context.send(user.get_mention() + ', ' + lib.get_string('project:err:names', user.get_guild()))

        # Make sure they don't already have a project with this shortname
        project = user.get_project(shortname)
        if project is not None:
            return await context.send(user.get_mention() + ', ' + lib.get_string('project:err:exists', user.get_guild()).format(shortname))

        # Create the project
        user.create_project(shortname, title)
        return await context.send(user.get_mention() + ', ' + lib.get_string('project:created', user.get_guild()).format(title, shortname))
예제 #9
0
    async def run_view(self, context, opts=None):
        """
        View a list of the user's projects
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        projects = user.get_projects()

        # If they have no projects, then we can't display them.
        if not projects:
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('project:noprojects', user.get_guild()))

        # Did they specify a shortname to look at?
        if opts:

            shortname = opts[0].lower()

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

            # Re-create the array, but with just this one element in it.
            projects = [project]

        message = ''

        for project in projects:

            if project.is_completed():
                message += ':sparkler: '

            message += '**' + project.get_name(
            ) + '** (' + project.get_shortname() + ')\n'
            message += lib.get_string('wordcount',
                                      user.get_guild()) + ': ' + str(
                                          project.get_words()) + '\n\n'

        # Project lists can get very long. If it is over 2000 characters, we need to split it.
        if len(message) >= 2000:
            return await self.split_send(
                context, user,
                lib.get_string('project:list', user.get_guild()) + message)
        else:
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('project:list', user.get_guild()) + message)
예제 #10
0
    async def run_join(self, context, starting_wc=None, shortname=None):
        """
        Join the sprint, with an optional starting word count and project shortname
        :param starting_wc:
        :param shortname: Shortname of Project
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        sprint = Sprint(user.get_guild())

        # If there is no active sprint, then just display an error
        if not sprint.exists():
            return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:err:noexists', user.get_guild()))

        # Convert starting_wc to int if we can
        starting_wc = lib.is_number(starting_wc)
        if starting_wc is False:
            starting_wc = 0

        # If the user is already sprinting, then just update their starting wordcount
        if sprint.is_user_sprinting(user.get_id()):

            # Update the sprint_users record. We set their current_wc to the same as starting_wc here, otherwise if they join with, say 50 and their current remains 0
            # then if they run a status, or in the ending calculations, it will say they wrote -50.
            sprint.update_user(user.get_id(), start=starting_wc, current=starting_wc)

            # Send message back to channel letting them know their starting word count was updated
            await context.send(user.get_mention() + ', ' + lib.get_string('sprint:join:update', user.get_guild()).format(starting_wc))

        else:

            # Join the sprint
            sprint.join(user.get_id(), starting_wc)

            # Send message back to channel letting them know their starting word count was updated
            await context.send(user.get_mention() + ', ' + lib.get_string('sprint:join', user.get_guild()).format(starting_wc))

        # If a project shortname is supplied, try to set that as what the user is sprinting for.
        if shortname is not None:

            # Convert to lowercase for searching.
            shortname = shortname.lower()

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

            sprint.set_project(project.get_id(), user.get_id())
            return await context.send(user.get_mention() + ', ' + lib.get_string('sprint:project', user.get_guild()).format(project.get_title()))
예제 #11
0
    async def run_restart(self, context, opts):
        """
        Mark a project as not completed
        :param context:
        :param opts:
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        shortname = opts[0].lower()

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

        project.uncomplete()
        return await context.send(user.get_mention() + ', ' + lib.get_string('project:uncompleted', user.get_guild()))
예제 #12
0
    async def run_status(self, context, opts):
        """
        Update the status of a project
        @param context:
        @param opts:
        @return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        shortname = opts[0].lower() if opts else None
        status = opts[1].lower() if len(opts) > 1 else None

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

        # Make sure the status is valid.
        if not status in self._statuses:
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('project:err:status', user.get_guild()).format(
                    status, ', '.join(self._statuses)))

        # If we are marking it finished or published for the first time, add xp.
        if (status == 'finished'
                or status == 'published') and not project.is_complete():
            xp = math.ceil(project.get_words() / 100)
            if xp < 10:
                xp = 10
            elif xp > 5000:
                xp = 5000
            await user.add_xp(xp)
            await context.send(
                user.get_mention() + ', ' +
                lib.get_string('project:completed', user.get_guild()).format(
                    project.get_title(), xp))

        project.set_status(status)
        return await context.send(
            user.get_mention() + ', ' +
            lib.get_string('project:status', user.get_guild()).format(
                lib.get_string('project:status:' + status, user.get_guild())))
예제 #13
0
    async def run_delete(self, context, opts):
        """
        Try to delete a project with the given shortname
        :param context:
        :param opts:
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)

        # Make sure the project exists first
        shortname = opts[0].lower()
        project = user.get_project(shortname)
        if not project:
            return await context.send(user.get_mention() + ', ' + lib.get_string('project:err:noexists', user.get_guild()).format(shortname))

        # Delete it.
        project.delete()
        return await context.send(user.get_mention() + ', ' + lib.get_string('project:deleted', user.get_guild()).format(project.get_name(), project.get_shortname()))
예제 #14
0
    async def run_view(self, context, opts):
        """
        View a specific project
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)

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

        shortname = opts[0].lower()
        project = user.get_project(shortname)
        if not project:
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('project:err:noexists',
                               user.get_guild()).format(shortname))

        # Display the embedded message response for this project.
        return await project.display(context)
예제 #15
0
    async def run_join(self, context, arg1=None, arg2=None):
        """
        Join the sprint, with an optional starting word count and project shortname
        :param opt1: Argument 1 of the join command
        :param opt2: Argument 2 of the join command
        :return:
        """
        user = User(context.message.author.id, context.guild.id, context)
        sprint = Sprint(user.get_guild())
        project_id = None
        starting_wc = None
        sprint_type = None

        # If there is no active sprint, then just display an error
        if not sprint.exists():
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('sprint:err:noexists', user.get_guild()))

        # Are we using the `same` keyword?
        if arg1 == "same":

            # Okay, check for their most recent sprint record
            most_recent = user.get_most_recent_sprint(sprint)
            if most_recent is not None:
                starting_wc = most_recent['ending_wc']
                project_id = most_recent['project']
                sprint_type = most_recent['sprint_type']

            # Can't use the second argument in this case.
            arg2 = None

        # Are we doing a no wordcount sprint? E.g. we are sprinting or using the functionality for something else.
        elif arg1 in ["edit", "non-wc"]:

            sprint_type = Sprint.SPRINT_TYPE_NO_WORDCOUNT

            # Can't use the second argument in this case.
            arg2 = None

        else:
            # Convert starting_wc to int if we can
            starting_wc = lib.is_number(arg1)

        # If the starting_wc is still False at this point, just set it to 0
        if not starting_wc:
            starting_wc = 0

        # If the user is already sprinting, then just update their starting wordcount
        if sprint.is_user_sprinting(user.get_id()):

            # Update the sprint_users record. We set their current_wc to the same as starting_wc here, otherwise if they join with, say 50 and their current remains 0
            # then if they run a status, or in the ending calculations, it will say they wrote -50.
            sprint.update_user(user.get_id(),
                               start=starting_wc,
                               current=starting_wc,
                               sprint_type=sprint_type)

            # If it's a non-wordcount sprint, send a different message.
            if sprint_type == Sprint.SPRINT_TYPE_NO_WORDCOUNT:
                await context.send(user.get_mention() + ', ' + lib.get_string(
                    'sprint:join:update:no_wordcount', user.get_guild()))
            else:
                # Send message back to channel letting them know their starting word count was updated
                await context.send(user.get_mention() + ', ' + lib.get_string(
                    'sprint:join:update', user.get_guild()).format(starting_wc)
                                   )

        else:

            # Join the sprint
            sprint.join(user.get_id(),
                        starting_wc=starting_wc,
                        sprint_type=sprint_type)

            if sprint_type == Sprint.SPRINT_TYPE_NO_WORDCOUNT:
                await context.send(user.get_mention() + ', ' + lib.get_string(
                    'sprint:join:update:no_wordcount', user.get_guild()))
            else:
                # Send message back to channel letting them know their starting word count was updated
                await context.send(user.get_mention() + ', ' + lib.get_string(
                    'sprint:join', user.get_guild()).format(starting_wc))

        # Currently this is the only usage of argument 2.
        shortname = arg2

        # If a project shortname is supplied, try to set that as what the user is sprinting for.
        if shortname is not None or project_id is not None:

            # Did we supply the project by name?
            if shortname is not None:

                # Convert to lowercase for searching.
                shortname = shortname.lower()

                # Make sure the project exists.
                project = user.get_project(shortname)

            # Or do we already have the ID from using 'same' and getting from previous sprint?
            elif project_id is not None:
                project = Project(project_id)

            # If that did not yield a valid project, send an error message.
            if not project:
                return await context.send(
                    user.get_mention() +
                    ', ' + lib.get_string('project:err:noexists',
                                          user.get_guild()).format(shortname))

            sprint.set_project(project.get_id(), user.get_id())
            return await context.send(
                user.get_mention() + ', ' +
                lib.get_string('sprint:project', user.get_guild()).format(
                    project.get_title()))
예제 #16
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)

        # 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 daily goal
        await user.add_to_goal('daily', 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)