Skip to content

Commit

Permalink
Fix lint/typing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
raccube committed Aug 16, 2024
1 parent 8904536 commit 61dd76c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 48 deletions.
9 changes: 8 additions & 1 deletion src/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@
PASSWORDS_CHANNEL_NAME,
)
from src.commands.join import join
from src.commands.team import Team, new_team, delete_team, create_voice, create_team_channel, export_team
from src.commands.team import (
Team,
new_team,
delete_team,
export_team,
create_voice,
create_team_channel,
)


class BotClient(discord.Client):
Expand Down
2 changes: 1 addition & 1 deletion src/commands/join.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
REASON = "A correct password was entered."


@discord.app_commands.command(
@discord.app_commands.command( # type:ignore[arg-type]
name='join',
description='Join a team using a password',
)
Expand Down
114 changes: 70 additions & 44 deletions src/commands/team.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import TYPE_CHECKING, Iterable
from typing import TYPE_CHECKING, Mapping

import discord
from discord import app_commands, role
from discord import app_commands

from src.commands.ui import TeamDeleteConfirm

Expand All @@ -10,9 +10,10 @@

from src.constants import (
ROLE_PREFIX,
TEAM_LEADER_ROLE,
TEAM_CATEGORY_NAME,
PASSWORDS_CHANNEL_NAME,
TEAM_VOICE_CATEGORY_NAME, TEAM_LEADER_ROLE,
TEAM_VOICE_CATEGORY_NAME,
)

TEAM_CREATED_REASON = "Created via command by "
Expand All @@ -27,11 +28,16 @@ class Team(app_commands.Group):
group = Team()


def permissions(client: "BotClient", team: discord.Role) -> dict[discord.Role, discord.PermissionOverwrite]:
def permissions(client: "BotClient", team: discord.Role) -> Mapping[
discord.Role | discord.Member, discord.PermissionOverwrite]:
if not isinstance(client.guild, discord.Guild):
return {}

return {
client.guild.default_role: discord.PermissionOverwrite(
read_messages=False,
send_messages=False),
send_messages=False
),
client.volunteer_role: discord.PermissionOverwrite(
read_messages=True,
send_messages=True,
Expand All @@ -43,7 +49,7 @@ def permissions(client: "BotClient", team: discord.Role) -> dict[discord.Role, d
}


@group.command(
@group.command( # type:ignore[arg-type]
name='new',
description='Creates a role and channel for a team',
)
Expand All @@ -56,8 +62,7 @@ async def new_team(interaction: discord.interactions.Interaction["BotClient"], t
password: str) -> None:
guild: discord.Guild | None = interaction.guild
if guild is None:
await interaction.response.send_message("No guild found", ephemeral=True)
return
raise app_commands.NoPrivateMessage()

category = discord.utils.get(guild.categories, name=TEAM_CATEGORY_NAME)
role_name = f"{ROLE_PREFIX}{tla.upper()}"
Expand Down Expand Up @@ -87,7 +92,7 @@ async def _save_password(guild: discord.Guild, tla: str, password: str) -> None:
await channel.send(f"```\n{tla.upper()}:{password}\n```")


@group.command(
@group.command( # type:ignore[arg-type]
name='delete',
description='Deletes a role and channel for a team',
)
Expand All @@ -96,22 +101,21 @@ async def _save_password(guild: discord.Guild, tla: str, password: str) -> None:
)
async def delete_team(interaction: discord.interactions.Interaction["BotClient"], tla: str) -> None:
guild: discord.Guild | None = interaction.guild
role: discord.Role | None = discord.utils.get(guild.roles, name=f"{ROLE_PREFIX}{tla.upper()}")
if guild is None:
return
raise app_commands.NoPrivateMessage()
role: discord.Role | None = discord.utils.get(guild.roles, name=f"{ROLE_PREFIX}{tla.upper()}")

if role is None:
await interaction.response.send_message(f"Team {tla.upper()} does not exist", ephemeral=True)
return

view = TeamDeleteConfirm(guild, tla)

await interaction.response.send_message(f"Are you sure you want to delete Team {tla.upper()}\n\n"
await interaction.response.send_message(f"Are you sure you want to delete Team {tla.upper()}?\n\n"
f"This will kick all of its members.", view=view, ephemeral=True)
await view.wait()
if view.value:
await interaction.edit_original_response(content=f"_Deleting Team {tla.upper()}..._", view=None)
guild: discord.Guild | None = interaction.guild
reason = f"Team removed by {interaction.user.name}"
if role is not None:
for member in role.members:
Expand All @@ -124,11 +128,13 @@ async def delete_team(interaction: discord.interactions.Interaction["BotClient"]

await role.delete(reason=reason)

if not interaction.channel.name.startswith(f"team-{tla.lower()}"):
if isinstance(interaction.channel, discord.abc.GuildChannel) and not interaction.channel.name.startswith(f"team-{tla.lower()}"):
await interaction.edit_original_response(content=f"Team {tla.upper()} has been deleted")
else:
await interaction.delete_original_response()


@group.command(
@group.command( # type:ignore[arg-type]
name='voice',
description='Create a voice channel for a team',
)
Expand All @@ -137,10 +143,10 @@ async def delete_team(interaction: discord.interactions.Interaction["BotClient"]
)
async def create_voice(interaction: discord.interactions.Interaction["BotClient"], tla: str) -> None:
guild: discord.Guild | None = interaction.guild
role: discord.Role | None = discord.utils.get(guild.roles, name=f"{ROLE_PREFIX}{tla.upper()}")
if guild is None:
return
raise app_commands.NoPrivateMessage()

role: discord.Role | None = discord.utils.get(guild.roles, name=f"{ROLE_PREFIX}{tla.upper()}")
if role is None:
await interaction.response.send_message(f"Team {tla.upper()} does not exist", ephemeral=True)
return
Expand All @@ -154,7 +160,7 @@ async def create_voice(interaction: discord.interactions.Interaction["BotClient"
await interaction.response.send_message(f"{channel.mention} created!", ephemeral=True)


@group.command(
@group.command( # type:ignore[arg-type]
name='channel',
description='Create a secondary channel for a team',
)
Expand All @@ -169,6 +175,11 @@ async def create_team_channel(
) -> None:
guild: discord.Guild | None = interaction.guild
if guild is None:
raise app_commands.NoPrivateMessage()

role: discord.Role | None = discord.utils.get(guild.roles, name=f"{ROLE_PREFIX}{tla.upper()}")
if role is None:
await interaction.response.send_message("Team does not exist", ephemeral=True)
return

main_channel = discord.utils.get(guild.text_channels, name=f"team-{tla.lower()}")
Expand All @@ -181,14 +192,51 @@ async def create_team_channel(
new_channel = await guild.create_text_channel(
name=f"team-{tla.lower()}-{suffix.lower()}",
category=category,
overwrites=main_channel.overwrites,
overwrites=permissions(interaction.client, role),
position=main_channel.position + 1,
reason=TEAM_CREATED_REASON
)
await interaction.response.send_message(f"{new_channel.mention} created!", ephemeral=True)


@group.command(
async def _find_password(
team_tla: str,
interaction: discord.interactions.Interaction["BotClient"],
) -> str:
async for team_name, password in interaction.client.load_passwords():
if team_name == team_tla:
return password
return ""


async def _export_team(
team_tla: str,
only_teams: bool,
guild: discord.Guild,
interaction: discord.interactions.Interaction["BotClient"],
) -> str:
main_channel = discord.utils.get(guild.text_channels, name=f"team-{team_tla.lower()}")
if main_channel is None and not isinstance(main_channel, discord.abc.GuildChannel):
raise app_commands.AppCommandError("Invalid TLA")

password = await _find_password(team_tla, interaction)
commands = [f"/team new tla:{team_tla} name:{main_channel.topic} password:{password}"]

if not only_teams:
channels = filter(lambda c: c.name.startswith(f"team-{team_tla.lower()}-"), guild.text_channels)
for channel in channels:
suffix = channel.name.removeprefix(f"team-{team_tla.lower()}-")
commands.append(f"/team channel tla:{team_tla} suffix:{suffix}")

has_voice: bool = discord.utils.get(guild.voice_channels, name=f"team-{team_tla.lower()}") is not None
if has_voice:
commands.append(f"/team voice tla:{team_tla}")

return "\n".join(commands) + "\n"
return ""


@group.command( # type:ignore[arg-type]
name='export',
description='Outputs all commands needed to create a team (or all teams)',
)
Expand All @@ -207,35 +255,13 @@ async def export_team(

await interaction.response.defer(thinking=True, ephemeral=True)

async def _find_password(team_tla: str) -> str:
async for team_name, password in interaction.client.load_passwords():
if team_name == team_tla:
return password

async def _export_team(team_tla: str) -> str:
main_channel = discord.utils.get(guild.text_channels, name=f"team-{team_tla.lower()}")
password = await _find_password(team_tla)
commands = [f"/team new tla:{team_tla} name:{main_channel.topic} password:{password}"]

if not only_teams:
channels = filter(lambda c: c.name.startswith(f"team-{team_tla.lower()}-"), guild.text_channels)
for channel in channels:
suffix = channel.name.removeprefix(f"team-{team_tla.lower()}-")
commands.append(f"/team channel tla:{team_tla} suffix:{suffix}")

has_voice: bool = discord.utils.get(guild.voice_channels, name=f"team-{team_tla.lower()}") is not None
if has_voice:
commands.append(f"/team voice tla:{team_tla}")

return "\n".join(commands) + "\n"

output = "```\n"

if tla is None:
for team_role in guild.roles:
if team_role.name.startswith(ROLE_PREFIX) and team_role.name != TEAM_LEADER_ROLE:
output = output + await _export_team(team_role.name.removeprefix(ROLE_PREFIX))
output = output + await _export_team(team_role.name.removeprefix(ROLE_PREFIX), only_teams, guild, interaction)
else:
output = output + await _export_team(tla)
output = output + await _export_team(tla, only_teams, guild, interaction)
output = output + "\n```"
await interaction.followup.send(content=output, ephemeral=True)
9 changes: 7 additions & 2 deletions src/commands/ui.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from typing import TYPE_CHECKING

import discord

if TYPE_CHECKING:
from src.bot import BotClient


class TeamDeleteConfirm(discord.ui.View):
def __init__(self, guild: discord.Guild, tla: str):
Expand All @@ -9,11 +14,11 @@ def __init__(self, guild: discord.Guild, tla: str):
self.value: bool = False

@discord.ui.button(label='Delete', style=discord.ButtonStyle.red)
async def confirm(self, interaction: discord.Interaction, item) -> None:
async def confirm(self, interaction: discord.interactions.Interaction["BotClient"], item: discord.ui.Item[discord.ui.View]) -> None:
self.value = True
self.stop()

@discord.ui.button(label='Cancel', style=discord.ButtonStyle.grey)
async def cancel(self, interaction: discord.Interaction, item) -> None:
async def cancel(self, interaction: discord.interactions.Interaction["BotClient"], item: discord.ui.Item[discord.ui.View]) -> None:
await interaction.response.defer(ephemeral=True)
self.stop()

0 comments on commit 61dd76c

Please sign in to comment.