Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate info about teachers in subject rooms #996

Merged
merged 4 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cogs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ def bot_room(self) -> disnake.TextChannel:
def bot_dev_channel(self) -> disnake.TextChannel:
return self.bot.get_channel(self.config.bot_dev_channel)

@cached_property
def teacher_info_channel(self) -> disnake.TextChannel:
return self.bot.get_channel(self.config.teacher_info_channel)

def cog_unload(self) -> None:
for task in self.tasks:
task.cancel()
73 changes: 73 additions & 0 deletions cogs/fitwide/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import json
import subprocess
from datetime import datetime, timezone
from io import BytesIO

import disnake
Expand Down Expand Up @@ -497,3 +498,75 @@ async def fitwide_checks_error(self, inter: disnake.ApplicationCommandInteractio
if isinstance(error, commands.CheckFailure):
await inter.send(MessagesCZ.not_in_modroom)
return True

@cooldowns.default_cooldown
@commands.check(room_check.is_in_modroom)
@commands.slash_command(name="gen_teacher_info", description=MessagesCZ.gen_teacher_info_brief)
async def gen_teacher_info(self, inter: disnake.ApplicationCommandInteraction):
"""Generate teacher info channel"""
await inter.send(MessagesCZ.gen_teacher_info_start)
# Get all semester categories
categories = [
disnake.utils.get(inter.guild.categories, name=semester_name)
for semester_name in features.CATEGORIES_NAMES
]

# Check if all categories were found
invalid_categories = [
semester_name
for semester_name, category in zip(features.CATEGORIES_NAMES, categories)
if category is None
]
if invalid_categories:
# Tell which categories were invalid
await inter.edit_original_response(
MessagesCZ.gen_teacher_info_inv_catg(categories=invalid_categories)
)
return

teacher_roles = await features.get_teacher_roles(inter.guild)

if None in teacher_roles:
await inter.edit_original_response(MessagesCZ.gen_teacher_info_inv_roles)
return

teacher_info_channel = self.teacher_info_channel
if teacher_info_channel is None:
await inter.edit_original_response(MessagesCZ.gen_teacher_info_channel_none)
return

# Clear channel before sending new data
await teacher_info_channel.purge()
await teacher_info_channel.send(MessagesCZ.gen_teacher_info_header)

# Run through all semester channels
for index, category in enumerate(categories):
progress_bar = utils.create_bar(index, len(categories))
await inter.edit_original_message(
content=MessagesCZ.gen_teacher_info_processing(progress_bar=progress_bar)
)
for channel in category.channels:
perms_list = await features.get_teacher_perms_list(channel, teacher_roles)
if perms_list is not None:
await teacher_info_channel.send(
perms_list, allowed_mentions=disnake.AllowedMentions.none()
)

await inter.edit_original_response(MessagesCZ.gen_teacher_info_success)

@commands.Cog.listener()
async def on_guild_channel_update(
self, before: disnake.abc.GuildChannel, after: disnake.abc.GuildChannel
) -> None:
"""Update teacher info channel on permissions change"""
if before.overwrites != after.overwrites and after.category.name in features.CATEGORIES_NAMES:
perms_list_before, perms_list_after = await features.update_teacher_info(
after, self.teacher_info_channel
)
if perms_list_before is None and perms_list_after is None:
return
embed = disnake.Embed(title="Teacher permissions update", color=disnake.Colour.yellow())
missing = "None"
embed.description = f"## Old permissions\n{perms_list_before or missing}\n## New permissions\n{perms_list_after or missing}"
embed.timestamp = datetime.now(tz=timezone.utc)
await self.log_channel.send(embed=embed, allowed_mentions=disnake.AllowedMentions.none())
71 changes: 70 additions & 1 deletion cogs/fitwide/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
from disnake.ext import commands

import utils
from config.app_config import config
from database.verification import ValidPersonDB

CATEGORIES_NAMES = [
"1. semestr", "2. semestr", "3. semestr", "4. semestr", "5. semestr",
"zimni-volitelne", "letni-volitelne", "volitelne",
"zimni magistersky semestr", "letni magistersky semestr",
"zimni magistersky semestr 1", "letni magistersky semestr 1",
"zimni magistersky semestr 2", "letni magistersky semestr 2",
] # fmt: skip


Expand Down Expand Up @@ -70,3 +73,69 @@ async def set_channel_permissions_for_new_students(
for channel in channels:
await channel.set_permissions(bit0, read_messages=True)
await channel.set_permissions(mit0, read_messages=True)


async def get_teacher_roles(guild: disnake.Guild) -> list[disnake.Role]:
return [disnake.utils.get(guild.roles, id=role_id) for role_id in config.teacher_roles]


async def get_teacher_perms_list(
channel: disnake.abc.GuildChannel, teacher_roles: list[disnake.Role]
) -> str | None:
"""Get message with teacher permissions"""
channel_teachers = []
for user, permission in channel.overwrites.items():
if not isinstance(user, disnake.Member): # Only user overwrites
continue

# Check if user is a teacher
if not set(user.roles).intersection(teacher_roles):
continue

# Check if user has permission to read messages
if not permission.read_messages:
continue

channel_teachers.append(user)

perms_list = None

if channel_teachers:
perms_list = f"**{channel.name.upper()}: {channel.mention}**\n"
for teacher in channel_teachers:
perms_list += f"- {teacher.mention}"
user = ValidPersonDB.get_user_by_id(teacher.id)
if user:
perms_list += f" ({user.name})"
perms_list += "\n"

return perms_list


async def update_teacher_info(
channel: disnake.abc.GuildChannel, teacher_info_channel: disnake.TextChannel
) -> tuple[str | None, str | None]:
"""Update teacher info channel"""
teacher_roles = await get_teacher_roles(channel.guild)
perms_list = await get_teacher_perms_list(channel, teacher_roles)

if not perms_list:
return None, None

# Don't ping anyone
no_one = disnake.AllowedMentions.none()

async for message in teacher_info_channel.history():
if message.author == channel.guild.me and channel.name.upper() in message.content:
old_content = message.content
await message.edit(content=perms_list, allowed_mentions=no_one)
return old_content, perms_list
elif channel.name.upper() in message.content:
old_content = message.content
await message.delete()
await teacher_info_channel.send(perms_list, allowed_mentions=no_one)
return old_content, perms_list

# Channel had no listing yet
await teacher_info_channel.send(perms_list, allowed_mentions=no_one)
return None, perms_list
8 changes: 8 additions & 0 deletions cogs/fitwide/messages_cz.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,11 @@ class MessagesCZ(GlobalMessages):
not_in_modroom = "Nothing to see here comrade. <:KKomrade:484470873001164817>"
login_already_exists = "Uživatel již existuje v databázi."
vutapi_brief = "Získá data z VUT API"
gen_teacher_info_brief = "Generuje informace o vyučujících"
gen_teacher_info_start = "Generuji informace o vyučujících..."
gen_teacher_info_header = "# Vyučující mající přístup k předmětovým kanálům"
gen_teacher_info_processing = "Generuji informace o vyučujících: {progress_bar}"
gen_teacher_info_success = "Informace o vyučujících byly úspěšně vygenerovány."
gen_teacher_info_inv_catg = "Některé kategorie mají neplatné názvy. Hodilo by se je opravit: {categories}"
gen_teacher_info_inv_roles = "Nemohu najít role pro vyučující."
gen_teacher_info_channel_none = "Nemohu najít kanál vyucujici-info."
2 changes: 2 additions & 0 deletions config/app_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Config:
mod_role: int = get_attr(toml_dict, "base", "mod_role")
submod_role: int = get_attr(toml_dict, "base", "submod_role")
helper_role: int = get_attr(toml_dict, "base", "helper_role")
teacher_roles: List[int] = get_attr(toml_dict, "base", "teacher_roles")

# Verification
verification_role: str = get_attr(toml_dict, "verification", "role")
Expand Down Expand Up @@ -106,6 +107,7 @@ class Config:
mod_room: int = get_attr(toml_dict, "channels", "mod_room")
submod_helper_room: int = get_attr(toml_dict, "channels", "submod_helper_room")
report_channel: int = get_attr(toml_dict, "channels", "report_channel")
teacher_info_channel: int = get_attr(toml_dict, "channels", "teacher_info_channel")

# Meme repost
meme_room: int = get_attr(toml_dict, "bettermeme", "meme_room")
Expand Down
3 changes: 3 additions & 0 deletions config/config.template.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ guild_id = 0
mod_role = 461550034668748800
submod_role = 591372495936815114
helper_role = 461550323727859712
# Vyucujici Doktorand
teacher_roles = [1020697715857948733, 591348532422639666]

[verification]
role = ''
Expand Down Expand Up @@ -74,6 +76,7 @@ bot_room = 461549842896781312
mod_room = 505679727936143361
submod_helper_room = 1023669101744357377
report_channel = 1120635712950251551
teacher_info_channel = 635169501771464704

allowed_channels = [
'bot_room',
Expand Down