예제 #1
0
    async def help_command(self, ctx: Context, command):
        """
        Send command description as message in channel.

        Attributes
        ----------
        command: str
            The name of command for getting the description
        """
        # Get command obj from the name
        command = self.bot.get_command(command)

        if command:
            embed = discord.Embed(
                title=command.name,
                colour=discord.Colour.blue(),
                description=command.help,
            )

            bot_as_user = self.bot.get_user(settings.BOT_ID)
            embed.set_author(
                name=str(bot_as_user),
                icon_url=bot_as_user.avatar_url,
            )
            await ctx.send(embed=embed)

            await ctx.message.add_reaction('✔')
            log_template.command_success(ctx)
        else:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.command_not_found)
예제 #2
0
    async def save_raid(self, ctx: Context, captain_name: str, time_leaving=''):
        """
        Save active raid by specific captain name and time leaving

        Attributes:
        ----------
        captain_name: str
            Name of the captain that created the raid.
        time_leaving: str or None
            Time when raid leaving. Required to fill if captain has more than one raid.
        """
        # Checking correct input
        await check_input.validation(**locals())

        curr_raid = self.raid_list.find_raid(ctx.guild.id, ctx.channel.id,
                                             captain_name, time_leaving, ignore_channels=True)
        # if not find raid to save
        if not curr_raid:
            await check_input.not_correct(ctx, 'Не нашёл рейд для сохранение.')
            log_template.command_fail(ctx, logger_msgs.raids_not_found)
            return

        curr_raid.save_raid()

        await ctx.message.add_reaction('✔')
        log_template.command_success(ctx)
예제 #3
0
    async def show(self, ctx: Context, captain_name: str, time_leaving=''):
        """
        Send member list of raid as image

        Attributes:
        ----------
        captain_name: str
            Name of the user that created the raid.
        time_leaving: str or None
            Time when raid leaving. Required to fill if captain has more than one raid.
        """

        # Checking correct inputs arguments
        await check_input.validation(**locals())

        curr_raid = self.raid_list.find_raid(ctx.guild.id,
                                             ctx.channel.id,
                                             captain_name,
                                             time_leaving,
                                             ignore_channels=True)

        if curr_raid:
            path = curr_raid.table_path()
            curr_raid.save_raid()
            await ctx.send(file=discord.File(path))

            await ctx.message.add_reaction('✔')
            log_template.command_success(ctx)
        else:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.raid_not_found)
예제 #4
0
    async def remove_res(self, ctx: commands.context.Context, name: str):
        """
        Allow user exit the raid by command

        Attributes:
        ----------
        name: str
            Nickname of user that want leave the raid.
        captain_name: str
            Nickname of user that created the raid.
        time_leaving: str
            Time when raid leaving. Required to fill if captain has more than one raid.
        """
        # Checking correct inputs arguments
        await check_input.validation(**locals())

        current_raid = self.raid_list.find_raid_by_nickname(name)

        if not current_raid:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.nope_in_raids)
        else:
            current_raid -= name
            await current_raid.raid_msgs.update_coll_msg(self.bot)

            await ctx.message.add_reaction('✔')
            log_template.command_success(ctx)
예제 #5
0
async def not_correct(ctx, *errors):
    """
    Responsible for wrong input handling
    """
    message = messages.wrong_command.format(command=ctx.message.content)
    errors = ''.join(errors)
    await ctx.author.send(message + errors)
    log_template.command_fail(ctx, errors)
예제 #6
0
    async def save_raids(self, ctx: Context):
        """
        Save all active raids in locale storage.
        """
        if self.raid_list:
            for some_raid in self.raid_list:
                some_raid.save_raid()

            await ctx.message.add_reaction('✔')
            log_template.command_success(ctx)
        else:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.raids_not_found)
예제 #7
0
    async def send_logs(self, ctx: Context):
        """
        Command for admins and developers. Send the bot logs as msg to channel.
        """
        path_to_logs = os.path.join('settings', 'logger', 'logs.log')

        if os.path.exists(path_to_logs):
            await ctx.send(file=discord.File(path_to_logs))
            await ctx.message.add_reaction('✔')
            log_template.command_success(ctx)
        else:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.logs_not_found)
