示例#1
0
class RaidRegistration(commands.Cog):
    """
    Cog that responsible for user registration. After registration user can use reaction.
    """
    database = database_process.DatabaseManager()

    def __init__(self, bot):
        self.bot = bot

    @commands.command(name=command_names.function_command.reg, help=help_text.reg)
    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)

    @commands.command(name=command_names.function_command.rereg, help=help_text.rereg)
    async def rereg(self, ctx: Context, name: str):
        """
        Re-register game nickname in bot database.

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

        self.database.user.rereg_user(ctx.author.id, str(ctx.author), name)

        await ctx.message.add_reaction('✔')
        log_template.command_success(ctx)
示例#2
0
class Admin(commands.Cog):
    """
    Cog for controlling server, channels and messages.
    """
    database = database_process.DatabaseManager()

    def __init__(self, bot):
        self.bot = bot

    @commands.command(name=command_names.function_command.remove_there,
                      help=help_text.remove_there)
    @commands.guild_only()
    @commands.has_role('Капитан')
    async def remove_there(self, ctx: Context):
        """
        Allow the raid creator use command for mass messages remove in current channel.
        """
        guild = ctx.guild
        channel = ctx.channel
        self.database.settings.update_settings(guild.id, str(guild),
                                               channel.id, str(channel))

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

    @commands.command(name=command_names.function_command.not_remove_there,
                      help=help_text.not_remove_there)
    @commands.guild_only()
    @commands.has_permissions(administrator=True, manage_messages=True)
    async def not_remove_there(self, ctx: Context):
        """
        Does not allow use command for mass messages remove in current channel.
        """
        guild = ctx.guild
        channel = ctx.channel
        self.database.settings.not_delete_there(guild.id, channel.id)

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

    @commands.command(name=command_names.function_command.remove_msgs,
                      help=help_text.remove_msgs)
    @commands.guild_only()
    @commands.has_role('Капитан')
    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)
示例#3
0
class Base(commands.Cog):
    """
    Cog that responsible for basic bot commands.
    """
    database = database_process.DatabaseManager()

    def __init__(self, bot):
        self.bot = bot
        self.bot.remove_command('help')  # Remove command to create custom help

    @commands.command(name=command_names.function_command.test,
                      help=help_text.test)
    async def test(self, ctx: Context):
        """
        Command witch does nothing. For developer and debugging.
        """
        await check_input.validation(**locals())
        await ctx.message.add_reaction('❌')
        await ctx.message.add_reaction('✔')
        log_template.command_success(ctx)

    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)

    @commands.command(name=command_names.function_command.send_logs,
                      help=help_text.send_logs)
    @commands.is_owner()
    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)

    @commands.command(name=command_names.function_command.help,
                      help=help_text.help)
    async def help(self, ctx: Context, command=''):
        """
        Custom help command.

        Attributes
        ----------
        command: str
            The name of command for getting the description
        """
        # If user enter name of command to get description
        if command:
            await self.help_command(ctx, command)
            return

        # Dict of emoji for control custom help
        HELP_EMODJI = ['🔼', '1⃣', '2⃣', '3⃣', '4⃣', '5⃣', '6⃣', '7⃣', '8⃣']
        pages = {}
        # Cogs witch should not be shown in help
        not_help_cogs = ['Base', 'Events']

        # Get all available commands of the bot
        cogs_commands = {}
        for cog_name in self.bot.cogs:
            if cog_name not in not_help_cogs:
                cogs_commands[messages.cog_names[cog_name]] = self.bot.get_cog(
                    cog_name).get_commands()

        main_embed = discord.Embed(title=messages.help_title,
                                   colour=discord.Colour.blue())

        bot_as_user = self.bot.get_user(settings.BOT_ID)
        main_embed.set_author(
            name=str(bot_as_user),
            icon_url=bot_as_user.avatar_url,
        )

        # Generate pages of cogs with description of all commands in cog
        section_help = messages.section_help.format(emoji=HELP_EMODJI[0])
        for index, (cog_name,
                    bot_commands) in enumerate(cogs_commands.items()):
            section_help += f"**{HELP_EMODJI[1:][index]}  -  {cog_name}**\n"
            page = f"**{cog_name}**:\n"
            for command in bot_commands:
                page += f"**`{settings.PREFIX}{command.name}` - {command.short_doc}**\n"

            embed_page = discord.Embed(title=messages.help_title,
                                       colour=discord.Colour.blue(),
                                       description=page)

            embed_page.set_author(
                name=str(bot_as_user),
                icon_url=bot_as_user.avatar_url,
            )

            pages[HELP_EMODJI[1:][index]] = embed_page

        main_embed.add_field(name=messages.section_title,
                             value=section_help,
                             inline=False)

        main_embed.add_field(name=messages.author_title,
                             value=messages.author_command_description,
                             inline=False)

        main_embed.add_field(name=messages.additional_help_title,
                             value=messages.additional_help,
                             inline=False)

        main_embed.add_field(name=messages.help_reaction_title,
                             value=messages.help_reaction,
                             inline=False)

        # Set home page
        pages[HELP_EMODJI[0]] = main_embed

        help_msg = await ctx.send(embed=main_embed)

        log_template.command_success(ctx)

        # Add control emoji for message
        for emoji in HELP_EMODJI:
            await help_msg.add_reaction(emoji)

        def check(reaction, user):
            """
            Only user who use command can use control emoji
            """
            return (user == ctx.message.author
                    and str(reaction.emoji) in HELP_EMODJI)

        while True:
            try:
                # Waiting for a click reaction from the user
                reaction, user = await self.bot.wait_for('reaction_add',
                                                         timeout=600.0,
                                                         check=check)
            except asyncio.TimeoutError:
                return

            log_template.user_answer(ctx, str(reaction))

            # Switch page
            embed = pages.get(str(reaction))
            if embed:
                await help_msg.edit(embed=embed)

    @commands.command(name=command_names.function_command.turn_off_bot,
                      help=help_text.turn_off_bot)
    @commands.is_owner()
    async def turn_off_bot(self, ctx: Context):
        """
        Disables the bot. Available only to the bot creator.
        """
        log_template.command_success(ctx)
        await self.bot.logout()

    @commands.command(name=command_names.function_command.author_of_bot,
                      help=help_text.author_of_bot)
    async def author_of_bot(self, ctx: Context):
        """
        Send information about creator and bot as message in current channel.
        """
        embed = discord.Embed(title=messages.author_title,
                              colour=discord.Colour.blue(),
                              description=messages.about_author)
        await ctx.send(embed=embed)
        log_template.command_success(ctx)
示例#4
0
class RaidCreation(commands.Cog):
    """
    Cog that responsible for creating and removing raids
    """
    database = database_process.DatabaseManager()
    raid_list = raid_list.RaidList()

    def __init__(self, bot):
        self.bot = bot

    def captain_raids(self, captain_name: str) -> list or None:
        """
        Return list of all captains Raid's or None.

        Attribute:
        ----------
        captain_name: str
            Nickname of user that drove people

        Return:
        ----------
        list or None if raids of captains not exist
        """
        current_raids = []
        for some_raid in self.raid_list:
            if some_raid.captain_name == captain_name:
                current_raids.append(some_raid)
        return current_raids

    def captain_raids_str(self, captain_name: str) -> str or None:
        """"
        Return list of all captains Raid's or None as text.

        Attribute:
        ----------
        captain_name: str
            Nickname of user that drove people

        Return:
        ----------
        str or None if raids of captains not exist
        """
        current_raids = self.captain_raids(captain_name)

        if not current_raids:
            return

        msg = messages.yours_current_raids_start
        for captain_raid in current_raids:
            guild_name = str(self.bot.get_guild(captain_raid.guild_id))
            channel_name = str(self.bot.get_channel(captain_raid.channel_id))
            msg += (
                f"**{guild_name}**/**{channel_name}**/"
                f"**{captain_raid.server}**/**{captain_raid.raid_time.time_leaving}**\n"
            )
        return msg

    async def notify_about_leaving(self, current_raid: Raid):
        """
        Send notification message to all users in raid after notification time.

        Attributes:
        ----------
        current_raid: Raid
            raid to notification
        """
        # Get secs left to notification
        secs_sleep = current_raid.raid_time.secs_to_notify()

        if not secs_sleep:
            return

        current_raid.raid_time.is_notified = True
        # Sleep before notification time
        sleep_task = asyncio.create_task(asyncio.sleep(secs_sleep))
        current_raid.raid_time.notification_task = sleep_task
        await sleep_task

        users_list = self.database.user.get_users_id(list(current_raid.member_dict.keys()))
        amount = 0
        # Send notification msg to users
        for member in users_list:
            if member:
                user = self.bot.get_user(member.get('discord_id'))
                await user.send(messages.member_notification)
                amount += 1

        # Send notification message to the captain
        captain_id = self.database.user.user_post_by_name(current_raid.captain_name).get('discord_id')
        captain = self.bot.get_user(captain_id)
        await captain.send(messages.captain_notification)

        log_template.notify_success(current_raid.raid_time.time_leaving, amount + 1)

    @commands.command(name=command_names.function_command.remove_raid, help=help_text.remove_raid)
    @commands.guild_only()
    @commands.has_role('Капитан')
    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)

    @commands.command(name=command_names.function_command.collection, help=help_text.collection)
    @commands.guild_only()
    @commands.has_role('Капитан')
    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)

    def check_captain_registration(self, user: discord.User, captain_name: str):
        """
        Register captain in database if he is not registered yet

        Attributes:
        ----------
        user: discord.User
            discord user that captain
        captain_name: str
            game nickname of user
        """
        nickname = self.database.user.find_user(str(user))
        if nickname == captain_name:
            return
        else:
            self.database.user.rereg_user(user.id, str(user), captain_name)

    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('Капитан отказался создавать новый рейд')

    @commands.command(name=command_names.function_command.captain, help=help_text.captain)
    @commands.guild_only()
    @commands.has_role('Капитан')
    async def captain(self, ctx: Context,
                      captain_name: str, server: str, time_leaving: str, time_reservation_open='', reservation_count=0):
        """
        Create raid. Start process of collection user into the new raid.

        Attributes:
        ----------
        captain_name: str
            Nickname of user who drove people.
        server: str
            Game server where captain will carry.
        time_leaving: str
            Time when raid will sail.
        time_reservation_open: str or None
            Time when bot start collection people in raid.
            If None than start collection after one minute.
        reservation_count: int or 0
            Amount of places which cannot be borrowed
        """
        await check_input.validation(**locals())
        await self.check_raid_exists(ctx, captain_name, time_leaving)
        self.check_captain_registration(ctx.author, captain_name)

        if not time_reservation_open:
            time_reservation_open = tools.now_time_plus_minute()

        new_raid = raid.Raid(
            captain_name,
            server,
            time_leaving,
            time_reservation_open,
            ctx.guild.id,
            ctx.channel.id,
            reservation_count
        )
        self.raid_list.append(new_raid)

        await ctx.send(messages.raid_created.format(time_reservation_open=time_reservation_open))
        await ctx.message.add_reaction('✔')
        log_template.command_success(ctx)

        # Wait time reservation open
        time_left_sec = tools.get_sec_left(time_reservation_open)
        sleep_task = asyncio.create_task(asyncio.sleep(time_left_sec))
        new_raid.waiting_collection_task = sleep_task
        await sleep_task

        # Start raid collection
        collection_task = asyncio.create_task(self.collection(ctx, captain_name, time_leaving))
        new_raid.collection_task = sleep_task
        await collection_task

    @commands.command(name=command_names.function_command.cap, help=help_text.cap)
    @commands.guild_only()
    @commands.has_role('Капитан')
    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'),
            )
示例#5
0
class RaidOverview(commands.Cog):
    """
    Cog of raid manager that responsible for raid overviewing.
    """
    database = database_process.DatabaseManager()
    raid_list = raid_list.RaidList()

    def __init__(self, bot):
        self.bot = bot

    @commands.command(name=command_names.function_command.show_raids,
                      help=help_text.show_raids)
    async def show_raids(self, ctx: Context, show_all=''):
        """
        Send information about all active raid

        Attributes:
        ----------
        show_all: str
            If not None show all active raids witch created by bot
        """
        log_template.command_success(ctx)

        if not show_all:
            # Check raids exist
            if self.raid_list:
                await ctx.send(messages.no_active_raids)
                return

            # Generate information about active raids and send
            msg_of_raid = messages.active_raids_start
            for curr_raid in self.raid_list:
                if ctx.guild.id == curr_raid.guild_id:
                    channel_name = str(
                        self.bot.get_channel(curr_raid.channel_id))
                    msg_of_raid += messages.active_raid_all.format(
                        channel_name=channel_name,
                        captain_name=curr_raid.captain_name,
                        server=curr_raid.server,
                        time_leaving=curr_raid.raid_time.time_leaving,
                    )
                await ctx.send(msg_of_raid)

        else:
            # Check raids exist
            if self.raid_list:
                await ctx.send(messages.no_active_raids)
                return

            # Generate information about active raids and send
            msg_of_raid = messages.active_raids_start
            for curr_raid in self.raid_list:
                guild_name = str(self.bot.get_guild(curr_raid.guild_id))
                channel_name = str(self.bot.get_channel(curr_raid.channel_id))
                msg_of_raid += messages.active_raid_hide.format(
                    guild_name=guild_name,
                    channel_name=channel_name,
                    captain_name=curr_raid.captain_name,
                    time_leaving=curr_raid.raid_time.time_leaving,
                )
            await ctx.send(msg_of_raid)

    @commands.command(name=command_names.function_command.show_text_raids,
                      help=help_text.show_text_raids)
    @commands.guild_only()
    @commands.has_role('Капитан')
    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)

    @commands.command(name=command_names.function_command.show,
                      help=help_text.show)
    @commands.guild_only()
    @commands.has_role('Капитан')
    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)
示例#6
0
class Statistics(commands.Cog):
    """
    Cog that provides all collected statistics.
    """
    database = database_process.DatabaseManager()

    def __init__(self, bot):
        self.bot = bot

    @staticmethod
    def user_stat_msg(user, user_info: dict,
                      captain_info: dict) -> discord.Embed:
        """
        Return all information that bot knows about user to current channel as message.

        Attributes:
        ----------
        user: discord.User
            User for getting information about him
        user_info: dict
            All user information collected by bot from database
        captain_info: dict
            All user information that drove people collected by bot

        Returns:
        --------
        :discord.Embed
            All information about user as embed
        """

        text_message = messages.no_data
        if user_info:
            # Choose a title whichever user drove or not people
            if captain_info and captain_info.get('raids_created'):
                text_message = messages.captain_title
            else:
                text_message = messages.member_title

            # Add the user game nickname
            text_message += (f"**{user_info.get('nickname')}**.\n")

            # Add information about whether the user joined raids or not
            if user_info.get('entries'):
                text_message += messages.raids_joined.format(
                    entries=user_info.get('entries'))
            else:
                text_message += messages.no_raids_joined

            # Add information about whether the user drove people or not.
            if captain_info and captain_info.get('raids_created'):
                raids_created = captain_info.get('raids_created')
                drove_people = captain_info.get('drove_people')
                if raids_created < 5:
                    text_message += messages.drove_raids_l5.format(
                        raids_created=raids_created)
                else:
                    text_message += messages.drove_raids_g5.format(
                        raids_created=raids_created)
                if drove_people < 5:
                    text_message += messages.drove_people_l5.format(
                        drove_people=captain_info.get('drove_people'))
                else:
                    text_message += messages.drove_people_g5.format(
                        drove_people=captain_info.get('drove_people'))
                text_message += messages.last_time_drove.format(
                    last_created=captain_info.get('last_created'))

        embed = discord.Embed(title=messages.statistics_user_title,
                              colour=discord.Colour.blue(),
                              description=text_message)
        # Add avatar
        if user:
            embed.set_author(
                name=str(user),
                icon_url=user.avatar_url,
            )
        return embed

    @commands.command(name=command_names.function_command.user_statistics,
                      help=help_text.user_statistics)
    async def user_statistics(self, ctx: Context, nickname=''):
        """
        Send all information about the user collected by bot as message in current channel.

        Attributes:
        ----------
        nickname: str
            information about specific user else about author of command
        """
        user = None
        # Check specific user
        if nickname:
            # Try to find user in db
            user_info = self.database.user.find_user_post_by_name(nickname)
            # If user exist try to find captain activity in db
            if user_info:
                captain_info = self.database.captain.find_captain_post(
                    user_info['discord_user'])
                user = self.bot.get_user(user_info['discord_id'])
            else:
                captain_info = None
        else:
            # If specific user not exist get current user
            user = ctx.author
            user_info = self.database.user.find_user_post(str(user))
            captain_info = self.database.captain.find_captain_post(str(user))

        embed = self.user_stat_msg(user, user_info, captain_info)
        await ctx.send(embed=embed)
        log_template.command_success(ctx)

    @commands.command(name=command_names.function_command.guild_statistics,
                      help=help_text.guild_statistics)
    @commands.has_permissions(administrator=True, manage_messages=True)
    async def guild_statistics(self, ctx: Context):
        """
        Send all information about the current server collected by bot as message in current channel.
        """
        guild = ctx.guild
        user = ctx.author
        guild_info = self.database.settings.find_settings_post(guild.id)

        # Collect all information from db
        text_message = messages.no_data
        if guild_info and guild_info.get('can_remove_in_channels'):
            text_message = messages.can_remove_msgs_in
            for channel_id, channel in guild_info.get(
                    'can_remove_in_channels').items():
                text_message += f" - **{channel}**\n"

        embed = discord.Embed(title=messages.statistics_guild_title,
                              colour=discord.Colour.blue(),
                              description=text_message)

        embed.set_author(
            name=str(guild),
            icon_url=user.guild.icon_url,
        )

        await ctx.send(embed=embed)
        log_template.command_success(ctx)
示例#7
0
class RaidJoining(commands.Cog):
    """
    Cog that responsible for entering and exiting the raid.
    """
    database = database_process.DatabaseManager()
    raid_list = raid_list.RaidList()

    def __init__(self, bot):
        self.bot = bot

    async def raid_reaction_add(self, collection_msg: discord.Message,
                                emoji: discord.Emoji, user: discord.User):
        """
        Getting user into raid by adding reaction.

        Attributes:
        ----------
        collection_msg: discord.Message
            Collection message through which user can get into the raid.
        emoji: discord.Emoji
            Emoji that user added to get into raid.
        user: discord.User
            User that want to get into raid
        """
        if str(emoji) != '❤' or user.id == settings.BOT_ID:
            return

        guild = collection_msg.guild
        channel = collection_msg.channel

        # Check registration
        nickname = self.database.user.find_user(str(user))
        if not nickname:
            await user.send(messages.no_registration)
            log_template.reaction(guild, channel, user, emoji,
                                  logger_msgs.no_registration)
            return

        current_raid = self.raid_list.find_raid_by_coll_id(collection_msg.id)

        # Check user exists in raid
        if nickname in current_raid:
            await user.send(messages.already_in_raid)
            log_template.reaction(guild, channel, user, emoji,
                                  logger_msgs.already_in_raid)
            return

        if current_raid.is_full:
            log_template.reaction(guild, channel, user, emoji,
                                  logger_msgs.raid_is_full)
            await user.send(messages.raid_not_joined)
            return

        # If user already in same raid
        if not self.raid_list.is_correct_join(
                nickname, current_raid.raid_time.time_leaving):
            log_template.reaction(guild, channel, user, emoji,
                                  logger_msgs.already_in_same_raid)
            await user.send(messages.already_joined)
            return

        msg_success = messages.raid_joined.format(
            captain_name=current_raid.captain_name,
            server=current_raid.server,
            time_leaving=current_raid.raid_time.time_leaving,
        )

        # Add user into raid
        current_raid += nickname
        self.database.user.user_joined_raid(str(user))

        await user.send(msg_success)
        await current_raid.raid_msgs.update_coll_msg(self.bot)
        log_template.reaction(
            guild, channel, user, emoji,
            logger_msgs.raid_joining.format(
                captain_name=current_raid.captain_name))

    async def raid_reaction_remove(self, collection_msg: discord.Message,
                                   emoji: discord.Emoji, user: discord.User):
        """
        Allow user exit raid by removing reaction.

        Attributes:
        ----------
        collection_msg: discord.Message
            Collection message through which user can get into the raid.
        emoji: discord.Emoji
            Emoji that user added to exit raid.
        user: discord.User
            User that want exit raid
        """
        if str(emoji) != '❤' or user.id == settings.BOT_ID:
            return

        current_raid = self.raid_list.find_raid_by_coll_id(collection_msg.id)

        nickname = self.database.user.find_user(str(user))
        if not nickname or nickname not in current_raid:
            return

        # Remove user from raid
        current_raid -= nickname
        self.database.user.user_leave_raid(str(user))

        await user.send(
            messages.raid_leave.format(captain_name=current_raid.captain_name))
        await current_raid.raid_msgs.update_coll_msg(self.bot)

        guild = collection_msg.guild
        channel = collection_msg.channel
        log_template.reaction(
            guild, channel, user, emoji,
            logger_msgs.raid_leaving.format(
                captain_name=current_raid.captain_name))

    @commands.command(name=command_names.function_command.reserve,
                      help=help_text.reserve)
    @commands.guild_only()
    @commands.has_role('Капитан')
    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)

    @commands.command(name=command_names.function_command.remove_res,
                      help=help_text.remove_res)
    @commands.guild_only()
    @commands.has_role('Капитан')
    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)