make docstrings consistent

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
leanderandClaude Opus 5.5 committed 2026-10-29 22:55:32 +01:00
1 parent 1d29222fa4
commit 70c0236a16
30 files changed
+583 -242

No files matched your search

+12 -12
View File
@@ -174,7 +174,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The interaction that triggered this
Returns
----------
@@ -190,7 +190,7 @@ class Anime(commands.Cog):
Parameters
----------
text: The raw HTML
text (str): The raw HTML
Returns
----------
@@ -210,7 +210,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The interaction that triggered this
query (str): The GraphQL query
variables (str): The variables for the query
key (str): The key to return from the response
@@ -340,7 +340,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
user (str): The user to get information about
"""
@@ -468,7 +468,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
user (str): The user to get information about
"""
@@ -561,7 +561,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
user (str): The user to get information about
"""
@@ -656,7 +656,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
search (str): The name of the anime to fetch information about
"""
@@ -812,7 +812,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
search (str): The name of the manga to fetch information about
"""
@@ -945,7 +945,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
search (str): The name of the character to fetch information about
"""
@@ -1041,7 +1041,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
search (str): The name of the creator to fetch information about
"""
@@ -1142,7 +1142,7 @@ class Anime(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
search (str): The name of the studio to fetch information about
"""
@@ -1236,7 +1236,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Anime(bot))
+7 -3
View File
@@ -25,6 +25,10 @@ class Aurora(commands.Cog):
self.aurora_alarm.start()
def cog_unload(self):
"""
Stop the aurora alarm when the cog is unloaded
"""
self.bot.logger.info("Unloading cog")
self.aurora_alarm.cancel()
@@ -33,8 +37,8 @@ class Aurora(commands.Cog):
Get the current aurora and cloud cover forecast for Chateau Neuf
Returns
-------
(dict) The forecast data | None
----------
(dict | None): The forecast data. None if it couldn't be fetched
"""
async with self.bot.http_session.get(
@@ -130,7 +134,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Aurora(bot))
+10 -6
View File
@@ -145,6 +145,10 @@ class Birthday(commands.Cog):
await channel.send(message)
async def cog_unload(self):
"""
Stop the birthday check when the cog is unloaded
"""
self.bot.logger.info("Unloading cog")
self.birthday_check.cancel()
@@ -270,7 +274,7 @@ class Birthday(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
day (int): Day of the month
month (int): Month of the year
year (int): Year
@@ -310,7 +314,7 @@ class Birthday(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
await self.bot.db.execute("DELETE FROM birthdays WHERE discord_id = (%s)", (interaction.user.id,))
@@ -329,8 +333,8 @@ class Birthday(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
user (discord.Member | discord.User | None): The user to show the birthday of. Defaults to None.
interaction (discord.Interaction): The slash command interaction
user (discord.Member | discord.User | None): The user to show the birthday of. Defaults to the invoking user
"""
if not user:
@@ -380,7 +384,7 @@ class Birthday(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
if not interaction.guild:
@@ -424,7 +428,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Birthday(bot))
+6 -6
View File
@@ -30,7 +30,7 @@ class BotInfo(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
# Dev user info
@@ -105,7 +105,7 @@ class BotInfo(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
embed = discord.Embed(color=interaction.client.user.color)
@@ -121,7 +121,7 @@ class BotInfo(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
embed = discord.Embed(color=interaction.client.user.color)
@@ -134,7 +134,7 @@ class BotInfo(commands.Cog):
Returns
----------
(int) The bot's ping in milliseconds
(int): The bot's ping in milliseconds
"""
return int(self.bot.latency * 1000)
@@ -145,7 +145,7 @@ class BotInfo(commands.Cog):
Returns
----------
(str) The bot's uptime in human readable format
(str): The bot's uptime in human readable format
"""
now = time()
@@ -163,7 +163,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(BotInfo(bot))
+47 -2
View File
@@ -42,7 +42,7 @@ class CS2Bingo(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
await open_lobby(interaction, self.active_lobbies, BingoView, "Bingolobby", timedelta(minutes=10))
@@ -64,6 +64,19 @@ class BingoGenerator:
@classmethod
async def sample_cells(cls, players: list[str], bot: commands.Bot) -> dict[str, list[str]]:
"""
Pick 25 squares for each player's sheet
Parameters
----------
players (list[str]): The Discord IDs of the players
bot (commands.Bot): The bot instance
Returns
----------
(dict[str, list[str]]): Each player's squares, keyed by their Discord ID
"""
assert 0 < len(players) <= 10
default_space = list(cls.CELLS["all"])
@@ -97,6 +110,7 @@ class BingoGenerator:
Parameters
----------
players (list[discord.Member]): The players to generate sheets for
bot (commands.Bot): The bot instance
Returns
----------
@@ -118,6 +132,19 @@ class BingoGenerator:
@classmethod
def generate_sheet(cls, sample_space: list, image: np.ndarray) -> bytes:
"""
Draw the squares on a bingo sheet
Parameters
----------
sample_space (list): The squares to draw. Emptied as they are drawn
image (np.ndarray): The empty bingo sheet
Returns
----------
(bytes): The sheet as PNG data
"""
image = image.copy()
# start = 8, 294
@@ -141,12 +168,30 @@ class BingoGenerator:
class BingoView(LobbyView):
"""Bingo lobby that sends every player a bingo sheet when started"""
def __init__(self, lobby: Lobby, bot: commands.Bot):
"""
Parameters
----------
lobby (Lobby): The lobby to show
bot (commands.Bot): The bot instance
"""
super().__init__(lobby, bot)
@discord.ui.button(label="Start", style=discord.ButtonStyle.green)
@override
async def start_lobby(self, interaction: discord.Interaction, button: discord.ui.Button):
"""
Close the lobby and send every player their bingo sheet
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
button (discord.ui.Button): The button that was pressed
"""
if interaction.user != self.lobby.host:
embed = embed_templates.error_warning("Bare hosten kan starte bingoen")
return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10)
@@ -184,7 +229,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(CS2Bingo(bot))
+12 -12
View File
@@ -29,7 +29,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
process = await asyncio.create_subprocess_exec(
@@ -56,7 +56,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
channel (int): The channel ID to send the message to
text (str): The text to send
"""
@@ -80,7 +80,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
activity_type (str): The type of activity to set the bot's status to
message (str): The message to set the bot's status to
status_type (str): The type of status to set the bot's status to
@@ -111,7 +111,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
guild_id (int): The ID of the guild to leave
"""
@@ -155,7 +155,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
async with self.bot.http_session.get("https://wtfismyip.com/json") as response:
@@ -177,7 +177,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
if not ctx.invoked_subcommand:
@@ -190,7 +190,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
cog (str): The name of the cog to disable
"""
@@ -214,7 +214,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
cog (str): The name of the cog to enable
"""
@@ -238,7 +238,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
cog (str): The name of the cog to reload
"""
@@ -262,7 +262,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
extensions = [f"cogs.{file[:-3]}" for file in listdir("./src/cogs") if file.endswith(".py")]
@@ -278,7 +278,7 @@ class DevTools(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
failed = await self.reload_extensions(list(self.bot.extensions))
@@ -339,7 +339,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(DevTools(bot))
+8 -8
View File
@@ -27,7 +27,7 @@ class Errors(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
self.bot.logger.info(
@@ -45,8 +45,8 @@ class Errors(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
command (app_commands.Command | app_commands.ContextMenu): Command object
interaction (discord.Interaction): The slash command interaction
command (app_commands.Command | app_commands.ContextMenu): The command that was run
"""
self.bot.logger.info(
@@ -62,8 +62,8 @@ class Errors(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
error (commands.CommandError): Eror context object
ctx (commands.Context): The command context
error (commands.CommandError): The error the command raised
"""
# Let the user retry a command that failed without waiting for its cooldown.
@@ -126,8 +126,8 @@ class Errors(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
error (app_commands.AppCommandError): Eror context object
interaction (discord.Interaction): The slash command interaction
error (app_commands.AppCommandError): The error the command raised
"""
if not interaction.response.is_done():
@@ -187,7 +187,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Errors(bot))
+16 -16
View File
@@ -13,7 +13,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("<https://imgur.com/a/uGopaSq>")
@@ -26,7 +26,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://i.imgur.com/ypyK1mi.jpg")
@@ -39,7 +39,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://i.imgur.com/ZqgZEEA.jpg")
@@ -52,7 +52,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://i.imgur.com/Gx9DQE5.jpg")
@@ -65,7 +65,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://i.imgur.com/188MoIV.jpg")
@@ -78,7 +78,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://twitter.com/NTNU/status/970667413564993536")
@@ -91,7 +91,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://i.imgur.com/h84fknj.jpg")
@@ -100,11 +100,11 @@ class Fun(commands.Cog):
@commands.command()
async def erna(self, ctx: commands.Context):
"""
erna, vil ikke
Reply with Erna Solberg's "vil ikke" tweet
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://twitter.com/erna_solberg/status/1075333228779765760")
@@ -117,7 +117,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://twitter.com/vikingfotball/status/919622148599230465")
@@ -130,7 +130,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("A snake eating its own tail indicates that its excrement provides food for it")
@@ -143,7 +143,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply("https://youtube.com/playlist?list=PLFV_L_I9qjsoVvh0KT5kHC2_VB8ZGtQoG&si=CpioMM0k3-XTrHCL")
@@ -156,7 +156,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply(
@@ -171,7 +171,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
await ctx.reply(
@@ -186,7 +186,7 @@ class Fun(commands.Cog):
Parameters
----------
ctx (commands.Context): Context object
ctx (commands.Context): The command context
"""
f = discord.File("./src/assets/edb.png")
@@ -199,7 +199,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Fun(bot))
+13 -9
View File
@@ -12,6 +12,8 @@ from cogs.utils import embed_templates
@dataclass
class FunReply:
"""A reply the bot sends when a message matches its pattern"""
name: str
pattern: str
reply: str
@@ -20,6 +22,8 @@ class FunReply:
@dataclass
class FunReplySettings:
"""Settings changed with /autosvar. None means the reply's default is used"""
enabled: bool = True
cooldown: int | None = None
chance: int | None = None
@@ -161,7 +165,7 @@ class FunReplies(commands.Cog):
Parameters
----------
message (discord.Message): Message object to check for triggers to
message (discord.Message): The message to check for triggers
"""
if message.author.bot:
@@ -177,12 +181,12 @@ class FunReplies(commands.Cog):
Parameters
----------
message (discord.Message): The message object to check for triggers
message (discord.Message): The message to check for triggers
fun_reply (FunReply): The fun reply to check
Returns
----------
bool: Whether or not the reply was triggered
(bool): Whether or not the reply was triggered
"""
settings = self.get_settings(fun_reply.name)
@@ -220,7 +224,7 @@ class FunReplies(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
name (str): The name of the fun reply
"""
@@ -240,7 +244,7 @@ class FunReplies(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
name (str): The name of the fun reply
"""
@@ -264,7 +268,7 @@ class FunReplies(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
name (str): The name of the fun reply
seconds (int | None): The cooldown in seconds. None resets it to the default
"""
@@ -290,7 +294,7 @@ class FunReplies(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
name (str): The name of the fun reply
percent (int | None): The chance in percent. None resets it to the default
"""
@@ -309,7 +313,7 @@ class FunReplies(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
lines = []
@@ -328,7 +332,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(FunReplies(bot))
+4 -2
View File
@@ -65,7 +65,9 @@ class Galtinn(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
galtinn_username (str | None): The Galtinn username to look up
discord_user (discord.User | None): The Discord user to look up. Defaults to the invoking user
"""
if discord_user and galtinn_username:
@@ -147,7 +149,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Galtinn(bot))
+5 -5
View File
@@ -59,7 +59,7 @@ class Gullkorn(commands.Cog):
Returns
----------
str: The input data formatted into a prettified string
(str): The input data formatted into a prettified string
"""
formatted_string = ""
@@ -79,7 +79,7 @@ class Gullkorn(commands.Cog):
Parameters
----------
message (discord.Message): Message object to check for triggers to
message (discord.Message): The message that was sent
"""
if message.author.bot or message.channel.id != self.bot.channel_ids.get("gullkorn") or not message.mentions:
@@ -121,8 +121,8 @@ class Gullkorn(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
user (discord.Member, optional): Discord user to fetch stats for. Defaults to None.
interaction (discord.Interaction): The slash command interaction
user (discord.Member | None): The user to fetch stats for. Defaults to the invoking user
"""
# This looks kinda ugly, ngl
@@ -186,7 +186,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Gullkorn(bot))
+27 -27
View File
@@ -31,7 +31,7 @@ class Info(commands.Cog):
roles (list[discord.Role]): List of roles
Returns
-------
----------
(str): String of roles
"""
@@ -49,11 +49,11 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The interaction that triggered this
join_method (callable): Function to join the boosters with
Returns
-------
----------
(str): String of boosters
"""
@@ -77,7 +77,7 @@ class Info(commands.Cog):
members (list[discord.Member]): List of members
Returns
-------
----------
(str): String of members
"""
@@ -97,7 +97,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
# Days since guild was created
@@ -253,7 +253,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
roles = self.construct_role_string(interaction.guild.roles)
@@ -276,7 +276,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
if len(interaction.guild.premium_subscribers) == 0:
@@ -301,7 +301,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
embed = discord.Embed(color=interaction.guild.me.color, description=f"[Lenke]({interaction.guild.icon})")
@@ -318,7 +318,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
if not interaction.guild.splash:
@@ -339,7 +339,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
if not interaction.guild.banner:
@@ -362,7 +362,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
role (discord.Role): Role to fetch information about
"""
@@ -408,7 +408,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
channel (discord.TextChannel): Text channel to fetch information about
"""
@@ -442,7 +442,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
channel (discord.VoiceChannel): Voice channel to fetch information about
"""
@@ -467,7 +467,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
roles = sorted(
@@ -494,7 +494,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
emoji (discord.Emoji): Emoji to fetch information about
"""
@@ -534,7 +534,7 @@ class Info(commands.Cog):
Parameters
----------
ctx (commands.Context): Command context object
ctx (commands.Context): The command context
"""
if ctx.message.type != discord.MessageType.reply:
@@ -584,7 +584,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
# Sort members by creation date
@@ -616,7 +616,7 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
# Sort members by creation date
@@ -647,8 +647,8 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
user (discord.Member, optional): User to get information about. Defaults to None (invoker).
interaction (discord.Interaction): The slash command interaction
user (discord.Member | None): The user to get information about. Defaults to the invoking user
"""
if not user:
@@ -743,8 +743,8 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
user (discord.Member, optional): User to get roles of. Defaults to None (invoker).
interaction (discord.Interaction): The slash command interaction
user (discord.Member | None): The user to get the roles of. Defaults to the invoking user
"""
if not user:
@@ -774,8 +774,8 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
user (discord.Member, optional): User to get roles of. Defaults to None (invoker).
interaction (discord.Interaction): The slash command interaction
user (discord.Member | None): The user to get the missing roles of. Defaults to the invoking user
"""
if not user:
@@ -807,8 +807,8 @@ class Info(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
user (discord.User, optional): User to get avatar of. Defaults to None (invoker).
interaction (discord.Interaction): The slash command interaction
user (discord.User | None): The user to get the avatar of. Defaults to the invoking user
"""
if not user:
@@ -826,7 +826,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Info(bot))
+3 -3
View File
@@ -52,7 +52,7 @@ class MCWhitelist(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
minecraft_username (str): Minecraft username
"""
@@ -129,7 +129,7 @@ class MCWhitelist(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
# Check if the discord user is in the db
@@ -190,7 +190,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(MCWhitelist(bot))
+7 -7
View File
@@ -52,7 +52,7 @@ class Meme(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction
interaction (discord.Interaction): The slash command interaction
attachment (discord.Attachment): The image to deepfry
"""
@@ -115,7 +115,7 @@ class Meme(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction
interaction (discord.Interaction): The slash command interaction
bad_text (str): The upper text, what's disliked
good_text (str): The lower text, what's liked
"""
@@ -169,7 +169,7 @@ class Meme(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
attachment (discord.Attachment): The image to point at. Only supports png and jpg for now
"""
@@ -286,9 +286,9 @@ class Meme(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction
query (str|None): Search term to look up the media on YouTube
url (str|None): Link to the source media. Used instead of the search term if both are given
interaction (discord.Interaction): The slash command interaction
query (str | None): Search term to look up the media on YouTube
url (str | None): Link to the source media. Used instead of the search term if both are given
"""
if not url and not query:
@@ -357,7 +357,7 @@ class Meme(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction
interaction (discord.Interaction): The slash command interaction
top_text (str): The upper text
bottom_text (str): The lower text
"""
+20 -20
View File
@@ -58,7 +58,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
await interaction.response.send_message("<:sven:762725919604473866> Weebs 👉 <#803596668129509417>")
@@ -74,7 +74,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
text (str): Text to translate
"""
@@ -114,8 +114,8 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
user (discord.Member | discord.User | None): The user you want to see the dicksize of. Defaults to author
interaction (discord.Interaction): The slash command interaction
user (discord.Member | discord.User | None): The user to measure. Defaults to the invoking user
"""
if not user:
@@ -149,7 +149,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
course_code (str): UiO course code
"""
@@ -175,24 +175,24 @@ class Misc(commands.Cog):
@app_commands.command(name="klappifiser", description="Klappifiser tekst")
@app_commands.rename(text="tekst")
@app_commands.describe(text="Teksten som skal klappifiseres")
async def clapify(self, interation: discord.Interaction, text: str):
async def clapify(self, interaction: discord.Interaction, text: str):
"""
Add clap emoji between every word of a string
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
text (str): Text to clapify
"""
if len(text) >= 1000:
embed = embed_templates.error_warning("Teksten er for lang")
return await interation.response.send_message(embed=embed)
return await interaction.response.send_message(embed=embed)
text = text.replace(" ", "👏")
embed = discord.Embed(color=interation.client.user.color, description=f"**{text.upper()}**")
await interation.response.send_message(embed=embed)
embed = discord.Embed(color=interaction.client.user.color, description=f"**{text.upper()}**")
await interaction.response.send_message(embed=embed)
@app_commands.checks.bot_has_permissions(embed_links=True)
@app_commands.checks.cooldown(1, 2)
@@ -210,7 +210,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
text (str): Text to mock
user (discord.User | None): User to mention in the reply
"""
@@ -241,7 +241,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
country_code (str): Country code
year (int): Year
"""
@@ -287,7 +287,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
user (discord.Member): User to match with
"""
@@ -367,7 +367,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
links = [
@@ -390,7 +390,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
random_result = random.randint(1, 100) # We use 1 and not 0 to avoid a tie
@@ -411,7 +411,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
text (str): Human-readable time string
"""
@@ -439,7 +439,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
copypasta = (
@@ -461,7 +461,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
excuses = [
@@ -489,7 +489,7 @@ class Misc(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
bushisms = [
@@ -609,7 +609,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Misc(bot))
+11 -1
View File
@@ -11,6 +11,12 @@ class RepeatedMessages(commands.Cog):
"""Send messages at specific points of time"""
def __init__(self, bot: commands.Bot):
"""
Parameters
----------
bot (commands.Bot): The bot instance
"""
self.bot = bot
# self.fredag.start()
@@ -20,6 +26,10 @@ class RepeatedMessages(commands.Cog):
def cog_unload(self):
# self.fredag.cancel()
# self.mandag.cancel()
"""
Stop the repeated messages when the cog is unloaded
"""
self.new_year.cancel()
def get_general_channel(self) -> discord.TextChannel | None:
@@ -104,7 +114,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(RepeatedMessages(bot))
+41 -14
View File
@@ -28,12 +28,22 @@ from cogs.utils import misc_utils
@dataclass
class CreditUser:
"""A user's row in the social credit table"""
user_id: int
credit_score: int
class SocialCredit(commands.Cog):
"""Give and take social credit for things users do"""
def __init__(self, bot: commands.Bot):
"""
Parameters
----------
bot (commands.Bot): The bot instance
"""
self.bot = bot
self.fuck_uwu.start()
self.voice_activity.start()
@@ -67,8 +77,12 @@ class SocialCredit(commands.Cog):
def add_new_citizen(func):
"""
Decorator that, when used, make sure that a user is inserted
into the database before executing the function
Decorator that makes sure the user is in the database before running the function.
The user's ID has to be the function's first argument
Parameters
----------
func (callable): The function to wrap
"""
async def wrapper(*args, **kwargs):
@@ -80,7 +94,11 @@ class SocialCredit(commands.Cog):
def roll(percent: int = 50):
"""
Decorator that executes the function with a given percent chance
Decorator that only runs the function with a given chance
Parameters
----------
percent (int): The chance of running the function, in percent
"""
def decorator(func):
@@ -175,6 +193,10 @@ class SocialCredit(commands.Cog):
await self.bot.wait_until_ready()
async def cog_unload(self):
"""
Stop the daily and voice loops when the cog is unloaded
"""
self.bot.logger.info("Unloading cog")
self.fuck_uwu.cancel()
self.voice_activity.cancel()
@@ -236,7 +258,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
user (discord.Member | None): The user to check the score of. Defaults to the user who invoked the command
"""
@@ -270,7 +292,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
"""
await interaction.response.defer()
@@ -300,7 +322,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
message (discord.Message): The message object
message (discord.Message): The message to check
"""
if message.author.bot:
@@ -320,7 +342,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
message (discord.Message): The message object
message (discord.Message): The message to check
"""
if message.channel.id == self.bot.channel_ids.get("politics"):
@@ -333,7 +355,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
message (discord.Message): The message object
message (discord.Message): The message to check
"""
if message.channel.id == self.bot.channel_ids.get("member_chat"):
@@ -346,7 +368,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
message (discord.Message): The message object
message (discord.Message): The message to check
"""
illegal_hours = [5, 6, 7, 8, 9]
@@ -361,7 +383,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
message (discord.Message): The message object
message (discord.Message): The message to check
"""
happy_hours = [1, 2, 3, 4]
@@ -375,7 +397,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
message (discord.Message): The message object
message (discord.Message): The message to check
"""
slurs = [
@@ -412,7 +434,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
message (discord.Message): The message object
message (discord.Message): The message to check
"""
# This only works in the UiO Gaming server as well
@@ -427,7 +449,7 @@ class SocialCredit(commands.Cog):
Parameters
----------
reaction (discord.Reaction): The reaction object
reaction (discord.Reaction): The reaction that was added
user (discord.User | discord.Member): The user who reacted
"""
@@ -449,6 +471,11 @@ class SocialCredit(commands.Cog):
async def on_star_remove(self, reaction: discord.Reaction, user: discord.User | discord.Member):
"""
Deducts points from users who have a star reaction removed from their message
Parameters
----------
reaction (discord.Reaction): The reaction that was removed
user (discord.User | discord.Member): The user who removed it
"""
if user.bot or reaction.emoji != "⭐" or reaction.message.author == user:
@@ -467,7 +494,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(SocialCredit(bot))
+9 -5
View File
@@ -76,8 +76,8 @@ class StarboardScraper(commands.Cog):
Get the ID of the last scraped message
Returns
-------
int or None: Last scraped message ID or None if never scraped
----------
(int | None): Last scraped message ID or None if never scraped
"""
result = await self.bot.db.fetchone("""
SELECT last_scraped_message_id
@@ -114,8 +114,8 @@ class StarboardScraper(commands.Cog):
message (discord.Message): The starboard message to parse
Returns
-------
tuple(int, int) | None: (original_message_id, original_channel_id) or None if parsing failed
----------
(tuple[int, int] | None): The original message ID and channel ID. None if parsing failed
"""
if not message.embeds:
@@ -217,6 +217,10 @@ class StarboardScraper(commands.Cog):
await self.scrape_starboard_channel()
async def cog_unload(self):
"""
Stop the starboard check when the cog is unloaded
"""
self.bot.logger.info("Unloading cog")
self.star_check.cancel()
@@ -227,7 +231,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(StarboardScraper(bot))
+7 -3
View File
@@ -65,6 +65,10 @@ class Streak(commands.Cog):
""")
async def cog_unload(self):
"""
Stop the loops and save the cached streaks when the cog is unloaded
"""
self.bot.logger.info("Unloading cog")
self.insert_cache_loop.cancel()
self.streak_check.cancel()
@@ -233,7 +237,7 @@ class Streak(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction
interaction (discord.Interaction): The slash command interaction
user (discord.Member | discord.User | None): The user to get the streak for
"""
@@ -287,7 +291,7 @@ class Streak(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction
interaction (discord.Interaction): The slash command interaction
"""
await interaction.response.defer()
@@ -318,7 +322,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Streak(bot))
+16 -2
View File
@@ -19,9 +19,17 @@ class TempVoice(commands.Cog):
self.temp_voice_helper = TempVoiceHelper(bot)
async def cog_load(self):
"""
Set up the temporary voice channel helper before the cog is used
"""
await self.temp_voice_helper.start()
async def cog_unload(self):
"""
Stop checking for inactive temporary voice channels when the cog is unloaded
"""
self.temp_voice_helper.check_temp_vc_channels.cancel()
@commands.Cog.listener()
@@ -30,6 +38,12 @@ class TempVoice(commands.Cog):
):
"""
Listen for disconnects from the temporary voice channels
Parameters
----------
member (discord.Member): The member whose voice state changed
before (discord.VoiceState): The voice state before the change
after (discord.VoiceState): The voice state after the change
"""
await self.temp_voice_helper.on_voice_state_update(member, before, after)
@@ -50,7 +64,7 @@ class TempVoice(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
name (str): The name of the channel
limit (int): The user limit of the channel. 0 means no limit
"""
@@ -72,7 +86,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(TempVoice(bot))
+81 -7
View File
@@ -44,7 +44,7 @@ class TenMan(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
await open_lobby(interaction, self.active_lobbies, TenManView, "10 Man Lobby", timedelta(minutes=30))
@@ -61,7 +61,7 @@ class TenManView(LobbyView):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The interaction that triggered this
button (discord.ui.Button): The button that was pressed
"""
@@ -96,10 +96,22 @@ class TeamDraft:
@property
def leaders(self) -> list[discord.Member]:
"""
Returns
----------
(list[discord.Member]): The two team leaders
"""
return [team[0] for team in self.teams]
@property
def done(self) -> bool:
"""
Returns
----------
(bool): Whether every player has been picked
"""
return not self.remaining
def pick(self, player_id: int):
@@ -161,7 +173,7 @@ class StageView(discord.ui.View):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The interaction that triggered this
reason (str): Why the user was denied
Returns
@@ -174,6 +186,10 @@ class StageView(discord.ui.View):
return False
async def on_timeout(self):
"""
Disable the step's menus and buttons after SELECTION_TIMEOUT seconds without interaction
"""
for item in self.children:
item.disabled = True
@@ -183,6 +199,16 @@ class StageView(discord.ui.View):
pass # The message has been deleted
async def on_error(self, interaction: discord.Interaction, error: Exception, item: discord.ui.Item):
"""
Log the error and tell the user something went wrong
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
error (Exception): The error that was raised
item (discord.ui.Item): The menu or button that was used
"""
self.bot.logger.error(f"{type(self).__name__} error", exc_info=error)
embed = embed_templates.error_fatal("Oopsie woopsie, we made a fucky wucky!")
@@ -196,10 +222,30 @@ class TeamLeaderView(StageView):
"""The host picks two team leaders"""
def __init__(self, lobby: Lobby, bot: commands.Bot, message: discord.PartialMessage):
"""
Parameters
----------
lobby (Lobby): The closed lobby
bot (commands.Bot): The bot instance
message (discord.PartialMessage): The lobby message
"""
super().__init__(lobby, bot, message)
self.add_item(TeamLeaderSelect(lobby.players))
async def interaction_check(self, interaction: discord.Interaction) -> bool:
"""
Only let the host pick team leaders
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
Returns
----------
(bool): Whether the user may use the menu
"""
if interaction.user != self.lobby.host:
return await self.deny(interaction, "Bare hosten kan velge lagledere")
return True
@@ -222,6 +268,8 @@ class TeamLeaderView(StageView):
class TeamLeaderSelect(discord.ui.Select):
"""Menu for picking the two team leaders"""
def __init__(self, players: list[discord.Member]):
"""
Parameters
@@ -241,7 +289,7 @@ class TeamLeaderSelect(discord.ui.Select):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The interaction that triggered this
"""
view: TeamLeaderView = self.view
@@ -269,6 +317,18 @@ class DraftView(StageView):
self.add_item(PlayerSelect(draft.remaining))
async def interaction_check(self, interaction: discord.Interaction) -> bool:
"""
Only let the team leader whose turn it is pick
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
Returns
----------
(bool): Whether the user may use the menu
"""
if interaction.user not in self.draft.leaders:
return await self.deny(interaction, "Bare lagledere kan velge spillere")
if interaction.user != self.draft.leaders[self.draft.turn]:
@@ -277,6 +337,8 @@ class DraftView(StageView):
class PlayerSelect(discord.ui.Select):
"""Menu for picking the next player for a team"""
def __init__(self, players: list[discord.Member]):
"""
Parameters
@@ -296,7 +358,7 @@ class PlayerSelect(discord.ui.Select):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The interaction that triggered this
"""
view: DraftView = self.view
@@ -323,6 +385,18 @@ class VoiceView(StageView):
self.moved_teams: set[int] = set()
async def interaction_check(self, interaction: discord.Interaction) -> bool:
"""
Only let team leaders move their team
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
Returns
----------
(bool): Whether the user may use the button
"""
if interaction.user not in (self.teams[0][0], self.teams[1][0]):
return await self.deny(interaction, "Bare lagleder kan flytte laget!")
return True
@@ -334,7 +408,7 @@ class VoiceView(StageView):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The interaction that triggered this
button (discord.ui.Button): The button that was pressed
"""
@@ -373,7 +447,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(TenMan(bot))
+39 -10
View File
@@ -13,7 +13,15 @@ from cogs.utils import misc_utils
class UserFacts(commands.Cog):
"""Let users share facts about themselves, like their height and MBTI"""
def __init__(self, bot):
"""
Parameters
----------
bot (commands.Bot): The bot instance
"""
self.bot = bot
self.mbti_codes = {
@@ -70,7 +78,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
user (discord.Member): The user to see the height of
"""
@@ -114,7 +122,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
height_cm (int): The height of the user
"""
@@ -139,7 +147,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
"""
updated = await self.bot.db.execute(
@@ -167,7 +175,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
"""
result = await self.bot.db.fetchall("""
@@ -202,7 +210,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
user (discord.Member): The user to see the MBTI of
"""
@@ -267,7 +275,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
mbti (str): The MBTI of the user
"""
@@ -293,7 +301,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The interaction that triggered this
current (str): The current input
"""
@@ -310,7 +318,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
"""
updated = await self.bot.db.execute(
@@ -338,7 +346,7 @@ class UserFacts(commands.Cog):
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The slash command interaction
"""
embed = discord.Embed(title="Hva er MBTI?", color=discord.Color.blurple())
@@ -352,6 +360,14 @@ class UserFacts(commands.Cog):
await interaction.response.send_message(embed=embed)
def create_similarity_matrix(self):
"""
Count how many letters every pair of MBTI types has in common
Returns
----------
(np.ndarray): The number of shared letters, indexed like mbti_list
"""
def similarity(mbti_1, mbti_2):
similarity = 0
for i in range(4):
@@ -372,6 +388,19 @@ class UserFacts(commands.Cog):
def create_mbti_graph(
self, user_mbti: tuple[discord.Member, str], others: list[tuple[discord.Member, str]]
) -> bytes:
"""
Draw a graph of how similar a user's MBTI is to other users'
Parameters
----------
user_mbti (tuple[discord.Member, str]): The invoking user and their MBTI
others (list[tuple[discord.Member, str]]): Other users and their MBTIs
Returns
----------
(bytes): The graph as PNG data
"""
user, mbti = user_mbti
# Create a Graphviz graph
@@ -403,7 +432,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(UserFacts(bot))
+111 -21
View File
@@ -20,7 +20,7 @@ async def send_as_txt_file(interaction: discord.Interaction, content: str, filen
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The interaction that triggered this
content (str): String that's too long to send
filename (str): Name of the file as shown in Discord
"""
@@ -34,11 +34,11 @@ async def get_file_bytesio(file: discord.Attachment | discord.Asset) -> BytesIO:
Returns a BytesIO object of the file
Parameters
-----------
file (discord.Attatchment | discord.Asset): The file to get the BytesIO object of
----------
file (discord.Attachment | discord.Asset): The file to get the BytesIO object of
Returns
-----------
----------
(BytesIO): The file as a BytesIO object
"""
@@ -62,11 +62,13 @@ class ScrollerButton(discord.ui.Button):
):
"""
Parameters
-----------
----------
paginator (Paginator): The paginator object that contains the data to be paginated
button_action (callable): The function that returns the requested page
content_constructor (callable): A function that takes a paginator object and a page number and returns an embed
owner (discord.User|discord.Member): The user that invoked the paginator. Only this user can use the button
owner (discord.User | discord.Member): The user that invoked the paginator. Only this user can use the button
label (str): The text on the button
disabled (bool): Whether the button starts out disabled
"""
super().__init__(label=label, disabled=disabled)
@@ -80,8 +82,8 @@ class ScrollerButton(discord.ui.Button):
What to do when the button is pressed
Parameters
-----------
interaction (discord.Interaction): Slash command context object
----------
interaction (discord.Interaction): The interaction that triggered this
"""
if interaction.user.id != self.owner.id:
@@ -101,18 +103,18 @@ class Scroller(discord.ui.View):
"""View that allows scrolling through pages of data using the pagination module"""
def __init__(
self, paginatior: Paginator, owner: discord.User | discord.Member, content_constructor: callable = None
self, paginator: Paginator, owner: discord.User | discord.Member, content_constructor: callable = None
):
"""
Parameters
-----------
----------
paginator (Paginator): The paginator object that contains the data to be paginated
owner (discord.User|discord.Member): The user that invoked the paginator. Only this user can use the buttons
owner (discord.User | discord.Member): The user that invoked the paginator. Only this user can use the buttons
content_constructor (callable): A function that takes a paginator object and a page number and returns an embed
"""
super().__init__()
self.paginator = paginatior
self.paginator = paginator
self.content_constructor = content_constructor if content_constructor else self.__default_content_constructor
self.add_item(
@@ -161,7 +163,7 @@ class Scroller(discord.ui.View):
Constructs the embed to be displayed
Parameters
-----------
----------
base_embed (discord.Embed): The base embed to add fields to
"""
@@ -173,9 +175,12 @@ class Scroller(discord.ui.View):
Parameters
----------
paginator (Paginator): Paginator dataclass
page (list): List of streaks to display on a page
embed (discord.Embed): Embed to add fields to
page (list): The items to show on the page
embed (discord.Embed): The embed to add the page to
Returns
----------
(discord.Embed): The embed with the page added
"""
embed.description = "\n".join(page)
@@ -185,6 +190,8 @@ class Scroller(discord.ui.View):
@dataclass
class Lobby:
"""Players gathering before an activity starts. Closed once it starts, is deleted or times out"""
host: discord.User
players: list[discord.User]
ends: datetime
@@ -204,7 +211,7 @@ async def open_lobby(
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The interaction that triggered this
lobbies (dict[int, Lobby]): The cog's lobbies by host ID. The new lobby is added to it
view_class (type[LobbyView]): The view to show the lobby with
title (str): The title of the lobby message
@@ -241,7 +248,16 @@ async def open_lobby(
class LobbyView(discord.ui.View):
"""Lobby players can join, leave and be kicked from. Subclasses decide what starting it does"""
def __init__(self, lobby: Lobby, bot: commands.Bot):
"""
Parameters
----------
lobby (Lobby): The lobby to show
bot (commands.Bot): The bot instance
"""
lobby_end = (lobby.ends - discord.utils.utcnow()).total_seconds()
super().__init__(timeout=lobby_end)
@@ -253,6 +269,10 @@ class LobbyView(discord.ui.View):
self.add_item(self.kick_menu)
async def on_timeout(self):
"""
Close the lobby and disable its buttons when it times out
"""
await self.end_lobby()
if self.message:
try:
@@ -261,12 +281,24 @@ class LobbyView(discord.ui.View):
pass # The message has been deleted
async def end_lobby(self):
"""
Close the lobby, disable its buttons and stop listening for interactions
"""
self.lobby.closed = True
for item in self.children:
item.disabled = True
self.stop()
async def rerender_players(self, interaction: discord.Interaction):
"""
Update the player list and the kick menu in the lobby message
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
"""
self.kick_menu.update_options()
embed = interaction.message.embeds[0].set_field_at(
0,
@@ -277,6 +309,15 @@ class LobbyView(discord.ui.View):
@discord.ui.button(label="Bli med", style=discord.ButtonStyle.blurple)
async def join_lobby(self, interaction: discord.Interaction, button: discord.ui.Button):
"""
Add the user to the lobby
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
button (discord.ui.Button): The button that was pressed
"""
if self.lobby.closed:
embed = embed_templates.error_warning("Lobbyen har allerede startet")
return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10)
@@ -303,6 +344,15 @@ class LobbyView(discord.ui.View):
@discord.ui.button(label="Start", style=discord.ButtonStyle.green)
async def start_lobby(self, interaction: discord.Interaction, button: discord.ui.Button):
"""
Close the lobby. Subclasses override this to start their activity
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
button (discord.ui.Button): The button that was pressed
"""
if interaction.user != self.lobby.host:
embed = embed_templates.error_warning("Bare hosten kan starte")
return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10)
@@ -319,6 +369,15 @@ class LobbyView(discord.ui.View):
@discord.ui.button(label="Forlat", style=discord.ButtonStyle.gray)
async def leave_lobby(self, interaction: discord.Interaction, button: discord.ui.Button):
"""
Remove the user from the lobby
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
button (discord.ui.Button): The button that was pressed
"""
if interaction.user == self.lobby.host:
embed = embed_templates.error_warning(
"Du kan ikke forlate lobbyen som host. Slett lobbyen i stedet om ønskelig!"
@@ -337,6 +396,15 @@ class LobbyView(discord.ui.View):
@discord.ui.button(label="Slett", style=discord.ButtonStyle.red)
async def delete_lobby(self, interaction: discord.Interaction, button: discord.ui.Button):
"""
Close the lobby and delete its message
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
button (discord.ui.Button): The button that was pressed
"""
if interaction.user != self.lobby.host:
embed = embed_templates.error_warning("Bare hosten kan slette lobbyen")
return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10)
@@ -349,7 +417,15 @@ class LobbyView(discord.ui.View):
class _KickSelectMenu(discord.ui.Select):
"""Menu the host uses to kick players from the lobby"""
def __init__(self, parent_view: LobbyView):
"""
Parameters
----------
parent_view (LobbyView): The lobby view the menu belongs to
"""
self.parent_view = parent_view
super().__init__(placeholder="Kick en spiller", max_values=1, min_values=1)
self.update_options()
@@ -367,6 +443,14 @@ class _KickSelectMenu(discord.ui.Select):
]
async def callback(self, interaction: discord.Interaction):
"""
Kick the selected player from the lobby
Parameters
----------
interaction (discord.Interaction): The interaction that triggered this
"""
if interaction.user != self.parent_view.lobby.host:
embed = embed_templates.error_warning("Bare hosten kan kicke spillere")
return await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=10)
@@ -463,6 +547,12 @@ class TempVoiceHelper:
):
"""
Listen for disconnects from the temporary voice channels
Parameters
----------
member (discord.Member): The member whose voice state changed
before (discord.VoiceState): The voice state before the change
after (discord.VoiceState): The voice state after the change
"""
for channel in (before.channel, after.channel):
@@ -537,13 +627,13 @@ class TempVoiceHelper:
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The interaction that triggered this
name (str): The name of the channel
limit (int): The user limit of the channel
Returns
----------
(discord.VoiceChannel) | None: The object for the newly created channel. None if failed
(discord.VoiceChannel | None): The new channel. None if it couldn't be created
"""
# Get the UiO Gaming server's VC category. If the command is not invoked in that server it should still be fine
@@ -592,13 +682,13 @@ class TempVoiceHelper:
Parameters
----------
interaction (discord.Interaction): The interaction object
interaction (discord.Interaction): The interaction that triggered this
channel (discord.VoiceChannel): The channel the users should be moved to
users (list[discord.User]): A list of users to be moved
Returns
----------
(list[discord.User]) | None: A list of users that failed to be moved. None if all users were moved
(list[discord.User]): The users that couldn't be moved. Empty if everyone was moved
"""
failed_users = []
+7 -7
View File
@@ -6,11 +6,11 @@ def error_warning(text: str) -> discord.Embed:
Creates an embed with a specified error message based on a warning template
Parameters
-----------
----------
text (str): The error message
Returns
-----------
----------
(discord.Embed): An embed object based on the template with the specified text
"""
@@ -23,11 +23,11 @@ def error_fatal(text: str) -> discord.Embed:
Creates an embed with a specified error message based on a warning template
Parameters
-----------
----------
text (str): The error message
Returns
-----------
----------
(discord.Embed): An embed object based on the template with the specified text
"""
@@ -40,12 +40,12 @@ def success(text: str) -> discord.Embed:
Creates an embed with a specified message using a template signifying success.
Parameters
-----------
----------
text (str): The message
Returns
-----------
discord.Embed: An embed object based on the template with the specified text
----------
(discord.Embed): An embed object based on the template with the specified text
"""
embed = discord.Embed(color=discord.Color.green(), description=f"✅ {text}")
+1 -1
View File
@@ -114,7 +114,7 @@ class Paginator:
Returns
----------
(list|None): The page you requested
(list | None): The page you requested
"""
if page < 1 or page > self.total_page_count:
+13 -11
View File
@@ -26,7 +26,7 @@ async def fetch_article(session: aiohttp.ClientSession, title: str):
Returns
----------
tuple: The title, url, text and image of the article
(tuple): The title, url, text and image of the article
"""
# The wiki renders the article to HTML for us, so templates are already expanded
@@ -78,7 +78,7 @@ async def fetch_page_image(session: aiohttp.ClientSession, title: str) -> str |
Returns
----------
str | None: The url of the image. None if the article has no image or it couldn't be fetched
(str | None): The url of the image. None if the article has no image or it couldn't be fetched
"""
params = {
@@ -110,7 +110,7 @@ def shorten(text: str, limit: int) -> str:
Returns
----------
str: The shortened text
(str): The shortened text
"""
if len(text) <= limit:
@@ -146,7 +146,7 @@ def viteboka_embed(title: str, url: str, text: str, image: str):
Returns
----------
discord.Embed: The embed
(discord.Embed): The embed
"""
embed = discord.Embed(color=discord.Color.orange(), title=title, url=url, description=text)
@@ -157,6 +157,8 @@ def viteboka_embed(title: str, url: str, text: str, image: str):
class VitebokaException(Exception):
"""Raised when an article can't be fetched. The message is shown to the user"""
pass
@@ -185,7 +187,7 @@ class Viteboka(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
query (str): The search query
"""
@@ -243,7 +245,7 @@ class Viteboka(commands.Cog):
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
await interaction.response.defer()
@@ -286,8 +288,8 @@ class ArticleButton(discord.ui.Button):
):
"""
Parameters
-----------
owner (discord.User|discord.Member): The user that invoked the paginator. Only this user can use the button
----------
owner (discord.User | discord.Member): The user that invoked the paginator. Only this user can use the button
label (str): The label of the button
article_title (str): The title of the article the button is associated with
"""
@@ -301,8 +303,8 @@ class ArticleButton(discord.ui.Button):
What to do when the button is pressed
Parameters
-----------
interaction (discord.Interaction): Slash command context object
----------
interaction (discord.Interaction): The interaction that triggered this
"""
await interaction.response.defer()
@@ -328,7 +330,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(Viteboka(bot))
+5 -1
View File
@@ -26,6 +26,10 @@ class WebsiteEvents(commands.Cog):
)
async def cog_load(self):
"""
Start syncing events once the bot is ready
"""
asyncio.create_task(self.after_ready())
async def after_ready(self):
@@ -153,7 +157,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(WebsiteEvents(bot))
+19 -19
View File
@@ -166,7 +166,7 @@ class WordCloud(commands.Cog):
Returns
----------
bool: Whether the message can be counted
(bool): Whether the message can be counted
"""
return (
@@ -184,7 +184,7 @@ class WordCloud(commands.Cog):
Returns
----------
list[str]: List of words
(list[str]): List of words
"""
tokens = []
@@ -215,7 +215,7 @@ class WordCloud(commands.Cog):
"""
Returns
----------
set[str]: Norwegian and english words too common to include in a wordcloud
(set[str]): Norwegian and english words too common to include in a wordcloud
"""
return set(stopwords.words("norwegian") + stopwords.words("english"))
@@ -233,7 +233,7 @@ class WordCloud(commands.Cog):
Returns
----------
BytesIO: BytesIO object containing the wordcloud image
(BytesIO): BytesIO object containing the wordcloud image
"""
mask = np.array(Image.open("./src/assets/word_cloud_mask.png"))
@@ -265,7 +265,7 @@ class WordCloud(commands.Cog):
Returns
----------
BytesIO: BytesIO object containing the wordcloud image
(BytesIO): BytesIO object containing the wordcloud image
"""
return WordCloud.render_wordcloud(max_words, allow_bigrams, lambda wc: wc.generate(text))
@@ -282,7 +282,7 @@ class WordCloud(commands.Cog):
Returns
----------
BytesIO: BytesIO object containing the wordcloud image
(BytesIO): BytesIO object containing the wordcloud image
"""
filter_words = WordCloud.filter_words()
@@ -305,11 +305,11 @@ class WordCloud(commands.Cog):
@wordcloud_group.command(name="samtykke", description="Gi samtykke til å samle meldingsdataen din for ordskyer")
async def consent(self, interaction: discord.Interaction):
"""
Gi samtykke til å samle meldingsdataen din
Consent to having your messages counted for word clouds
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
if interaction.user.id in self.consenting_users:
@@ -342,11 +342,11 @@ class WordCloud(commands.Cog):
@wordcloud_group.command(name="slett", description="Fjern samtykke og slett alle dine ordskydata")
async def consent_remove(self, interaction: discord.Interaction):
"""
Fjern samtykke og slett meldingsdata
Withdraw consent and delete your word cloud data
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
if interaction.user.id not in self.consenting_users:
@@ -380,11 +380,11 @@ class WordCloud(commands.Cog):
@wordcloud_group.command(name="data", description="Få tilsendt dine ordskydata i JSON-format")
async def data(self, interaction: discord.Interaction):
"""
Få tilsendt dine data
Send the user their word cloud data as a JSON file
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
result = await self.bot.db.fetchall(
@@ -420,11 +420,11 @@ class WordCloud(commands.Cog):
)
async def generate_db(self, interaction: discord.Interaction):
"""
Generer en ordsky basert på dine mest frekvente sagte ord siden du ga samtykke
Generate a word cloud from the user's most used words since they consented
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
"""
await interaction.response.defer()
@@ -480,7 +480,7 @@ class WordCloud(commands.Cog):
Returns
----------
list[discord.TextChannel]: Channels the user can write in, the bot can read and that aren't private
(list[discord.TextChannel]): Channels the user can write in, the bot can read and that aren't private
"""
# The word cloud is posted publicly, so skip private channels like board chats.
@@ -513,7 +513,7 @@ class WordCloud(commands.Cog):
Returns
----------
list[str]: The tokens of the user's messages
(list[str]): The tokens of the user's messages
"""
tokens = []
@@ -547,11 +547,11 @@ class WordCloud(commands.Cog):
@app_commands.describe(amount="Hvor mange av de siste meldingene i hver kanal som skal leses. Flere tar lengre tid")
async def generate_last(self, interaction: discord.Interaction, amount: app_commands.Range[int, 50, 2000] = 1000):
"""
Generer en ordsky basert på dine mest frekvente sagte ord fra de siste meldingene dine
Generate a word cloud from the user's most used words in the most recent messages of each channel
Parameters
----------
interaction (discord.Interaction): Slash command context object
interaction (discord.Interaction): The slash command interaction
amount (int): How many of the most recent messages in each channel to read
"""
@@ -587,7 +587,7 @@ async def setup(bot: commands.Bot):
Parameters
----------
bot (commands.Bot): Bot instance
bot (commands.Bot): The bot instance
"""
await bot.add_cog(WordCloud(bot))
+4
View File
@@ -9,6 +9,10 @@ class BotLogger:
"""Logging config for the bot"""
def __init__(self):
"""
Log to the console and to a new file in logs/ for every run
"""
logger = logging.getLogger("discord")
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
+22 -2
View File
@@ -43,6 +43,10 @@ class Bot(commands.Bot):
"""UiO Gaming Bot"""
def __init__(self):
"""
Read the config and disable the cogs whose credentials are missing
"""
super().__init__(
command_prefix=commands.when_mentioned_or(config["bot"]["prefix"]),
case_insensitive=True,
@@ -103,6 +107,10 @@ class Bot(commands.Bot):
misc_utils.MIDNIGHT = datetime.time(tzinfo=midnight_tz)
async def setup_hook(self):
"""
Open the HTTP session and database pool, load the cogs and sync the slash commands
"""
self.http_session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=15))
if self.db_pool:
await self.db_pool.open(wait=True, timeout=30)
@@ -127,6 +135,10 @@ class Bot(commands.Bot):
await self.tree.sync(guild=discord.Object(id=self.guild_id))
async def close(self):
"""
Close the HTTP session and database pool when the bot shuts down
"""
await super().close()
if hasattr(self, "http_session"):
await self.http_session.close()
@@ -136,6 +148,10 @@ class Bot(commands.Bot):
async def configure_db_connection(self, conn):
"""
Sets the session time zone of every new database connection to the bot's time zone
Parameters
----------
conn (psycopg.AsyncConnection): The new database connection
"""
if self.timezone_name:
@@ -165,13 +181,13 @@ class Bot(commands.Bot):
Check if the credentials are valid. Removes cogs from the class' `cog_files` attribute if not
Parameters
-----------
----------
credentials (dict): The credentials to check
dependant_cogs (set): The cogs that depend on the credentials
Returns
----------
bool: Whether the credentials are valid. If not, the dependant cogs are disabled.
(bool): Whether the credentials are valid. If not, the dependant cogs are disabled.
"""
for credential in credentials.values():
@@ -188,6 +204,10 @@ bot = Bot()
@bot.event
async def on_ready():
"""
Print the bot's info and set its presence once it's connected
"""
if not hasattr(bot, "uptime"):
bot.uptime = time()