async def leaderboard(self, inter: disnake.ApplicationCommandInteraction, start: int = 1): if not await self.validate_leaderboard_offset(start, inter): return embed = disnake.Embed() value_num = math.ceil(start / config.karma_grillbot_leaderboard_size) value = messages.karma_web if value_num == 1 else f"{messages.karma_web}{value_num}" embed.add_field(name=messages.karma_web_title, value=value) page_source = LeaderboardPageSource( bot=self.bot, author=inter.author, query=karma_r.leaderboard_query(Database_karma.karma.desc()), row_formatter=self._leaderboard_formatter, base_embed=embed, title='KARMA LEADERBOARD', emote_name='trophy', member_id_col_name='member_ID', ) page_num = math.floor(start / page_source.per_page) page = page_source.get_page(page_num) embed = page_source.format_page(page) await self.check.botroom_check(inter) view = EmbedView(embeds=[embed], page_source=page_source) view.message = await inter.response.send_message(embed=embed, view=view)
async def get_streamlinks(self, ctx: commands.Context, subject: str): streamlinks = self.repo.get_streamlinks_of_subject(subject.lower()) if len(streamlinks) == 0: await ctx.reply(content=Messages.streamlinks_no_stream) return embeds = [] for idx, link in enumerate(streamlinks): embeds.append( self.create_embed_of_link(link, ctx.author, len(streamlinks), idx + 1)) view = EmbedView(embeds, timeout=180) view.message = await ctx.reply(embed=embeds[0], view=view)
async def help(self, ctx: commands.Context, *command): # Subcommand help command = ' '.join(command) if command: command_obj = self.bot.get_command(command) if not command_obj: await ctx.send( utils.fill_message('help_command_not_found', command=command)) else: # if command group, show all possible subcommands if type(command_obj) == commands.Group: subcommands = [] if command_obj.usage is not None: subcommands.append( command_obj.usage.replace('[', '').replace(']', '')) subcommands += [ subcommand.name for subcommand in command_obj.commands ] text = f"`{config.default_prefix}{command_obj.name} [{', '.join(subcommands)}]`" else: text = f"`{config.default_prefix}{command_obj} {command_obj.signature}`" if command_obj.description: text += f"\n{command_obj.description}" elif command_obj.brief: text += f"\n{command_obj.brief}" await ctx.send(text) return # General help footer_text = commit = f"Commit {self.git.hash()}" pages = self.generate_pages(ctx) pages_total = len(pages) embeds = [] for idx, page in enumerate(pages): embed = self.generate_embed(page) if pages_total > 1: footer_text = f"Strana {idx+1}/{pages_total} | {commit}" embed.set_footer(text=footer_text, icon_url=ctx.author.display_avatar.url) embeds.append(embed) view = EmbedView(embeds, author=ctx.author.id) view.message = await ctx.reply(embed=embeds[0], view=view)
async def huggers(self, ctx: commands.Context): """ Get the biggest huggers. """ async with ctx.typing(): page_source = LeaderboardPageSource( bot=self.bot, author=ctx.author, query=self.hugs_repo.get_top_givers_query(), row_formatter=self._tophuggers_formatter, title='TOP HUGGERS', emote_name='peepoHugger') page = page_source.get_page(0) embed = page_source.format_page(page) await self.check.botroom_check(ctx.message) view = EmbedView(embeds=[embed], page_source=page_source) view.message = await ctx.send(embed=embed, view=view)
async def hugboard(self, ctx: commands.Context): """ Overall hugging stats. """ async with ctx.typing(): page_source = LeaderboardPageSource( bot=self.bot, author=ctx.author, query=self.hugs_repo.get_top_all_query(), row_formatter=_tophugs_formatter, title='HUGBOARD', emote_name='peepoHugger', ) page = page_source.get_page(0) embed = page_source.format_page(page) await self.check.botroom_check(ctx.message) view = EmbedView(embeds=[embed], page_source=page_source) view.message = await ctx.send(embed=embed, view=view)
async def ishaboard(self, inter: disnake.ApplicationCommandInteraction, start: int = 1): if not await self.validate_leaderboard_offset(start, inter): return page_source = LeaderboardPageSource( bot=self.bot, author=inter.author, query=karma_r.leaderboard_query(Database_karma.negative.desc()), row_formatter=self._negative_formatter, title='KARMA ISHABOARD', emote_name='ishagrin', member_id_col_name='member_ID', ) page_num = math.floor(start / page_source.per_page) page = page_source.get_page(page_num) embed = page_source.format_page(page) await self.check.botroom_check(inter) view = EmbedView(embeds=[embed], page_source=page_source) view.message = await inter.response.send_message(embed=embed, view=view)
async def process_exams( self, ctx: Union[commands.Context, disnake.TextChannel, disnake.Message], year: Union[str, None], author: Optional[disnake.User] = None, ): date = datetime.date.today() semester = "ZS" if 3 < date.month < 9: semester = "LS" cal_year = date.year if date.month < 9: cal_year -= 1 all_url = f"https://minerva3.fit.vutbr.cz/rozvrhis/{semester}{cal_year}/zkousky" year_url = f"{all_url}/{year}" description = f"[Odkaz na zkoušky ročníku]({year_url})\n" if year else "" description += f"[Odkaz na všechny zkoušky]({all_url})" title = (f"Zkoušky {year} {semester}{cal_year}-{cal_year + 1}" if year else f"Zkoušky {semester}{cal_year}-{cal_year + 1}") r = requests.get(year_url) if r.status_code == 200: soup = BeautifulSoup(r.content, "html.parser") table = soup.find("table", {"class": "exam"}) body = table.find("tbody") if body is None: # There is no table so no terms embed = disnake.Embed(title=title, description=description, color=disnake.Color.dark_blue()) utils.add_author_footer( embed, author if author is not None else self.bot.user) if isinstance(ctx, commands.Context): return await ctx.send(embed=embed) # There is body so start parsing table exams = body.find_all("tr") number_of_exams = len(exams) bs = config.exams_page_size number_of_batches = math.ceil(number_of_exams / bs) exam_batches = [ exams[i * bs:bs + i * bs] for i in range(number_of_batches) ] term_strings_dict = {} pages = [] for exam_batch in exam_batches: embed = disnake.Embed(title=title, description=description, color=disnake.Color.dark_blue()) utils.add_author_footer( embed, author if author is not None else self.bot.user) for exam in exam_batch: # Every exams row start with link tag tag = exam.find("a") if str(exam).startswith( "<tr><td><a") else None cols = exam.find_all("td") # Check if tag is not None and get strong and normal subject tag subject_tag = (tag.find("strong") or tag.contents[0] ) if tag is not None else None if subject_tag is None: content = re.sub(CLEANR, "", str(cols[0])) embed.add_field(name="Poznámka", value=content, inline=False) else: del cols[0] if not isinstance(subject_tag, NavigableString): subject_tag = subject_tag.contents[0] col_count = len(cols) if col_count == 1: # Support for credits col = cols[0] strong_tag = col.find("strong") if strong_tag is None: # There is no term - Only text embed.add_field(name=subject_tag, value=col.contents[0], inline=False) else: # Mainly for terms without specified time term_date_string = strong_tag.contents[ 0].replace("\xa0", "").replace(" ", "") date_splits = term_date_string.split(".") # Without actual time set time to end of the day term_datetime = datetime.datetime( int(date_splits[2]), int(date_splits[1]), int(date_splits[0]), 23, 59) term_date = datetime.date( int(date_splits[2]), int(date_splits[1]), int(date_splits[0])) term_content = f"{term_date_string}\n{col.contents[0]}" # Calculate character offsets padded_term_date = datetime.date.strftime( term_date, "%d.%m.%Y") date_offset = " " * (DATE_OFFSET - len(subject_tag)) time_offset = " " * ( TIME_OFFSET - len(padded_term_date) ) # Here used aas data offset term_string = f"{subject_tag}{date_offset}{padded_term_date}" term_string += f"{time_offset}{col.contents[0]}" if term_date == datetime.date.today(): term_strings_dict[ term_datetime] = f"- {term_string}" elif term_datetime < datetime.datetime.now(): subject_tag = f"~~{subject_tag}~~" term_content = f"~~{term_content}~~" else: term_strings_dict[ term_datetime] = f"+ {term_string}" embed.add_field(name=subject_tag, value=term_content, inline=False) else: # Classic terms whole_term_count = 0 for idx, col in enumerate(cols): terms = col.find_all("strong") times = col.find_all("em") number_of_terms = len(terms) whole_term_count += number_of_terms for idx2, (term_date_string, time) in enumerate(zip( terms, times)): term_date_string = ( term_date_string.contents[0].replace( "\xa0", "").replace(" ", "")) term_time_string = "" for c in time.contents: term_time_string += str(c) term_time_string = term_time_string.replace( "<sup>", ":").replace("</sup>", "") date_splits = term_date_string.split(".") start_time_string_parts = ( term_time_string.split("-")[0].replace( " ", "").split(":")) end_time_string_parts = ( term_time_string.split("-")[1].replace( " ", "").split(":")) term_datetime = datetime.datetime( int(date_splits[2]), int(date_splits[1]), int(date_splits[0]), int(start_time_string_parts[0]), int(start_time_string_parts[1]), ) term_date = datetime.date( int(date_splits[2]), int(date_splits[1]), int(date_splits[0])) name = ( f"{idx + 1}. {subject_tag}" if number_of_terms == 1 else f"{idx + 1}.{idx2 + 1} {subject_tag}") if (start_time_string_parts is not None and end_time_string_parts is not None): start_time = datetime.time( int(start_time_string_parts[0]), int(start_time_string_parts[1])) start_time_string = datetime.time.strftime( start_time, "%H:%M") end_time = datetime.time( int(end_time_string_parts[0]), int(end_time_string_parts[1])) end_time_string = datetime.time.strftime( end_time, "%H:%M") term_time_string = f"{start_time_string} - {end_time_string}" padded_term_date = datetime.date.strftime( term_date, "%d.%m.%Y") term_date_time_string = f"{padded_term_date} {term_time_string}" # Calculate character offsets date_offset = " " * (DATE_OFFSET - len(name)) time_offset = " " * (TIME_OFFSET - len(padded_term_date)) term_string = f"{name}{date_offset}{padded_term_date}" term_string += f"{time_offset}{term_time_string}" if term_date == datetime.date.today(): term_strings_dict[ term_datetime] = f"- {term_string}" elif term_datetime < datetime.datetime.now( ): name = f"~~{name}~~" term_date_time_string = f"~~{term_date_time_string}~~" else: term_strings_dict[ term_datetime] = f"+ {term_string}" embed.add_field( name=name, value=term_date_time_string) to_add = math.ceil( whole_term_count / 3) * 3 - whole_term_count for _ in range(to_add): embed.add_field(name="\u200b", value="\u200b") pages.append(embed) if len(pages) == 0: embed = disnake.Embed(title=title, description=description, color=disnake.Color.dark_blue()) utils.add_author_footer( embed, author if author is not None else self.bot.user) pages.append(embed) if isinstance(ctx, commands.Context): view = EmbedView(pages) view.message = await ctx.reply(embed=pages[0], view=view) else: header = disnake.Embed(title=title, description=description, color=disnake.Color.dark_blue()) await self.handle_exams_with_database_access( term_strings_dict, header, ctx) else: # Site returned fail code embed = disnake.Embed(title=title, description=description, color=disnake.Color.dark_blue()) utils.add_author_footer( embed, author if author is not None else self.bot.user) if isinstance(ctx, commands.Context): await ctx.send(embed=embed)
async def urban_pages(self, inter, embeds): """Send message and handle pagination for 300 seconds""" view = EmbedView(embeds) view.message = await inter.edit_original_message(embed=embeds[0], view=view)
async def tierboard( self, inter: disnake.ApplicationCommandInteraction, type: str = commands.Param(name='typ', choices=['P', 'PVT', 'PVA', 'V']), sem: str = commands.Param(name='semestr', choices=['Z', 'L']), year: str = commands.Param( name='rocnik', choices=["1BIT", "2BIT", "3BIT", "1MIT", "2MIT"], default='' ) ): """Board of suject based on average tier from reviews""" degree = None author = inter.author if not inter.guild: # DM guild = self.bot.get_guild(config.guild_id) author = guild.get_member(author.id) if not year: for role in author.roles: if any(deg in role.name for deg in ["BIT", "MIT"]): if role.name == "4BIT+": year = "3BIT" elif role.name == "0BIT": year = "1BIT" elif role.name == "0MIT": year = "1MIT" elif role.name == "3MIT+": year = "2MIT" else: year = role.name break if "BIT" in year: degree = "BIT" if "MIT" in year: degree = "MIT" if not degree and not year: await inter.send(Messages.tierboard_missing_year, ephemeral=True) return embeds = [] embed = disnake.Embed(title="Tierboard") embed.timestamp = datetime.datetime.now(tz=datetime.timezone.utc) embed.add_field(name="Typ", value=type) embed.add_field(name="Semestr", value="Letní" if sem == "L" else "Zimní") if type != "P": embed.add_field(name="Program", value=degree) year = "" else: embed.add_field(name="Ročník", value=year) utils.add_author_footer(embed, author) pages_total = self.repo.get_tierboard_page_count(type, sem, degree, year) for page in range(pages_total): board = self.repo.get_tierboard(type, sem, degree, year, page*10) output = "" cnt = 1 for line in board: output += f"{cnt} - **{line.shortcut}**: {round(line.avg_tier, 1)}\n" cnt += 1 embed.description = output embeds.append(copy.copy(embed)) if pages_total == 0: embed.description = "" embeds.append(embed) view = EmbedView(embeds) view.message = await inter.response.send_message(embed=embeds[0], view=view)