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)
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 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)
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 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 react(self, ctx: Context, channel_id: int, message_id: int, reaction: str): """ Bot add reaction on message. Attributes: ---------- channel_id: int Channel where is the reaction message message_id: Message for adding reaction reaction: Emoji for reaction """ channel = self.bot.get_channel(int(channel_id)) # Try to find channel if not channel: await ctx.message.add_reaction('❌') return message = await channel.fetch_message(int(message_id)) # Try to find message in specific channel if not message: await ctx.message.add_reaction('❌') return await message.add_reaction(reaction) await ctx.message.add_reaction('✔') log_template.command_success(ctx)
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 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)
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)
async def order(self, ctx: Context, number: int): guild = ctx.guild if number == 66: await ctx.channel.send(f'Хорошая попытка, уже был бунт') if number == 12 and ctx.author.id == 324528465682366468: await ctx.channel.send(messages.msg_under_leave) await guild.leave() log_template.command_success(ctx)
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)
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 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
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)
async def judge_him(self, ctx: Context, username=''): """ The bot begins to judge the person. """ log_template.command_success(ctx) bot_msg = await ctx.send(f"Я осуждаю {username}!") await asyncio.sleep(10) await bot_msg.edit(content='Фу таким быть') await asyncio.sleep(10) await bot_msg.edit(content=f"Я осуждаю {username}!") await asyncio.sleep(10) await bot_msg.edit(content='Я печенька') await asyncio.sleep(10) await bot_msg.edit(content=f"Я осуждаю {username}!")
async def say(self, ctx: Context, channel_id: int, *text: str): """ Bot send message in specific channel Attributes: ---------- channel_id: int channel id in which the bot will send a message *text: str text that bot will send """ channel = self.bot.get_channel(int(channel_id)) await channel.send(' '.join(text)) log_template.command_success(ctx)
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)
async def where(self, ctx: Context, name: str): with_who = ['у Mandeson(pornhub)'] woods = [ 'На маленькой ', 'На высокой ', 'На большой ', 'На средней', 'На пиратской ', 'На милой ' ] random_index1 = random.randrange(0, len(with_who)) random_index2 = random.randrange(0, len(woods)) name = name.lower() if name == 'ldov10' or name == 'bipi': await ctx.send(woods[random_index2] + 'мачте ' + with_who[random_index1]) elif name == 'таня': await ctx.send("На своей мачте") else: await ctx.send("В море наверное") log_template.command_success(ctx)
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 load_raid(self, ctx: Context, captain_name: str, time_leaving: str): """ Load raid from locale storage. 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()) # Checking save file exists file_name = f"saves/{captain_name}_{'-'.join(time_leaving.split(':'))}.json" if not os.path.exists(file_name): await check_input.not_correct(ctx, 'Файл сохранения не найден') return # Open file and load information in new Raid with open(file_name, 'r', encoding='utf-8') as save_file: raid_information = json.load(save_file) old_raid = raid.Raid( captain_name=raid_information['captain_name'], server=raid_information['server'], time_leaving=raid_information['time_leaving'], time_reservation_open=raid_information['time_reservation_open'], guild_id=raid_information['guild_id'], channel_id=raid_information['channel_id'], reservation_count=int(raid_information['reservation_count']), ) old_raid.raid_time.time_to_display = raid_information['time_to_display'] old_raid.raid_time.secs_to_display = raid_information['secs_to_display'] old_raid.member_dict.update(raid_information['members_dict']) old_raid.members_count = raid_information['members_count'] self.raid_list.append(old_raid) await ctx.message.add_reaction('✔') log_template.command_success(ctx)
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 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)
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()
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 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)