aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Mark <[email protected]>2020-04-16 15:05:22 -0700
committerGravatar GitHub <[email protected]>2020-04-16 15:05:22 -0700
commitc6c87378cd6dd65e2fac83b97d48430c3cb0917c (patch)
treeadfeac6f64ed5ffc2f4e728d29bce4501199924c
parentMerge pull request #396 from ks129/keyerrors-fix (diff)
parentMerge branch 'master' into wait-until-guild-ready (diff)
Merge pull request #395 from python-discord/wait-until-guild-ready
Wait until guild ready
-rw-r--r--bot/bot.py36
-rw-r--r--bot/exts/easter/egg_facts.py7
-rw-r--r--bot/exts/evergreen/branding.py2
-rw-r--r--bot/exts/halloween/spookysound.py7
-rw-r--r--bot/exts/pride/pride_facts.py7
5 files changed, 48 insertions, 11 deletions
diff --git a/bot/bot.py b/bot/bot.py
index 4f238df8..b0162377 100644
--- a/bot/bot.py
+++ b/bot/bot.py
@@ -44,6 +44,8 @@ class SeasonalBot(commands.Bot):
self.http_session = ClientSession(
connector=TCPConnector(resolver=AsyncResolver(), family=socket.AF_INET)
)
+ self._guild_available = asyncio.Event()
+
self.loop.create_task(self.send_log("SeasonalBot", "Connected!"))
@property
@@ -149,7 +151,7 @@ class SeasonalBot(commands.Bot):
async def send_log(self, title: str, details: str = None, *, icon: str = None) -> None:
"""Send an embed message to the devlog channel."""
- await self.wait_until_ready()
+ await self.wait_until_guild_available()
devlog = self.get_channel(Channels.devlog)
if not devlog:
@@ -168,5 +170,37 @@ class SeasonalBot(commands.Bot):
await devlog.send(embed=embed)
+ async def on_guild_available(self, guild: discord.Guild) -> None:
+ """
+ Set the internal `_guild_available` event when PyDis guild becomes available.
+
+ If the cache appears to still be empty (no members, no channels, or no roles), the event
+ will not be set.
+ """
+ if guild.id != Client.guild:
+ return
+
+ if not guild.roles or not guild.members or not guild.channels:
+ log.warning("Guild available event was dispatched but the cache appears to still be empty!")
+ return
+
+ self._guild_available.set()
+
+ async def on_guild_unavailable(self, guild: discord.Guild) -> None:
+ """Clear the internal `_guild_available` event when PyDis guild becomes unavailable."""
+ if guild.id != Client.guild:
+ return
+
+ self._guild_available.clear()
+
+ async def wait_until_guild_available(self) -> None:
+ """
+ Wait until the PyDis guild becomes available (and the cache is ready).
+
+ The on_ready event is inadequate because it only waits 2 seconds for a GUILD_CREATE
+ gateway event before giving up and thus not populating the cache for unavailable guilds.
+ """
+ await self._guild_available.wait()
+
bot = SeasonalBot(command_prefix=Client.prefix)
diff --git a/bot/exts/easter/egg_facts.py b/bot/exts/easter/egg_facts.py
index 83918fb0..0051aa50 100644
--- a/bot/exts/easter/egg_facts.py
+++ b/bot/exts/easter/egg_facts.py
@@ -6,6 +6,7 @@ from pathlib import Path
import discord
from discord.ext import commands
+from bot.bot import SeasonalBot
from bot.constants import Channels, Colours, Month
from bot.utils.decorators import seasonal_task
@@ -19,7 +20,7 @@ class EasterFacts(commands.Cog):
It also contains a background task which sends an easter egg fact in the event channel everyday.
"""
- def __init__(self, bot: commands.Bot):
+ def __init__(self, bot: SeasonalBot):
self.bot = bot
self.facts = self.load_json()
@@ -35,7 +36,7 @@ class EasterFacts(commands.Cog):
@seasonal_task(Month.APRIL)
async def send_egg_fact_daily(self) -> None:
"""A background task that sends an easter egg fact in the event channel everyday."""
- await self.bot.wait_until_ready()
+ await self.bot.wait_until_guild_available()
channel = self.bot.get_channel(Channels.seasonalbot_commands)
await channel.send(embed=self.make_embed())
@@ -55,6 +56,6 @@ class EasterFacts(commands.Cog):
)
-def setup(bot: commands.Bot) -> None:
+def setup(bot: SeasonalBot) -> None:
"""Easter Egg facts cog load."""
bot.add_cog(EasterFacts(bot))
diff --git a/bot/exts/evergreen/branding.py b/bot/exts/evergreen/branding.py
index 72f31042..1d463c5b 100644
--- a/bot/exts/evergreen/branding.py
+++ b/bot/exts/evergreen/branding.py
@@ -198,7 +198,7 @@ class BrandingManager(commands.Cog):
All method calls in the internal loop are considered safe, i.e. no errors propagate
to the daemon's loop. The daemon itself does not perform any error handling on its own.
"""
- await self.bot.wait_until_ready()
+ await self.bot.wait_until_guild_available()
while True:
self.current_season = get_current_season()
diff --git a/bot/exts/halloween/spookysound.py b/bot/exts/halloween/spookysound.py
index 325447e5..569a9153 100644
--- a/bot/exts/halloween/spookysound.py
+++ b/bot/exts/halloween/spookysound.py
@@ -5,6 +5,7 @@ from pathlib import Path
import discord
from discord.ext import commands
+from bot.bot import SeasonalBot
from bot.constants import Hacktoberfest
log = logging.getLogger(__name__)
@@ -13,7 +14,7 @@ log = logging.getLogger(__name__)
class SpookySound(commands.Cog):
"""A cog that plays a spooky sound in a voice channel on command."""
- def __init__(self, bot: commands.Bot):
+ def __init__(self, bot: SeasonalBot):
self.bot = bot
self.sound_files = list(Path("bot/resources/halloween/spookysounds").glob("*.mp3"))
self.channel = None
@@ -27,7 +28,7 @@ class SpookySound(commands.Cog):
Cannot be used more than once in 2 minutes.
"""
if not self.channel:
- await self.bot.wait_until_ready()
+ await self.bot.wait_until_guild_available()
self.channel = self.bot.get_channel(Hacktoberfest.voice_id)
await ctx.send("Initiating spooky sound...")
@@ -42,6 +43,6 @@ class SpookySound(commands.Cog):
await voice.disconnect()
-def setup(bot: commands.Bot) -> None:
+def setup(bot: SeasonalBot) -> None:
"""Spooky sound Cog load."""
bot.add_cog(SpookySound(bot))
diff --git a/bot/exts/pride/pride_facts.py b/bot/exts/pride/pride_facts.py
index f759dcb1..c453bfa1 100644
--- a/bot/exts/pride/pride_facts.py
+++ b/bot/exts/pride/pride_facts.py
@@ -9,6 +9,7 @@ import dateutil.parser
import discord
from discord.ext import commands
+from bot.bot import SeasonalBot
from bot.constants import Channels, Colours, Month
from bot.utils.decorators import seasonal_task
@@ -20,7 +21,7 @@ Sendable = Union[commands.Context, discord.TextChannel]
class PrideFacts(commands.Cog):
"""Provides a new fact every day during the Pride season!"""
- def __init__(self, bot: commands.Bot):
+ def __init__(self, bot: SeasonalBot):
self.bot = bot
self.facts = self.load_facts()
@@ -35,7 +36,7 @@ class PrideFacts(commands.Cog):
@seasonal_task(Month.JUNE)
async def send_pride_fact_daily(self) -> None:
"""Background task to post the daily pride fact every day."""
- await self.bot.wait_until_ready()
+ await self.bot.wait_until_guild_available()
channel = self.bot.get_channel(Channels.seasonalbot_commands)
await self.send_select_fact(channel, datetime.utcnow())
@@ -101,6 +102,6 @@ class PrideFacts(commands.Cog):
)
-def setup(bot: commands.Bot) -> None:
+def setup(bot: SeasonalBot) -> None:
"""Cog loader for pride facts."""
bot.add_cog(PrideFacts(bot))