tickets_plus.cogs.routines
Tasks that run in the background from time to time.
This is where the bot's background tasks are defined. These tasks are scheduled to run at a specific interval, and are generally used to perform some sort of maintenance or cleanup. Like cleaning up users who are no longer prevented from something.
Typical usage example:
from tickets_plus import bot bot_instance = bot.TicketsPlusBot(...) await bot_instance.load_extension("tickets_plus.cogs.routines")
1"""Tasks that run in the background from time to time. 2 3This is where the bot's background tasks are defined. These tasks are 4scheduled to run at a specific interval, and are generally used to 5perform some sort of maintenance or cleanup. Like cleaning up users 6who are no longer prevented from something. 7 8Typical usage example: 9 ```py 10 from tickets_plus import bot 11 bot_instance = bot.TicketsPlusBot(...) 12 await bot_instance.load_extension("tickets_plus.cogs.routines") 13 ``` 14""" 15# License: EPL-2.0 16# SPDX-License-Identifier: EPL-2.0 17# Copyright (c) 2021-present The Tickets+ Contributors 18# This Source Code may also be made available under the following 19# Secondary Licenses when the conditions for such availability set forth 20# in the Eclipse Public License, v. 2.0 are satisfied: GPL-3.0-only OR 21# If later approved by the Initial Contributor, GPL-3.0-or-later. 22 23from discord.ext import commands, tasks 24 25from tickets_plus import bot 26from tickets_plus.database import config 27 28_CNFG = config.RuntimeConfig() 29 30 31class Routines(commands.Cog): 32 """Magic cog for background tasks. 33 34 We do the *real* magic here. This is where the background tasks 35 are defined. These tasks are scheduled to run at a specific 36 interval, and are generally used to perform some sort of 37 maintenance or cleanup. 38 """ 39 40 def __init__(self, bot_instance: bot.TicketsPlusBot): 41 """Initialize the cog. 42 43 This is called when the cog is loaded, and initializes the 44 background tasks. 45 46 Args: 47 bot_instance: The bot instance that loaded the cog. 48 """ 49 self._bt = bot_instance 50 self.clean_status.start() 51 self.notify_users.start() 52 53 async def cog_unload(self): 54 """Cancel all tasks when the cog is unloaded. 55 56 This is called when the cog is unloaded, and cancels all 57 tasks that are running. 58 """ 59 self.clean_status.cancel() 60 self.notify_users.cancel() 61 62 @tasks.loop(seconds=_CNFG.spt_clean_usr) 63 async def clean_status(self): 64 """Remove all status roles from users whose status has expired. 65 66 This task runs every minute, and checks if any users have a 67 status role that has expired. If so, it removes the role from 68 the user. 69 """ 70 async with self._bt.get_connection() as conn: 71 rehabilitated = await conn.get_expired_members() 72 for member in rehabilitated: 73 gld = member.guild 74 usr_id = member.user_id 75 actv_guild = self._bt.get_guild(gld.guild_id) 76 if actv_guild is None: 77 continue 78 actv_member = actv_guild.get_member(usr_id) 79 if actv_member is None: 80 continue 81 rles = [] 82 if gld.helping_block: 83 rles.append(actv_guild.get_role(gld.helping_block)) 84 if gld.support_block: 85 rles.append(actv_guild.get_role(gld.support_block)) 86 await actv_member.remove_roles(*rles, reason="Status expired") 87 member.status = 0 88 member.status_till = None 89 await conn.commit() 90 91 @clean_status.before_loop 92 async def before_clean_status(self): 93 """Delay the first run till the bot is ready. 94 95 Ensures that the bot is ready before the first run of the 96 task. 97 """ 98 await self._bt.wait_until_ready() 99 100 @tasks.loop(seconds=_CNFG.spt_notif_usr) 101 async def notify_users(self): 102 """Notifies users of their tickets closing soon. 103 104 Running every 2 minutes and 30 seconds, this task checks if 105 any tickets are lacking responses, 106 (time since last message above warning threshold) 107 and if so, sends a warning message to the user. 108 """ 109 async with self._bt.get_connection() as conn: 110 tickets = await conn.get_pending_tickets() 111 for ticket in tickets: 112 ticket.notified = True 113 gld = ticket.guild 114 usr_id = ticket.user_id 115 if usr_id is None: 116 continue 117 actv_guild = self._bt.get_guild(gld.guild_id) 118 if actv_guild is None: 119 continue 120 actv_member = actv_guild.get_member(usr_id) 121 if actv_member is None: 122 continue 123 appnd = "Please respond soon, or it will be closed." 124 if gld.any_autoclose: 125 appnd = ( 126 "Please respond soon, or it will be closed " 127 # pylint: disable=line-too-long # skipcq: FLK-E501 128 f"<t:{int((ticket.last_response + gld.any_autoclose).timestamp())}:R>.") 129 txt = (f"Your ticket <#{ticket.channel_id}> in {actv_guild.name} " 130 f"is still open. {appnd}") 131 await actv_member.send(txt) 132 await conn.commit() 133 134 @notify_users.before_loop 135 async def before_notify_users(self): 136 """Delay the first run till the bot is ready. 137 138 Ensures that the bot is ready before the first run of the 139 task. 140 """ 141 await self._bt.wait_until_ready() 142 143 144async def setup(bot_instance: bot.TicketsPlusBot): 145 """Load the cog into the bot. 146 147 This is called when the cog is loaded, and initializes the 148 cog instance. 149 150 Args: 151 bot_instance: The bot instance that loaded the cog. 152 """ 153 await bot_instance.add_cog(Routines(bot_instance))
32class Routines(commands.Cog): 33 """Magic cog for background tasks. 34 35 We do the *real* magic here. This is where the background tasks 36 are defined. These tasks are scheduled to run at a specific 37 interval, and are generally used to perform some sort of 38 maintenance or cleanup. 39 """ 40 41 def __init__(self, bot_instance: bot.TicketsPlusBot): 42 """Initialize the cog. 43 44 This is called when the cog is loaded, and initializes the 45 background tasks. 46 47 Args: 48 bot_instance: The bot instance that loaded the cog. 49 """ 50 self._bt = bot_instance 51 self.clean_status.start() 52 self.notify_users.start() 53 54 async def cog_unload(self): 55 """Cancel all tasks when the cog is unloaded. 56 57 This is called when the cog is unloaded, and cancels all 58 tasks that are running. 59 """ 60 self.clean_status.cancel() 61 self.notify_users.cancel() 62 63 @tasks.loop(seconds=_CNFG.spt_clean_usr) 64 async def clean_status(self): 65 """Remove all status roles from users whose status has expired. 66 67 This task runs every minute, and checks if any users have a 68 status role that has expired. If so, it removes the role from 69 the user. 70 """ 71 async with self._bt.get_connection() as conn: 72 rehabilitated = await conn.get_expired_members() 73 for member in rehabilitated: 74 gld = member.guild 75 usr_id = member.user_id 76 actv_guild = self._bt.get_guild(gld.guild_id) 77 if actv_guild is None: 78 continue 79 actv_member = actv_guild.get_member(usr_id) 80 if actv_member is None: 81 continue 82 rles = [] 83 if gld.helping_block: 84 rles.append(actv_guild.get_role(gld.helping_block)) 85 if gld.support_block: 86 rles.append(actv_guild.get_role(gld.support_block)) 87 await actv_member.remove_roles(*rles, reason="Status expired") 88 member.status = 0 89 member.status_till = None 90 await conn.commit() 91 92 @clean_status.before_loop 93 async def before_clean_status(self): 94 """Delay the first run till the bot is ready. 95 96 Ensures that the bot is ready before the first run of the 97 task. 98 """ 99 await self._bt.wait_until_ready() 100 101 @tasks.loop(seconds=_CNFG.spt_notif_usr) 102 async def notify_users(self): 103 """Notifies users of their tickets closing soon. 104 105 Running every 2 minutes and 30 seconds, this task checks if 106 any tickets are lacking responses, 107 (time since last message above warning threshold) 108 and if so, sends a warning message to the user. 109 """ 110 async with self._bt.get_connection() as conn: 111 tickets = await conn.get_pending_tickets() 112 for ticket in tickets: 113 ticket.notified = True 114 gld = ticket.guild 115 usr_id = ticket.user_id 116 if usr_id is None: 117 continue 118 actv_guild = self._bt.get_guild(gld.guild_id) 119 if actv_guild is None: 120 continue 121 actv_member = actv_guild.get_member(usr_id) 122 if actv_member is None: 123 continue 124 appnd = "Please respond soon, or it will be closed." 125 if gld.any_autoclose: 126 appnd = ( 127 "Please respond soon, or it will be closed " 128 # pylint: disable=line-too-long # skipcq: FLK-E501 129 f"<t:{int((ticket.last_response + gld.any_autoclose).timestamp())}:R>.") 130 txt = (f"Your ticket <#{ticket.channel_id}> in {actv_guild.name} " 131 f"is still open. {appnd}") 132 await actv_member.send(txt) 133 await conn.commit() 134 135 @notify_users.before_loop 136 async def before_notify_users(self): 137 """Delay the first run till the bot is ready. 138 139 Ensures that the bot is ready before the first run of the 140 task. 141 """ 142 await self._bt.wait_until_ready()
Magic cog for background tasks.
We do the real magic here. This is where the background tasks are defined. These tasks are scheduled to run at a specific interval, and are generally used to perform some sort of maintenance or cleanup.
41 def __init__(self, bot_instance: bot.TicketsPlusBot): 42 """Initialize the cog. 43 44 This is called when the cog is loaded, and initializes the 45 background tasks. 46 47 Args: 48 bot_instance: The bot instance that loaded the cog. 49 """ 50 self._bt = bot_instance 51 self.clean_status.start() 52 self.notify_users.start()
Initialize the cog.
This is called when the cog is loaded, and initializes the background tasks.
Arguments:
- bot_instance: The bot instance that loaded the cog.
54 async def cog_unload(self): 55 """Cancel all tasks when the cog is unloaded. 56 57 This is called when the cog is unloaded, and cancels all 58 tasks that are running. 59 """ 60 self.clean_status.cancel() 61 self.notify_users.cancel()
Cancel all tasks when the cog is unloaded.
This is called when the cog is unloaded, and cancels all tasks that are running.
A background task helper that abstracts the loop and reconnection logic for you.
The main interface to create this is through loop().
92 @clean_status.before_loop 93 async def before_clean_status(self): 94 """Delay the first run till the bot is ready. 95 96 Ensures that the bot is ready before the first run of the 97 task. 98 """ 99 await self._bt.wait_until_ready()
Delay the first run till the bot is ready.
Ensures that the bot is ready before the first run of the task.
A background task helper that abstracts the loop and reconnection logic for you.
The main interface to create this is through loop().
135 @notify_users.before_loop 136 async def before_notify_users(self): 137 """Delay the first run till the bot is ready. 138 139 Ensures that the bot is ready before the first run of the 140 task. 141 """ 142 await self._bt.wait_until_ready()
Delay the first run till the bot is ready.
Ensures that the bot is ready before the first run of the task.
145async def setup(bot_instance: bot.TicketsPlusBot): 146 """Load the cog into the bot. 147 148 This is called when the cog is loaded, and initializes the 149 cog instance. 150 151 Args: 152 bot_instance: The bot instance that loaded the cog. 153 """ 154 await bot_instance.add_cog(Routines(bot_instance))
Load the cog into the bot.
This is called when the cog is loaded, and initializes the cog instance.
Arguments:
- bot_instance: The bot instance that loaded the cog.