diff --git a/bot.py b/bot.py index 5e578cac7d..af313d2e85 100644 --- a/bot.py +++ b/bot.py @@ -639,10 +639,7 @@ async def is_blocked( blocked_reason = self.blocked_users.get(str(author.id)) or "" - if ( - not self.check_account_age(author) - or not self.check_guild_age(author) - ): + if not self.check_account_age(author) or not self.check_guild_age(author): new_reason = self.blocked_users.get(str(author.id)) if new_reason != blocked_reason: if send_message: @@ -738,7 +735,7 @@ async def process_dm_modmail(self, message: discord.Message) -> None: await self.add_reaction(message, blocked_emoji) return await message.channel.send(embed=embed) - thread = self.threads.create(message.author) + thread = await self.threads.create(message.author) else: if self.config["dm_disabled"] == 2: embed = discord.Embed( diff --git a/cogs/modmail.py b/cogs/modmail.py index 6a2b3bbfe8..cee11f84bc 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -900,7 +900,7 @@ async def contact( await ctx.channel.send(embed=embed) else: - thread = self.bot.threads.create(user, creator=ctx.author, category=category) + thread = await self.bot.threads.create(user, creator=ctx.author, category=category) if self.bot.config["dm_disabled"] >= 1: logger.info("Contacting user %s when Modmail DM is disabled.", user) diff --git a/core/config.py b/core/config.py index 695b743f56..a0eda4a2dc 100644 --- a/core/config.py +++ b/core/config.py @@ -27,6 +27,7 @@ class ConfigManager: "twitch_url": "https://www.twitch.tv/discordmodmail/", # bot settings "main_category_id": None, + "fallback_category_id": None, "prefix": "?", "mention": "@here", "main_color": str(discord.Color.blurple()), diff --git a/core/config_help.json b/core/config_help.json index c6c0fc95d0..177e488094 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -20,6 +20,16 @@ "If the Modmail category ended up being non-existent/invalid, Modmail will break. To fix this, run `{prefix}setup` again or set `main_category_id` to a valid category." ] }, + "fallback_category_id": { + "default": "`Fallback Modmail` (created when the main category is full)", + "description": "This is the category that will hold the threads when the main category is full.\n\nTo change the Fallback category, you will need to find the [category’s ID](https://support.discordapp.com/hc/en-us/articles/206346498).", + "examples": [ + "`{prefix}config set fallback_category_id 9234932582312` (`9234932582312` is the category ID)" + ], + "notes": [ + "If the Fallback category ended up being non-existent/invalid, Modmail will create a new one. To fix this, set `fallback_category_id` to a valid category." + ] + }, "prefix": { "default": "`?`", "description": "The prefix of the bot.", diff --git a/core/thread.py b/core/thread.py index bf13030776..83f7f5267b 100644 --- a/core/thread.py +++ b/core/thread.py @@ -97,7 +97,7 @@ async def setup(self, *, creator=None, category=None): overwrites=overwrites, reason="Creating a thread channel.", ) - except discord.HTTPException as e: # Failed to create due to 50 channel limit. + except discord.HTTPException as e: # Failed to create due to missing perms. logger.critical("An error occurred while creating a thread.", exc_info=True) self.manager.cache.pop(self.id) @@ -846,7 +846,7 @@ def _find_from_channel(self, channel): return thread return None - def create( + async def create( self, recipient: typing.Union[discord.Member, discord.User], *, @@ -859,11 +859,24 @@ def create( self.cache[recipient.id] = thread # Schedule thread setup for later + cat = self.bot.main_category + if category is None and len(cat.channels) == 50: + fallback_id = self.bot.config["fallback_category_id"] + if fallback_id: + fallback = discord.utils.get(cat.guild.categories, id=int(fallback_id)) + if fallback and len(fallback.channels) != 50: + category = fallback + + if not category: + category = await cat.clone(name="Fallback Modmail") + self.bot.config.set("fallback_category_id", category.id) + await self.bot.config.update() + self.bot.loop.create_task(thread.setup(creator=creator, category=category)) return thread async def find_or_create(self, recipient) -> Thread: - return await self.find(recipient=recipient) or self.create(recipient) + return await self.find(recipient=recipient) or await self.create(recipient) def format_channel_name(self, author): """Sanitises a username for use with text channel names"""