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