async def remove_channel_from_whitelist( self, ctx: discord.CommandInteraction, channel_name: str = commands.Param( description=Strings.warden_channel_remove_channel_description, autocomplete=text_channels_autocomplete)): channel = discord.utils.get(ctx.guild.channels, name=channel_name) if channel is None: return await ctx.send(embed=general_util.generate_error_message( Strings.populate_string("warden_channel_doesnt_exist", name=channel_name)), delete_after=Config.base_error_duration) settings = self.warden_repo.get_warden_settings(ctx.guild) if str(channel.id) not in settings.whitelist_channel_ids: return await ctx.send(embed=general_util.generate_error_message( Strings.populate_string("warden_channel_is_not_in_whitelist", name=channel_name)), delete_after=Config.base_error_duration) channel_ids = settings.whitelist_channel_ids.split(";") channel_ids.remove(str(channel.id)) channels_string = ";".join(channel_ids) settings.whitelist_channel_ids = channels_string self.warden_repo.update() await ctx.send( embed=general_util.generate_success_message("Settings updated"), delete_after=Config.base_success_duration)
async def role_giver_disable(self, ctx: commands.Context, role_giver_id: int): await general_util.delete_message(self.bot, ctx) role_giver = self.role_giver_repo.get_role_giver_by_id(role_giver_id) if role_giver is None: return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_doesnt_exist), delete_after=Config.base_error_duration) if role_giver.guild_ID != str(ctx.guild.id): return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_doesnt_belong_to_this_guild), delete_after=Config.base_error_duration) if not role_giver.enabled: return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_disable_already_disabled), delete_after=Config.base_error_duration) role_giver.enabled = False await self.delete_role_giver_instance(role_giver) self.role_giver_repo.update() await ctx.send(embed=general_util.generate_success_message( Strings.populate_string("role_giver_disable_success", id=role_giver.id)), delete_after=Config.base_success_duration)
async def edit_reminder_message(self, ctx: commands.Context, reminder_id: int, *, message: str): await general_util.delete_message(self.bot, ctx) reminder = self.reminder_repo.get_reminder_by_id(reminder_id) if reminder is None: return await ctx.send(embed=general_util.generate_error_message( Strings.reminder_invalid_id), delete_after=Config.base_error_duration) if reminder.user_ID == str( ctx.author.id) or ctx.author.id in Config.developer_ids: await self.update_reminder_in_database(reminder, ctx, message=message) await self.update_reminder_message(reminder) await ctx.send(embed=general_util.generate_success_message( Strings.populate_string("reminder_edit_success", id=reminder.id)), delete_after=Config.base_success_duration) else: await ctx.send(embed=general_util.generate_error_message( Strings.reminder_missing_permission), delete_after=Config.base_error_duration)
async def top(self, ctx: commands.Context, *, subreddit: str): await general_util.delete_message(self.bot, ctx) data = await self.make_request_to_reddit(subreddit, 25) if not data: return await ctx.channel.send( embed=general_util.generate_error_message( Strings.reddit_doesnt_exist), delete_after=Config.base_error_duration) idx = 0 data_sel = data[0] while "jpg" not in data_sel[2] and "png" not in data_sel[2]: idx += 1 if idx >= len(data): return await ctx.channel.send( embed=general_util.generate_error_message( Strings.reddit_doesnt_exist), delete_after=Config.base_error_duration) data_sel = data[idx] em = discord.Embed(title=f"{data_sel[0]}", color=discord.Color.blue()) em.set_footer(text=f"{data_sel[1]} Score") em.set_image(url=data_sel[2]) em.set_author(name=data_sel[3]) if data_sel[4]: em.description = data_sel[4] await ctx.send(embed=em)
async def add_filter_emoji(self, ctx: commands.Context, emoji: Union[int, discord.Emoji, discord.PartialEmoji, str]): await general_util.delete_message(self.bot, ctx) if isinstance(emoji, int): emoji = general_util.get_emoji_from_id(general_util.emoji_id_from_emoji(emoji), ctx.guild, self.bot) if emoji is None: return await ctx.send(embed=general_util.generate_error_message(Strings.karma_invalid_emoji), delete_after=Config.base_error_duration) reposter = self.repost_settings_repo.get_repost_settings(ctx.guild.id) if reposter is None: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_no_reposter), delete_after=Config.base_error_duration) emoji_ids = reposter.emoji_ids.split(";") if reposter.emoji_ids is not None else [] if len(emoji_ids) >= Config.reposter_filter_emoji_limit: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_add_filter_emoji_limit_reached), delete_after=Config.base_error_duration) emoji_id = general_util.emoji_id_from_emoji(emoji) if emoji_id in emoji_ids: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_add_filter_emoji_emoji_already_added), delete_after=Config.base_error_duration) emoji_ids.append(emoji_id) emoji_ids_string = ";".join(emoji_ids) reposter.emoji_ids = emoji_ids_string self.repost_settings_repo.update() await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("reposter_add_filter_emoji_success", emoji=emoji)), delete_after=Config.base_success_duration)
async def start_work(self, ctx: commands.Context, hours: int = 1): await general_util.delete_message(self.bot, ctx) if not self.player_repo.is_idle(ctx.author.id): return await ctx.send(embed=general_util.generate_error_message( Strings.rpg_cant_perfor_action_no_idle), delete_after=Config.base_error_duration) if hours < 0 or hours > 12: return await ctx.send(embed=general_util.generate_error_message( Strings.rpg_work_invalid_work_time), delete_after=Config.base_error_duration) end_date = datetime.now(tz=timezone.utc) + timedelta(hours=hours) action = self.player_repo.create_action(ctx.author, ActionsEnum.WORK, end_date) reward_string = rpg_util.get_expected_rewards_string(action.rewards) embed = discord.Embed(title="Work started", description=reward_string, color=discord.Color.blue()) embed.add_field(name="Duration", value=f"{hours}h") embed.add_field(name="End time (UTC)", value=end_date.strftime("%d.%b.%Y %H:%M")) general_util.add_author_footer(embed, ctx.author) await ctx.send(embed=embed, delete_after=Config.base_long_success_duration)
async def items_list(self, ctx: commands.Context, item_id:Optional[int]=None): await general_util.delete_message(self.bot, ctx) if item_id is None: items = self.item_repo.get_all_items() items_embeds = [] for item in items: embed = rpg_util.generate_item_embed(item) general_util.add_author_footer(embed, ctx.author) items_embeds.append(embed) if items_embeds: p_session = PaginatorSession(self.bot, ctx, pages=items_embeds) await p_session.run() else: await ctx.send(embed=general_util.generate_error_message(Strings.rpg_items_list_no_items), delete_after=Config.base_error_duration) else: item = self.item_repo.get_item_by_id(item_id) if item is None: return await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("rpg_item_not_found", id=item_id)), delete_after=Config.base_error_duration) embed = rpg_util.generate_item_embed(item) general_util.add_author_footer(embed, ctx.author) await ctx.send(embed=embed, delete_after=Config.base_long_success_duration)
async def grab_item(self, ctx: commands.Context, user: Union[discord.Member, discord.User, int], item_id: int, all:bool=False): await general_util.delete_message(self.bot, ctx) if isinstance(user, int): user_id = user user = await general_util.get_user(self.bot, user_id) if user is None: return await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("rpg_user_doesnt_exist", id=user_id)), delete_after=Config.base_error_duration) item = self.item_repo.get_item_by_id(item_id) if item is None: return await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("rpg_item_not_found", id=item_id)), delete_after=Config.base_error_duration) player = self.player_repo.get_player(user) inventory_slots:List[InventorySlot] = player.inventory for inventory_slot in inventory_slots: if inventory_slot.item.id == item.id: if all: self.player_repo.remove_all_from_inventory(int(player.user_id), item.id) return await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("rpg_items_grab_all_success", user=user.mention, item_name=item.name)), delete_after=Config.base_success_duration) else: self.player_repo.remove_from_inventory(int(player.user_id), item.id) return await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("rpg_items_grab_success", user=user.mention, item_name=item.name)), delete_after=Config.base_success_duration) await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("rpg_items_grab_item_not_in_inventory", user=user.mention, item_name=item.name)), delete_after=Config.base_error_duration)
async def add_filter_channel(self, ctx: commands.Context, channel: Union[discord.TextChannel, int]): await general_util.delete_message(self.bot, ctx) reposter = self.repost_settings_repo.get_repost_settings(ctx.guild.id) if reposter is None: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_no_reposter), delete_after=Config.base_error_duration) channel_ids = reposter.mode_channel_ids.split(";") if reposter.mode_channel_ids is not None else [] if len(channel_ids) >= Config.reposter_filter_channel_limit: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_add_filter_channel_limit_reached), delete_after=Config.base_error_duration) if isinstance(channel, discord.TextChannel): if str(channel.id) in channel_ids: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_add_filter_channel_already_added), delete_after=Config.base_error_duration) else: tmp_chan = await general_util.get_text_channel(ctx.guild, channel) if tmp_chan is None: return await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("reposter_add_filter_channel_invalid_id", id=channel)), delete_after=Config.base_error_duration) channel = tmp_chan if str(channel.id) == reposter.repost_channel_id: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_add_filter_channel_filter_same_as_repost), delete_after=Config.base_error_duration) channel_ids.append(str(channel.id)) channel_ids_string = ";".join(channel_ids) reposter.mode_channel_ids = channel_ids_string self.repost_settings_repo.update() await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("reposter_add_filter_channel_success", channel=channel.name)), delete_after=Config.base_success_duration)
async def exams(self, ctx: commands.Context, year: Union[str, None] = None): await general_util.delete_message(self.bot, ctx) if year is None: if isinstance(ctx.author, discord.Member): user_roles: List[discord.Role] = ctx.author.roles for role in user_roles: match = re.match(year_regex, role.name) if match is not None: year = self.process_match(match) if year is None: await ctx.send(embed=general_util.generate_error_message(Strings.exams_invalid_year), delete_after=Config.base_error_duration) return await self.process_exams(ctx, year) await ctx.send(embed=general_util.generate_error_message(Strings.exams_year_role_not_found)) else: year = year.upper() match = re.match(year_regex, year) if match is not None: year = self.process_match(match) if year is None: await ctx.send(embed=general_util.generate_error_message(Strings.exams_invalid_year), delete_after=Config.base_error_duration) await self.process_exams(ctx, year) else: await ctx.send(embed=general_util.generate_error_message(Strings.exams_invalid_year), delete_after=Config.base_error_duration)
async def process_request(ctx:Union[commands.Context, discord.CommandInteraction], room:str): url = f"https://www.fit.vut.cz/fit/map/.cs?show={room.upper()}&big=1" r = requests.get(url) if r.status_code != 200: return await ctx.send(embed=general_util.generate_error_message(Strings.fitroom_bad_response), delete_after=Config.base_error_duration) try: soup = BeautifulSoup(r.content, 'html.parser') main_body_ = soup.find("main", {"id": "main"}) floor_list_ = main_body_.find("ul", {"class": "pagination__list"}) active_floor_ = floor_list_.find("a", {"aria-current": "page"}) image_ = main_body_.find("svg") cursor_ = image_.find("polygon", {"class": "arrow"}) except Exception: logger.error(f"Failed to parse fit room\n{traceback.format_exc()}") return await ctx.send(embed=general_util.generate_error_message(Strings.fitroom_page_parsing_failed), delete_after=Config.base_error_duration) if image_ is None or cursor_ is None: return await ctx.send(embed=general_util.generate_error_message(Strings.fitroom_room_not_on_plan), delete_after=Config.base_error_duration) image_bytes = BytesIO() image_bytestring = str(image_).replace("/img/su/logo-kachnicka-mapa.png", "https://www.fit.vut.cz/img/su/logo-kachnicka-mapa.png").encode("utf-8") svg2png(bytestring=image_bytestring, write_to=image_bytes, parent_width=720, parent_height=1000, background_color="white", dpi=300) image_bytes.seek(0) embed = discord.Embed(title=f"Room {room}", color=discord.Color.dark_blue()) embed.set_image(url="attachment://plan.png") embed.description = f"[Link to website]({url})" embed.set_footer(text=str(active_floor_.text)) file = discord.File(fp=image_bytes, filename="plan.png") await ctx.send(embed=embed, file=file)
async def set_description(self, ctx: commands.Context, role_giver_id: int, *, description: str): await general_util.delete_message(self.bot, ctx) role_giver = self.role_giver_repo.get_role_giver_by_id(role_giver_id) if role_giver is None: return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_doesnt_exist), delete_after=Config.base_error_duration) if role_giver.guild_ID != str(ctx.guild.id): return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_doesnt_belong_to_this_guild), delete_after=Config.base_error_duration) if role_giver.enabled: await self.delete_role_giver_instance(role_giver) role_giver.enabled = False if len(description) > 4000: self.role_giver_repo.update() return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_description_too_long), delete_after=Config.base_error_duration) role_giver.description = description self.role_giver_repo.update() await ctx.send(embed=general_util.generate_success_message( Strings.populate_string("role_giver_description_success", description=description, id=role_giver.id)), delete_after=Config.base_success_duration)
async def update_reminder_in_database(self, reminder: ReminderData, ctx: commands.Context, date: str = None, time: str = None, message: str = None): if date is not None and time is not None: date_splits = date.split(".") time_splits = time.split(":") date_obj = parse_date_splits(date_splits, time_splits) if date_obj is None: return await ctx.send( embed=general_util.generate_error_message( Strings.reminder_invalid_time_or_date_format), delete_after=Config.base_error_duration) if (datetime.now() + timedelta(minutes=1)) > date_obj: return await ctx.send( embed=general_util.generate_error_message( Strings.reminder_date_in_past), delete_after=Config.base_error_duration) reminder.date = date_obj if message is not None: message = general_util.split_to_parts(message, 3000)[0] reminder.message = message self.reminder_repo.update()
async def unload(self, ctx: commands.Context, extension: str): await ctx.message.delete() if extension in Config.protected_modules: await ctx.channel.send(embed=general_util.generate_error_message(Strings.populate_string("unable_to_unload_protected_cog", extension=extension)), delete_after=Config.base_error_duration) return if extension == "all": loaded_cogs = [cog.file for cog in self.bot.cogs.values()] final_embed = discord.Embed(title="Cog unload", color=discord.Color.green(), description="Failed cogs:") for cog in loaded_cogs: if cog not in Config.protected_modules: try: self.bot.unload_extension(f"cogs.{cog}") logger.info(f'{cog} unloaded') except Exception as e: final_embed.description += f"\n{str(cog)}" final_embed.colour = discord.Color.orange() await ctx.channel.send(embed=general_util.generate_error_message(Strings.populate_string("unable_to_unload_cog", cog=cog, e=e)), delete_after=Config.base_error_duration) await ctx.send(embed=final_embed, delete_after=Config.base_long_success_duration) else: try: self.bot.unload_extension(f"cogs.{extension}") logger.info(f'{extension} unloaded') await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("cog_unloaded", extension=extension)), delete_after=Config.base_success_duration) except Exception as e: await ctx.channel.send(embed=general_util.generate_error_message(Strings.populate_string("unable_to_unload_cog", cog=extension, e=e)), delete_after=Config.base_error_duration)
async def load(self, ctx: commands.Context, extension: str): await ctx.message.delete() if extension == "all": loaded_cogs = [cog.file for cog in self.bot.cogs.values()] cogs_in_folder = [cog[:-3].lower() for cog in os.listdir("cogs") if str(cog).endswith(".py") and "__init__" not in str(cog)] if len(loaded_cogs) == len(cogs_in_folder): await ctx.channel.send(embed=general_util.generate_error_message(Strings.all_cogs_already_loaded), delete_after=Config.base_error_duration) return final_embed = discord.Embed(title="Cog load", color=discord.Color.green(), description="Failed cogs:") for cog in cogs_in_folder: if str(cog) not in loaded_cogs and str(cog) not in Config.protected_modules: try: self.bot.load_extension(f"cogs.{str(cog)}") logger.info(f"{str(cog)} loaded") await asyncio.sleep(0) except Exception as e: final_embed.description += f"\n{str(cog)}" final_embed.colour = discord.Color.orange() await ctx.channel.send(embed=general_util.generate_error_message(Strings.populate_string("unable_to_load_cog", cog=str(cog), e=e)), delete_after=Config.base_error_duration) await ctx.send(embed=final_embed, delete_after=Config.base_long_success_duration) else: try: self.bot.load_extension(f"cogs.{extension}") logger.info(f"{extension} loaded") await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("cog_loaded", extension=extension)), delete_after=Config.base_success_duration) except Exception as e: await ctx.channel.send(embed=general_util.generate_error_message(Strings.populate_string("unable_to_load_cog", cog=extension, e=e)), delete_after=Config.base_error_duration)
async def action_rewards_list(self, ctx: commands.Context, action_id: Optional[int] = None): await general_util.delete_message(self.bot, ctx) if action_id is not None: if action_id not in ActionsEnum.val_list(): return await ctx.send(embed=general_util.generate_error_message(Strings.rpg_list_actions_rewards_invalid_action_id), delete_after=Config.base_error_duration) action_rewards = self.rewards_repo.get_action_rewards(action_id) number_of_rewards = len(action_rewards) number_of_pages = math.ceil(number_of_rewards / 20) batches = [action_rewards[i * 20: i * 20 + 20] for i in range(number_of_pages)] pages = [] for batch in batches: embed = discord.Embed(title="Action rewards list", color=discord.Color.dark_blue()) general_util.add_author_footer(embed, ctx.author) for reward in batch: if reward.reward is not None: embed.add_field(name=f"ID: {reward.reward.id} - {ActionsEnum.get_name(reward.action_id)}", value=rpg_util.reward_to_string(reward.reward)) pages.append(embed) if pages: p_session = PaginatorSession(self.bot, ctx, pages=pages) await p_session.run() else: await ctx.send(embed=general_util.generate_error_message(Strings.rpg_list_actions_rewards_no_rewards), delete_after=Config.base_error_duration)
async def handle_reaction_add(self, ctx: ReactionContext): if self.bot.user.id in (ctx.member.id, ctx.message.author.id): return if not isinstance(ctx.emoji, str): return if ctx.emoji not in self.flag_to_code.keys(): return if ctx.guild.id in self.guilds_usage.keys() and self.guilds_usage[ ctx.guild.id] >= Config.translate_usage_limit_per_10_mins: return await ctx.channel.send( embed=general_util.generate_error_message( Strings.populate_string( "translate_on_cooldown", limit=Config.translate_usage_limit_per_10_mins)), delete_after=Config.base_error_duration) if self.translator.get_usage().any_limit_exceeded: return await ctx.channel.send( embed=general_util.generate_error_message( Strings.translate_api_limit_exceeded), delete_after=Config.base_error_duration) trg_lan = self.flag_to_code[ctx.emoji] if trg_lan.upper() not in self.supp_list: return await ctx.channel.send( embed=general_util.generate_error_message( Strings.translate_unsupported_language), delete_after=Config.base_error_duration) if ctx.message.content is not None and ctx.message.content != "": if len(ctx.message.content) > 1000: return await ctx.channel.send( embed=general_util.generate_error_message( Strings.populate_string( "translate_message_too_large", message_url=ctx.message.jump_url)), delete_after=Config.base_error_duration) if ctx.guild.id in self.guilds_usage.keys(): self.guilds_usage[ctx.guild.id] += 1 else: self.guilds_usage[ctx.guild.id] = 1 result = str( self.translator.translate_text(ctx.message.content, target_lang=trg_lan.upper())) translate_result = discord.Embed( color=discord.Color.dark_blue(), description=str(result) + f"\n\n[Original]({ctx.message.jump_url})", title=f"Translation to {trg_lan.upper()}") general_util.add_author_footer(translate_result, ctx.member) await ctx.channel.send(embed=translate_result)
async def remove_role(self, ctx: commands.Context, role_giver_id: int, role: Union[discord.Role, int, str]): await general_util.delete_message(self.bot, ctx) role_giver = self.role_giver_repo.get_role_giver_by_id(role_giver_id) if role_giver is None: return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_doesnt_exist), delete_after=Config.base_error_duration) if role_giver.guild_ID != str(ctx.guild.id): return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_doesnt_belong_to_this_guild), delete_after=Config.base_error_duration) role_ids = role_giver.role_IDs.split(";") if ( role_giver.role_IDs is not None and role_giver.role_IDs != "") else [] if len(role_ids) == 0: return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_remove_role_nothing_to_remove), delete_after=Config.base_error_duration) if isinstance(role, int): role = general_util.get_role(ctx.guild, role) elif isinstance(role, str): tmp_role = discord.utils.get(ctx.guild.roles, name=role) if tmp_role is None: roles = await ctx.guild.fetch_roles() tmp_role = discord.utils.get(roles, name=role) role = tmp_role if role is None: return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_cant_find_role), delete_after=Config.base_error_duration) if str(role.id) not in role_ids: return await ctx.send(embed=general_util.generate_error_message( Strings.role_giver_remove_role_not_in_roles), delete_after=Config.base_error_duration) if role_giver.enabled: await self.delete_role_giver_instance(role_giver) role_giver.enabled = False role_ids.remove(str(role.id)) role_string = ";".join(role_ids) role_giver.role_IDs = role_string self.role_giver_repo.update() await ctx.send(embed=general_util.generate_success_message( Strings.populate_string("role_giver_remove_role_success", name=role.name, id=role_giver.id)), delete_after=Config.base_success_duration)
async def reposter_create(self, ctx: commands.Context, repost_channel: discord.TextChannel): await general_util.delete_message(self.bot, ctx) if repost_channel.guild.id != ctx.guild.id: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_invalid_channel), delete_after=Config.base_error_duration) if self.repost_settings_repo.create_repost_settings(ctx.guild, repost_channel.id) is None: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_create_already_exist), delete_after=Config.base_error_duration) await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("reposter_create_success", chname=repost_channel.name)), delete_after=Config.base_success_duration)
async def _leave_s(self, ctx:commands.Context, sid: int): server = self.bot.get_guild(sid) if server: try: await server.leave() await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("system_server_left", name=server.name)), delete_after=Config.base_success_duration) except: await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("system_server_left_failed", name=server.name)), delete_after=Config.base_error_duration) else: await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("system_leave_server_id_not_found", sid=sid)), delete_after=Config.base_error_duration)
async def warden_scan( self, ctx: discord.CommandInteraction, limit: str = commands.Param( description=Strings.warden_scan_limit_description, default="all"), channel: str = commands.Param( description=Strings.warden_scan_channel_description, default=None, autocomplete=text_channels_autocomplete)): if channel is None: channel = ctx.channel else: channel = discord.utils.get(ctx.guild.channels, name=channel) if channel is None: return await ctx.send( embed=general_util.generate_error_message( Strings.populate_string("warden_channel_doesnt_exist", name=channel)), delete_after=Config.base_error_duration) guild_warden_settings = self.warden_repo.get_warden_settings(ctx.guild) if str(channel.id) not in guild_warden_settings.whitelist_channel_ids: return await ctx.send(embed=general_util.generate_error_message( Strings.populate_string("warden_channel_is_not_in_whitelist", name=channel.name)), delete_after=Config.base_error_duration) if limit.isnumeric(): limit = int(limit) elif limit == "all": limit = None else: return await ctx.send(embed=general_util.generate_error_message( Strings.warden_scan_bad_limit_format), delete_after=Config.base_error_duration) messages = await channel.history(limit=limit).flatten() ctr_hashes = 0 now = time.time() for i, message in enumerate(messages): if len(message.attachments) == 0: continue hashes = [x async for x in self.generate_message_hash(message)] ctr_hashes += len(hashes) await ctx.send( content="**SCAN COMPLETE**\n\n" f"Processed **{len(messages)}** messages.\n" f"Computed **{ctr_hashes}** hashes in {(time.time() - now):.1f} seconds.", delete_after=Config.base_long_success_duration)
async def reposter_threshold(self, ctx: commands.Context, threshold: int): await general_util.delete_message(self.bot, ctx) if threshold < 1: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_threshold_invalid_threshold), delete_after=Config.base_error_duration) reposter = self.repost_settings_repo.get_repost_settings(ctx.guild.id) if reposter is None: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_no_reposter), delete_after=Config.base_error_duration) reposter.emoji_threshold = threshold self.repost_settings_repo.update() await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("reposter_threshold_success", value=threshold)), delete_after=Config.base_success_duration)
async def create_effect(self, ctx: commands.Context, item_id:int, effect_id:int, ammount:int): await general_util.delete_message(self.bot, ctx) if not self.item_repo.item_exist(item_id): return await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("rpg_item_not_found", id=item_id)), delete_after=Config.base_error_duration) if effect_id not in EffectEnum.val_list(): return await ctx.send(embed=general_util.generate_error_message(Strings.rpg_items_effect_create_invalid_effect_id), delete_after=Config.base_error_duration) effect = self.item_repo.create_effect(item_id, effect_id, ammount) embed = rpg_util.generate_effect_embed(effect) general_util.add_author_footer(embed, ctx.author) await ctx.send(embed=embed, delete_after=Config.base_long_success_duration)
async def list_recent(self, ctx: commands.Context, limit:Optional[int]=None): await general_util.delete_message(self.bot, ctx) audit_logs = self.audit_repo.get_recent_logs(limit=limit) log_strings = [] for audit_log in audit_logs: user_name = audit_log.user.username if audit_log.user is not None else None if user_name is not None: display_name = audit_log.guild_user.display_name if audit_log.guild_user is not None else None if display_name is not None and display_name != user_name: user_name = f"{user_name} ({display_name})" guild_name = audit_log.guild.name if audit_log.guild is not None else None item_list = [str(audit_log.id), user_name, guild_name, audit_log.type.name, str(audit_log.created_at)] try: item_list.remove(None) except: pass log_strings.append(" - ".join(item_list)) if not log_strings: return await ctx.send(embed=general_util.generate_error_message("*No audit logs*"), delete_after=Config.base_error_duration) final_texts = [] while log_strings: tmp_text, log_strings = general_util.add_string_until_length(log_strings, 4000, "\n") final_texts.append(tmp_text) for text in final_texts: await ctx.send(f"```{text}```", delete_after=Config.base_long_success_duration)
async def get_player(self, ctx: commands.Context, *, player: Optional[Union[discord.Member, discord.User, int]] = None): await general_util.delete_message(self.bot, ctx) if player is None: player = ctx.author elif isinstance(player, int): player = await general_util.get_user(self.bot, player) if player is None: return ctx.send(embed=general_util.generate_error_message( Strings.rpg_player_get_player_doesnt_exist), delete_after=Config.base_error_duration) db_player = self.player_repo.get_player(player) embed = discord.Embed(title=f"{player.display_name} profile", color=discord.Color.blue()) embed.set_thumbnail( url=player.display_avatar.url if player. display_avatar is not None else player.default_avatar.url) embed.add_field(name="Level", value=str(db_player.level)) embed.add_field(name="XP", value=str(db_player.xp)) embed.add_field( name="XP to level", value=str( rpg_util.get_next_level_xp_requirement(db_player.level) - db_player.xp)) embed.add_field(name="Coins", value=str(db_player.money)) embed.add_field(name="Energy", value=str(db_player.energy)) embed.add_field( name="Inventory", value= f"{self.player_repo.get_current_size_of_inventory(player.id)}/{rpg_util.get_inventory_size(db_player.level)}" ) embed.add_field(name="Action", value=ActionsEnum.get_name(db_player.action.action_id) if db_player.action is not None else "None") if db_player.action is not None: embed.add_field( name="Remaining time", value=humanize.naturaldelta( db_player.action.end_date.replace(tzinfo=timezone.utc) - datetime.now(tz=timezone.utc))) embed.add_field( name="Return time (UTC)", value=db_player.action.end_date.strftime("%d.%b.%Y %H:%M")) if db_player.action.rewards: rewards_str = rpg_util.get_expected_rewards_string( db_player.action.rewards, length_limit=1000, header=False) if rewards_str != "": embed.add_field(name="Action reward", value=rewards_str) general_util.add_author_footer(embed, ctx.author) await ctx.send(embed=embed, delete_after=Config.base_long_success_duration)
async def set_birthday(self, ctx:commands.Context, date:str): await delete_message(self.bot, ctx) date_splits = date.split(".") if len(date_splits) != 3: return await ctx.send(embed=generate_error_message(Strings.set_birthday_invalid_date_format), delete_after=Config.base_error_duration) for date_split in date_splits: if not date_split.isalnum(): return await ctx.send(embed=generate_error_message(Strings.set_birthday_invalid_date_format), delete_after=Config.base_error_duration) day = int(date_splits[0]) month = int(date_splits[1]) year = int(date_splits[2]) self.repo.set_birthday(ctx.author, datetime.date(2000, month, day), year) await ctx.send(embed=generate_success_message(Strings.populate_string("set_birthday_success", date=date)), delete_after=Config.base_success_duration)
async def remove_filter_channel(self, ctx: commands.Context, channel: Union[discord.TextChannel, int]): await general_util.delete_message(self.bot, ctx) reposter = self.repost_settings_repo.get_repost_settings(ctx.guild.id) if reposter is None: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_no_reposter), delete_after=Config.base_error_duration) channel_ids = reposter.mode_channel_ids.split(";") if reposter.mode_channel_ids is not None else [] channel_id_string = str(channel.id) if isinstance(channel, discord.TextChannel) else str(channel) if not channel_id_string in channel_ids: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_remove_filter_channel_channel_not_present), delete_after=Config.base_error_duration) channel_ids.remove(channel_id_string) reposter.mode_channel_ids = ";".join(channel_ids) self.repost_settings_repo.update() await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("reposter_remove_filter_channel_success", channel=channel.name if isinstance(channel, discord.TextChannel) else channel)), delete_after=Config.base_success_duration)
async def reposter_channel(self, ctx: commands.Context, channel: discord.TextChannel): await general_util.delete_message(self.bot, ctx) if channel.guild.id != ctx.guild.id: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_invalid_channel), delete_after=Config.base_error_duration) reposter = self.repost_settings_repo.get_repost_settings(ctx.guild.id) if reposter is None: return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_no_reposter), delete_after=Config.base_error_duration) if str(channel.id) in (reposter.mode_channel_ids if reposter.mode_channel_ids is not None else []): return await ctx.send(embed=general_util.generate_error_message(Strings.reposter_channel_repost_channel_in_filter_channels), delete_after=Config.base_error_duration) reposter.repost_channel_id = str(channel.id) self.repost_settings_repo.update() await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("reposter_channel_success", name=channel.name)), delete_after=Config.base_success_duration)
async def remove_reminder(self, ctx: commands.Context, reminder_id: int): await general_util.delete_message(self.bot, ctx) reminder = self.reminder_repo.get_reminder_by_id(reminder_id) if reminder is None: return await ctx.send(embed=general_util.generate_error_message( Strings.reminder_invalid_id), delete_after=Config.base_error_duration) if reminder.user_ID == str( ctx.author.id) or ctx.author.id in Config.developer_ids: # If user is author of reminder or admin remove whole reminder if Config.reminder_delete_reminder_created_message_on_expire: try: channel = await self.bot.fetch_channel( int(reminder.reminder_message_channel_ID)) if channel is not None: reminder_message: Union[ discord.Message, None] = await channel.fetch_message( int(reminder.reminder_message_ID)) if reminder_message is not None: await reminder_message.delete() except: pass self.reminder_repo.delete_reminder_by_id(reminder.id) await ctx.send(embed=general_util.generate_success_message( Strings.reminder_remove_author_success), delete_after=Config.base_success_duration) self.reminder_force_update = True elif self.reminder_repo.user_in_subscribers(ctx.author.id, reminder.id): # If its subscriber then remove it from subscribers async with subscribers_manipulation_lock: self.reminder_repo.remove_subscription(ctx.author, reminder.id) await ctx.send(embed=general_util.generate_success_message( Strings.reminder_remove_subscriber_success), delete_after=Config.base_success_duration) else: await ctx.send(embed=general_util.generate_error_message( Strings.reminder_remove_missing_permissions), delete_after=Config.base_error_duration)
async def give_item(self, ctx: commands.Context, user:Union[discord.Member, discord.User, int], item_id:int): await general_util.delete_message(self.bot, ctx) if isinstance(user, int): user_id = user user = await general_util.get_user(self.bot, user_id) if user is None: return await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("rpg_user_doesnt_exist", id=user_id)), delete_after=Config.base_error_duration) item = self.item_repo.get_item_by_id(item_id) if item is None: return await ctx.send(embed=general_util.generate_error_message(Strings.populate_string("rpg_item_not_found", id=item_id)), delete_after=Config.base_error_duration) player = self.player_repo.get_player(user) self.player_repo.add_to_inventory(int(player.user_id), item_id) await ctx.send(embed=general_util.generate_success_message(Strings.populate_string("rpg_items_give_success", user=user.mention, item_name=item.name)), delete_after=Config.base_success_duration) await ctx.send(embed=rpg_util.generate_item_embed(item), delete_after=Config.base_success_duration)