예제 #8
0
    async def check_raid_exists(self, ctx: Context, captain_name: str, time_leaving=''):
        """
        Check raid exist by this captain. If raid exist ask captain.

        Attributes:
        ----------
        captain_name: str
            Name of the captain that created the raid.
        time_leaving: str or None
            Time when raid leaving. Required to fill if captain has more than one raid.
        """
        # Check captain exists
        captain_post = self.database.captain.find_captain_post(str(ctx.author))
        if not captain_post:
            self.database.captain.create_captain(str(ctx.author))

        # Check raid exists of this captain
        captain_raids = self.captain_raids(captain_name)
        if not captain_raids:
            return

        # If raid with this credentials absolutely matched
        for captain_raid in captain_raids:
            if captain_raid.raid_time.time_leaving == time_leaving:
                await ctx.author.send(messages.raid_exist_error)

                await ctx.message.add_reaction('❌')
                log_template.command_fail(ctx, logger_msgs.raid_exist)
                raise commands.errors.UserInputError('Такой рейд уже существует.')

        active_raids = self.captain_raids_str(captain_name)
        message = await ctx.author.send(messages.raid_exist_warning + active_raids)
        await message.add_reaction('✔')
        await message.add_reaction('❌')

        def check(reaction, user):
            """Process answer only by author of command and correct reaction"""
            return user.id == ctx.message.author.id and (str(reaction.emoji) == '✔' or str(reaction.emoji) == '❌')

        # Wait answer of user
        try:
            reaction, user = await self.bot.wait_for('reaction_add', timeout=300.0, check=check)
        except asyncio.TimeoutError:
            log_template.command_fail(ctx, logger_msgs.user_not_response)
            raise commands.errors.UserInputError('Капитан не ответил на вопрос о создании рейда')
        else:
            emoji = str(reaction.emoji)
            log_template.user_answer(ctx, emoji)

            if emoji == '❌':
                raise commands.errors.UserInputError('Капитан отказался создавать новый рейд')
예제 #9
0
    async def reg(self, ctx: Context, name: str):
        """
        Register game nickname in bot database.

        Attributes:
        ----------
        name: str
            Game user nickname.
        """
        # Checking correct input
        await check_input.validation(**locals())

        try:
            self.database.user.reg_user(ctx.author.id, str(ctx.author), name)
            await ctx.message.add_reaction('✔')
            log_template.command_success(ctx)
        except database_process.UserExists:
            await ctx.author.send(messages.already_registered)
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.already_registered)
예제 #10
0
    async def show_text_raids(self,
                              ctx: Context,
                              captain_name: str,
                              time_leaving=''):
        """
        Send member list of raid as text

        Attributes:
        ----------
        captain_name: str
            Name of the user that created the raid.
        time_leaving: str or None
            Time when raid leaving. Required to fill if captain has more than one raid.
        """
        # Checking correct inputs arguments
        await check_input.validation(**locals())

        curr_raid = self.raid_list.find_raid(ctx.guild.id,
                                             ctx.channel.id,
                                             captain_name,
                                             time_leaving,
                                             ignore_channels=True)

        if curr_raid:
            # If it's first display
            if not curr_raid.table:
                curr_raid.table_path()

            # Generate text member list
            text = curr_raid.table.create_text_table()
            title = text.split('\n')[0]
            embed = discord.Embed(title=title,
                                  colour=discord.Colour.blue(),
                                  description=text[len(title) + 1:])

            await ctx.send(curr_raid.table.create_text_table())
            await ctx.message.add_reaction('✔')
            log_template.command_success(ctx)
        else:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.raid_not_found)
