aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar ToxicKidz <[email protected]>2022-02-23 23:11:59 -0500
committerGravatar GitHub <[email protected]>2022-02-23 23:11:59 -0500
commit91621bc7ef590118e91bbb2e387db5e14128b530 (patch)
treeef0fc2a0225a08be8a184e2c89def2cd417ea139
parentMerge pull request #2101 from python-discord/fix/help-channels-attribute-error (diff)
parentMerge branch 'main' into feature/nonpinging-helper-notify (diff)
Merge pull request #2071 from minalike/feature/nonpinging-helper-notify
Notify helpers without ping when dormant channels are running low
-rw-r--r--bot/constants.py6
-rw-r--r--bot/exts/help_channels/_channel.py4
-rw-r--r--bot/exts/help_channels/_cog.py23
-rw-r--r--bot/exts/help_channels/_message.py93
-rw-r--r--config-default.yml17
5 files changed, 97 insertions, 46 deletions
diff --git a/bot/constants.py b/bot/constants.py
index 77c01bfa3..b775848fb 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -620,10 +620,12 @@ class HelpChannels(metaclass=YAMLGetter):
max_available: int
max_total_channels: int
name_prefix: str
- notify: bool
notify_channel: int
notify_minutes: int
- notify_roles: List[int]
+ notify_none_remaining: bool
+ notify_none_remaining_roles: List[int]
+ notify_running_low: bool
+ notify_running_low_threshold: int
class RedirectOutput(metaclass=YAMLGetter):
diff --git a/bot/exts/help_channels/_channel.py b/bot/exts/help_channels/_channel.py
index ea7d972b5..d9cebf215 100644
--- a/bot/exts/help_channels/_channel.py
+++ b/bot/exts/help_channels/_channel.py
@@ -24,7 +24,7 @@ class ClosingReason(Enum):
"""All possible closing reasons for help channels."""
COMMAND = "command"
- LATEST_MESSSAGE = "auto.latest_message"
+ LATEST_MESSAGE = "auto.latest_message"
CLAIMANT_TIMEOUT = "auto.claimant_timeout"
OTHER_TIMEOUT = "auto.other_timeout"
DELETED = "auto.deleted"
@@ -77,7 +77,7 @@ async def get_closing_time(channel: discord.TextChannel, init_done: bool) -> t.T
# Use the greatest offset to avoid the possibility of prematurely closing the channel.
time = Arrow.fromdatetime(msg.created_at) + timedelta(minutes=idle_minutes_claimant)
- reason = ClosingReason.DELETED if is_empty else ClosingReason.LATEST_MESSSAGE
+ reason = ClosingReason.DELETED if is_empty else ClosingReason.LATEST_MESSAGE
return time, reason
claimant_time = Arrow.utcfromtimestamp(claimant_time)
diff --git a/bot/exts/help_channels/_cog.py b/bot/exts/help_channels/_cog.py
index f276a7993..a93acffb6 100644
--- a/bot/exts/help_channels/_cog.py
+++ b/bot/exts/help_channels/_cog.py
@@ -78,7 +78,10 @@ class HelpChannels(commands.Cog):
self.channel_queue: asyncio.Queue[discord.TextChannel] = None
self.name_queue: t.Deque[str] = None
- self.last_notification: t.Optional[arrow.Arrow] = None
+ # Notifications
+ # Using a very old date so that we don't have to use Optional typing.
+ self.last_none_remaining_notification = arrow.get('1815-12-10T18:00:00.00000+00:00')
+ self.last_running_low_notification = arrow.get('1815-12-10T18:00:00.00000+00:00')
self.dynamic_message: t.Optional[int] = None
self.available_help_channels: t.Set[discord.TextChannel] = set()
@@ -252,13 +255,21 @@ class HelpChannels(commands.Cog):
if not channel:
log.info("Couldn't create a candidate channel; waiting to get one from the queue.")
- notify_channel = self.bot.get_channel(constants.HelpChannels.notify_channel)
- last_notification = await _message.notify(notify_channel, self.last_notification)
+ last_notification = await _message.notify_none_remaining(self.last_none_remaining_notification)
+
if last_notification:
- self.last_notification = last_notification
- self.bot.stats.incr("help.out_of_channel_alerts")
+ self.last_none_remaining_notification = last_notification
+
+ channel = await self.wait_for_dormant_channel() # Blocks until a new channel is available
+
+ else:
+ last_notification = await _message.notify_running_low(
+ self.channel_queue.qsize(),
+ self.last_running_low_notification
+ )
- channel = await self.wait_for_dormant_channel()
+ if last_notification:
+ self.last_running_low_notification = last_notification
return channel
diff --git a/bot/exts/help_channels/_message.py b/bot/exts/help_channels/_message.py
index 241dd606c..7ceed9b4d 100644
--- a/bot/exts/help_channels/_message.py
+++ b/bot/exts/help_channels/_message.py
@@ -124,52 +124,93 @@ async def dm_on_open(message: discord.Message) -> None:
)
-async def notify(channel: discord.TextChannel, last_notification: t.Optional[Arrow]) -> t.Optional[Arrow]:
+async def notify_none_remaining(last_notification: Arrow) -> t.Optional[Arrow]:
"""
- Send a message in `channel` notifying about a lack of available help channels.
+ Send a pinging message in `channel` notifying about there being no dormant channels remaining.
If a notification was sent, return the time at which the message was sent.
Otherwise, return None.
Configuration:
-
- * `HelpChannels.notify` - toggle notifications
- * `HelpChannels.notify_minutes` - minimum interval between notifications
- * `HelpChannels.notify_roles` - roles mentioned in notifications
+ * `HelpChannels.notify_minutes` - minimum interval between notifications
+ * `HelpChannels.notify_none_remaining` - toggle none_remaining notifications
+ * `HelpChannels.notify_none_remaining_roles` - roles mentioned in notifications
"""
- if not constants.HelpChannels.notify:
- return
+ if not constants.HelpChannels.notify_none_remaining:
+ return None
+
+ if (arrow.utcnow() - last_notification).total_seconds() < (constants.HelpChannels.notify_minutes * 60):
+ log.trace("Did not send none_remaining notification as it hasn't been enough time since the last one.")
+ return None
log.trace("Notifying about lack of channels.")
- if last_notification:
- elapsed = (arrow.utcnow() - last_notification).seconds
- minimum_interval = constants.HelpChannels.notify_minutes * 60
- should_send = elapsed >= minimum_interval
- else:
- should_send = True
+ mentions = " ".join(f"<@&{role}>" for role in constants.HelpChannels.notify_none_remaining_roles)
+ allowed_roles = [discord.Object(id_) for id_ in constants.HelpChannels.notify_none_remaining_roles]
- if not should_send:
- log.trace("Notification not sent because it's too recent since the previous one.")
- return
+ channel = bot.instance.get_channel(constants.HelpChannels.notify_channel)
+ if channel is None:
+ log.trace("Did not send none_remaining notification as the notification channel couldn't be gathered.")
try:
- log.trace("Sending notification message.")
-
- mentions = " ".join(f"<@&{role}>" for role in constants.HelpChannels.notify_roles)
- allowed_roles = [discord.Object(id_) for id_ in constants.HelpChannels.notify_roles]
-
- message = await channel.send(
+ await channel.send(
f"{mentions} A new available help channel is needed but there "
- f"are no more dormant ones. Consider freeing up some in-use channels manually by "
+ "are no more dormant ones. Consider freeing up some in-use channels manually by "
f"using the `{constants.Bot.prefix}dormant` command within the channels.",
allowed_mentions=discord.AllowedMentions(everyone=False, roles=allowed_roles)
)
-
- return Arrow.fromdatetime(message.created_at)
except Exception:
# Handle it here cause this feature isn't critical for the functionality of the system.
log.exception("Failed to send notification about lack of dormant channels!")
+ else:
+ bot.instance.stats.incr("help.out_of_channel_alerts")
+ return arrow.utcnow()
+
+
+async def notify_running_low(number_of_channels_left: int, last_notification: Arrow) -> t.Optional[Arrow]:
+ """
+ Send a non-pinging message in `channel` notifying about there being a low amount of dormant channels.
+
+ This will include the number of dormant channels left `number_of_channels_left`
+
+ If a notification was sent, return the time at which the message was sent.
+ Otherwise, return None.
+
+ Configuration:
+ * `HelpChannels.notify_minutes` - minimum interval between notifications
+ * `HelpChannels.notify_running_low` - toggle running_low notifications
+ * `HelpChannels.notify_running_low_threshold` - minimum amount of channels to trigger running_low notifications
+ """
+ if not constants.HelpChannels.notify_running_low:
+ return None
+
+ if number_of_channels_left > constants.HelpChannels.notify_running_low_threshold:
+ log.trace("Did not send notify_running_low notification as the threshold was not met.")
+ return None
+
+ if (arrow.utcnow() - last_notification).total_seconds() < (constants.HelpChannels.notify_minutes * 60):
+ log.trace("Did not send notify_running_low notification as it hasn't been enough time since the last one.")
+ return None
+
+ log.trace("Notifying about getting close to no dormant channels.")
+
+ channel = bot.instance.get_channel(constants.HelpChannels.notify_channel)
+ if channel is None:
+ log.trace("Did not send notify_running notification as the notification channel couldn't be gathered.")
+
+ try:
+ if number_of_channels_left == 1:
+ message = f"There is only {number_of_channels_left} dormant channel left. "
+ else:
+ message = f"There are only {number_of_channels_left} dormant channels left. "
+ message += "Consider participating in some help channels so that we don't run out."
+ await channel.send(message)
+ except Exception:
+ # Handle it here cause this feature isn't critical for the functionality of the system.
+ log.exception("Failed to send notification about running low of dormant channels!")
+ else:
+ bot.instance.stats.incr("help.running_low_alerts")
+ return arrow.utcnow()
async def pin(message: discord.Message) -> None:
diff --git a/config-default.yml b/config-default.yml
index 583733fda..dae923158 100644
--- a/config-default.yml
+++ b/config-default.yml
@@ -513,19 +513,16 @@ help_channels:
# Prefix for help channel names
name_prefix: 'help-'
- # Notify if more available channels are needed but there are no more dormant ones
- notify: true
+ notify_channel: *HELPERS # Channel in which to send notifications messages
+ notify_minutes: 15 # Minimum interval between none_remaining or running_low notifications
- # Channel in which to send notifications
- notify_channel: *HELPERS
-
- # Minimum interval between helper notifications
- notify_minutes: 15
-
- # Mention these roles in notifications
- notify_roles:
+ notify_none_remaining: true # Pinging notification for the Helper role when no dormant channels remain
+ notify_none_remaining_roles: # Mention these roles in the none_remaining notification
- *HELPERS_ROLE
+ notify_running_low: true # Non-pinging notification which is triggered when the channel count is equal or less than the threshold
+ notify_running_low_threshold: 4 # The amount of channels at which a running_low notification will be sent
+
redirect_output:
delete_delay: 15