From dbd06bfe38146d317d60ec637054abe8b268114e Mon Sep 17 00:00:00 2001 From: nexy7574 Date: Fri, 5 Jul 2024 00:34:14 +0100 Subject: [PATCH] Add the refresh button --- src/cogs/election.py | 85 +++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/src/cogs/election.py b/src/cogs/election.py index d35fb1e..633cdcc 100644 --- a/src/cogs/election.py +++ b/src/cogs/election.py @@ -2,6 +2,8 @@ This module is only meant to be loaded during election times. """ import asyncio +from calendar import c +from contextlib import asynccontextmanager import logging import random import datetime @@ -148,46 +150,63 @@ class ElectionCog(commands.Cog): # ] return results - @commands.slash_command(name="election") - async def get_election_results(self, ctx: discord.ApplicationContext): - """Gets the current election results""" - await ctx.defer() + async def _get_embed(self) -> discord.Embed | None: async with httpx.AsyncClient(headers=self.HEADERS) as client: response = await client.get(self.SOURCE, follow_redirects=True) if response.status_code != 200: - return await ctx.respond( - "Sorry, I can't do that right now (HTTP %d while fetching results from BBC)" % response.status_code - ) - - # noinspection PyTypeChecker + raise RuntimeError(f"HTTP {response.status_code} while fetching results from BBC") soup = await asyncio.to_thread(BeautifulSoup, response.text, "html.parser") - results = await self.bot.loop.run_in_executor(None, self.process_soup, soup) - if results: - now = discord.utils.utcnow() - date = now.date().strftime("%B %Y") - colour_scores = {} - embed = discord.Embed( - title="Election results - " + date, - url="https://bbc.co.uk/", - timestamp=now + results = await self.bot.loop.run_in_executor(None, self.process_soup, soup) + if results: + now = discord.utils.utcnow() + date = now.date().strftime("%B %Y") + colour_scores = {} + embed = discord.Embed( + title="Election results - " + date, + url="https://bbc.co.uk/", + timestamp=now + ) + embed.set_footer(text="Source from bbc.co.uk.") + description_parts = [] + + for party_name, values in results.items(): + councillors, net, colour = values + colour_scores[party_name] = councillors + symbol = "+" if net > 0 else '' + description_parts.append( + f"**{party_name}**: {symbol}{net:,} ({councillors:,} total)" ) - embed.set_footer(text="Source from bbc.co.uk.") - description_parts = [] - for party_name, values in results.items(): - councillors, net, colour = values - colour_scores[party_name] = councillors - symbol = "+" if net > 0 else '' - description_parts.append( - f"**{party_name}**: {symbol}{net:,} ({councillors:,} total)" - ) + top_party = list(sorted(colour_scores.keys(), key=lambda k: colour_scores[k], reverse=True))[0] + embed.colour = discord.Colour(results[top_party][2]) + embed.description = "\n".join(description_parts) + return embed - top_party = list(sorted(colour_scores.keys(), key=lambda k: colour_scores[k], reverse=True))[0] - embed.colour = discord.Colour(results[top_party][2]) - embed.description = "\n".join(description_parts) - return await ctx.respond(embed=embed) - else: - return await ctx.respond("Unable to get election results at this time.") + @commands.slash_command(name="election") + async def get_election_results(self, ctx: discord.ApplicationContext): + """Gets the current election results""" + class RefreshView(discord.ui.View): + @discord.ui.button(label="Refresh", style=discord.ButtonStyle.primary, emoji="\U0001f501") + async def refresh(_self, _btn, interaction): + await interaction.response.defer(invisible=True) + try: + embed = await self._get_embed() + except Exception as e: + self.log.exception("Failed to get election results.") + return await interaction.followup.send(f"Sorry, I cannot contact the BBC at this time: {e}") + if embed is None: + return await interaction.followup.send("Sorry, I could not find any election results.") + await interaction.edit_original_response(embed=embed) + + await ctx.defer() + try: + embed = await self._get_embed() + except Exception as e: + self.log.exception("Failed to get election results.") + return await ctx.respond(f"Sorry, I cannot contact the BBC at this time: {e}") + if embed is None: + return await ctx.respond("Sorry, I could not find any election results.") + await ctx.respond(embed=embed, view=RefreshView()) def setup(bot):