예제 #11
0
    async def remove_msgs(self, ctx: Context, amount=100):
        """
        Remove `amount` messages in current channel.

        Attributes
        ----------
        amount: str
            Amount of messages to delete
        """
        guild = ctx.guild
        channel = ctx.channel
        # In this channel can raid creator remove messages by bot?
        if not self.database.settings.can_delete_there(guild.id, channel.id):
            await ctx.message.add_reaction('❌')
            await ctx.author.send(messages.wrong_channel)
            log_template.command_fail(ctx, logger_msgs.wrong_channel)

        messages_to_remove = []
        msg_count = 0
        # Collect all messages in current channel that not older 14 days and not pinned
        async for msg in channel.history(limit=int(amount)):
            is_time_has_passed = datetime.now() - msg.created_at > timedelta(
                days=14)

            # Warning user if messages older than 14 days
            if not msg.pinned and is_time_has_passed:
                await ctx.author.send(
                    messages.remove_msgs_fail_14.format(msg_count=msg_count,
                                                        amount=amount))
                break

            if not msg.pinned:
                messages_to_remove.append(msg)
                msg_count += 1

        # Remove messages from channel
        await channel.delete_messages(messages_to_remove)
        log_template.command_success(ctx)
예제 #12
0
    async def remove_raid(self, ctx: Context, captain_name: str, time_leaving=''):
        """
        Remove available raid

        Attributes:
        ----------
        captain_name: str
            Name of the captain that created the raid.
        time_leaving: str or None
            Time when raid leaving. Required to fill if captain has more than one raid.
        """
        # Checking correct inputs arguments
        await check_input.validation(**locals())

        curr_raid = self.raid_list.find_raid(ctx.guild.id, ctx.channel.id, captain_name, time_leaving)
        if curr_raid:
            curr_raid.end_work()
            self.raid_list.remove(curr_raid)

            await ctx.message.add_reaction('✔')
            log_template.command_success(ctx)
        else:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.raid_not_found)
예제 #13
0
    async def cap(self, ctx: Context):
        """
        Short version of command captain. In this way user choose old parameters of raid by adding reaction.
        """
        # Dict of controlling emoji
        NUMBER_REACTIONS = {
            '1️⃣': 1, '2️⃣': 2, '3️⃣': 3,
            1: '1️⃣', 2: '2️⃣', 3: '3️⃣'
        }

        user = str(ctx.author)
        captain_post = self.database.captain.find_captain_post(user)

        # Get parameters of old raids
        if not captain_post:
            await ctx.message.add_reaction('❌')
            await ctx.author.send(messages.new_captain)
            log_template.command_fail(ctx, logger_msgs.captain_not_exist)
            return
        last_raids = captain_post.get('last_raids')

        raids_msg = messages.raid_create_choice_start.format(captain_name=captain_post['captain_name'])

        # Generate list of choices
        for index, last_raid in enumerate(last_raids):
            raids_msg += messages.raid_create_choice_server_time.format(
                index=index + 1, server=last_raid['server'], time_leaving=last_raid['time_leaving']
            )
            if last_raid.get('time_reservation_open'):
                raids_msg += messages.raid_create_choice_res_open.format(
                    time_reservation_open=last_raid['time_reservation_open']
                )
            if last_raid.get('reservation_count') and not last_raid['reservation_count'] == 1:
                raids_msg += messages.raid_create_choice_count.format(reservtaion_count=last_raid['reservation_count'])
            raids_msg += '.\n'

        # Send list of choices and add controlling reactions
        msg = await ctx.send(raids_msg)
        for number in range(len(last_raids)):
            await msg.add_reaction(NUMBER_REACTIONS[number + 1])

        def check(reaction, user):
            """Only get answer by author of command and correct reaction"""
            return (
                    user == ctx.message.author and
                    (
                            str(reaction.emoji) == '1️⃣' or str(reaction.emoji) == '2️⃣' or str(reaction.emoji) == '3️⃣'
                    )
            )

        try:
            # Wait for user answer
            reaction, user = await self.bot.wait_for('reaction_add', timeout=600.0, check=check)
        except asyncio.TimeoutError:
            log_template.command_fail(ctx, logger_msgs.user_not_response)
            await ctx.message.add_reaction('❌')
        else:
            emoji = str(reaction.emoji)
            log_template.user_answer(ctx, emoji)
            user_choice = NUMBER_REACTIONS[emoji]

            user_raid = last_raids[user_choice - 1]
            await self.check_raid_exists(ctx, captain_post.get('captain_name'), user_raid.get('time_leaving'))
            await self.captain(
                ctx,
                captain_post.get('captain_name'),
                user_raid.get('server'),
                user_raid.get('time_leaving'),
                user_raid.get('time_reservation_open'),
                user_raid.get('reservation_count'),
            )
예제 #14
0
    async def collection(self, ctx: Context, captain_name: str, time_leaving=''):
        """
        Send collection messaged to current channel and
        allowed users to get into the raid by adding reaction on collection message.

        Attributes:
        ----------
        captain_name: str
            Name of the captain that created the raid.
        time_leaving: str or None
            Time when raid leaving. Required to fill if captain has more than one raid.
        """
        # Checking correct inputs arguments
        await check_input.validation(**locals())

        curr_raid = self.raid_list.find_raid(
            ctx.guild.id, ctx.channel.id, captain_name, time_leaving, ignore_channels=True
        )

        # Does this captain have a raid with these parameters?
        if not curr_raid:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.raid_not_found)
            return

        # Its not deleted raid
        if curr_raid.is_deleted_raid:
            return

        # Stop async task if such exists for this raid
        if curr_raid.waiting_collection_task:
            curr_raid.waiting_collection_task.cancel()

        # Send message about collection
        collection_msg = await curr_raid.raid_msgs.send_coll_msg(ctx)
        await collection_msg.add_reaction('❤')

        log_template.command_success(ctx)

        # Remove the time that has already passed
        curr_raid.raid_time.validate_time()

        # Notify user if possible before leaving
        asyncio.ensure_future(self.notify_about_leaving(curr_raid))

        raid_time = curr_raid.raid_time.time_to_display.copy()
        for index, time_display in enumerate(raid_time):
            curr_raid.save_raid()

            # Update text msg of start collection Raid
            await curr_raid.raid_msgs.update_coll_msg(self.bot)

            # Wait next time to display raid table
            secs_left = curr_raid.raid_time.secs_left_to_display()
            curr_raid.coll_sleep_task = asyncio.create_task(asyncio.sleep(secs_left))
            await curr_raid.coll_sleep_task
            curr_raid.raid_time.time_passed()

            # Resend new message with raid table if not first time else just send table
            await curr_raid.raid_msgs.update_table_msg(self.bot, ctx)

        self.database.captain.update_captain(str(ctx.author), curr_raid)

        await ctx.send(messages.collection_end.format(server=curr_raid.server, captain_name=curr_raid.captain_name))
        await self.remove_raid(ctx, captain_name, time_leaving)
예제 #15
0
    async def reserve(self,
                      ctx: Context,
                      name: str,
                      captain_name='',
                      time_leaving=''):
        """
        Allow user join the raid by command

        Attributes:
        ----------
        name: str
            Nickname of user that want join the raid.
        captain_name: str
            Nickname of user that created the raid.
        time_leaving: str
            Time when raid leaving. Required to fill if captain has more than one raid.
        """
        # Checking correct input
        await check_input.validation(**locals())

        if not captain_name and not time_leaving:
            available_raids = self.raid_list.find_raids_by_guild(
                name, ctx.guild.id)

            if not available_raids:
                log_template.command_fail(ctx, logger_msgs.no_available_raids)
                await ctx.message.add_reaction('❌')
                return

            # Get raid which has the least people
            smaller_raid = min(available_raids)

            # Add user into raid
            smaller_raid += name
            await smaller_raid.raid_msgs.update_coll_msg(self.bot)

            await ctx.message.add_reaction('✔')

            log_template.command_success(ctx)
            return

        curr_raid = self.raid_list.find_raid(ctx.guild.id, ctx.channel.id,
                                             captain_name, time_leaving)

        if not curr_raid:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.raid_not_found)
            return

        if curr_raid.is_full:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.raid_is_full)
            return

        if name in curr_raid:
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.already_in_raid)
            return

        # if user already in the same raid
        if self.raid_list.is_correct_join(name, time_leaving):
            await ctx.author.send(messages.already_joined)
            await ctx.message.add_reaction('❌')
            log_template.command_fail(ctx, logger_msgs.already_in_same_raid)
            return

        # Add user into the raid
        curr_raid += name
        await curr_raid.raid_msgs.update_coll_msg(self.bot)

        await ctx.message.add_reaction('✔')
        log_template.command_success(ctx)