Implemented #2 and partially implemented #8

This commit is contained in:
2025-04-25 00:27:01 +02:00
parent 3e6cb75457
commit d9f563285c
3 changed files with 267 additions and 12 deletions

View File

@@ -1,8 +1,11 @@
from dataclasses import dataclass
from hashlib import shake_256
from logging import Logger
from typing import Any, Dict, List, Optional
from bson import ObjectId
from discord import Bot, Guild, Member, PermissionOverwrite, TextChannel, Forbidden, Role
from discord.abc import GuildChannel
from libbot.cache.classes import Cache
from pymongo.results import InsertOneResult
@@ -21,7 +24,7 @@ class PycordUser:
"_id",
"id",
"guild_id",
"channel_id",
"event_channels",
"is_jailed",
"current_event_id",
"current_stage_id",
@@ -34,13 +37,18 @@ class PycordUser:
_id: ObjectId
id: int
guild_id: int
channel_id: int | None
event_channels: Dict[str, int]
is_jailed: bool
current_event_id: ObjectId | None
current_stage_id: ObjectId | None
registered_event_ids: List[ObjectId]
completed_event_ids: List[ObjectId]
# TODO Review the redesign
# event_channel_ids: {
# "%event_id%": %channel_id%
# }
@classmethod
async def from_id(
cls, user_id: int, allow_creation: bool = True, cache: Optional[Cache] = None
@@ -93,7 +101,7 @@ class PycordUser:
"_id": self._id if not json_compatible else str(self._id),
"id": self.id,
"guild_id": self.guild_id,
"channel_id": self.channel_id,
"event_channels": self.event_channels,
"is_jailed": self.is_jailed,
"current_event_id": (
self.current_event_id if not json_compatible else str(self.current_event_id)
@@ -182,7 +190,7 @@ class PycordUser:
return {
"id": user_id,
"guild_id": guild_id,
"channel_id": None,
"event_channels": {},
"is_jailed": False,
"current_event_id": None,
"current_stage_id": None,
@@ -247,3 +255,109 @@ class PycordUser:
self.completed_event_ids.append(event_id)
await self._set(cache, completed_event_ids=self.completed_event_ids)
async def setup_event_channel(
self,
bot: Bot,
guild: Guild,
pycord_guild: "PycordGuild",
pycord_event: "PycordEvent",
cache: Optional[Cache] = None,
):
if str(pycord_event._id) in self.event_channels.keys():
return
discord_member: Member | None = guild.get_member(self.id)
discord_category: GuildChannel | None = bot.get_channel(pycord_guild.category_id)
if discord_member is None:
raise RuntimeError(
f"Discord guild member with ID {self.id} in guild with ID {guild.id} could not be found!"
)
# TODO Add a unique exception
# raise DiscordGuildMemberNotFoundError(self.id, guild.id)
if discord_category is None:
raise RuntimeError(
f"Discord category with ID {pycord_guild.category_id} in guild with ID {guild.id} could not be found!"
)
# TODO Add a unique exception
# raise DiscordCategoryNotFoundError(pycord_guild.category_id, guild.id)
permission_overwrites: Dict[Role | Member, PermissionOverwrite] = {
guild.default_role: PermissionOverwrite(
view_channel=False,
),
guild.self_role: PermissionOverwrite(
view_channel=True,
),
discord_member: PermissionOverwrite(
view_channel=True,
send_messages=True,
use_application_commands=True,
),
}
channel: TextChannel = await guild.create_text_channel(
f"{discord_member.name}_{shake_256(str(pycord_event._id).encode()).hexdigest(3)}",
category=discord_category,
overwrites=permission_overwrites,
reason=f"Event channel of {self.id} for event {pycord_event._id}",
)
await self.set_event_channel(pycord_event._id, channel.id, cache=cache)
async def lock_event_channel(
self,
guild: Guild,
event_id: str | ObjectId,
completely: bool = False,
channel: Optional[TextChannel] = None,
):
discord_member: Member | None = guild.get_member(self.id)
discord_channel: TextChannel | None = (
channel if channel is not None else guild.get_channel(self.event_channels[str(event_id)])
)
if discord_member is None:
raise RuntimeError(
f"Discord guild member with ID {self.id} in guild with ID {guild.id} could not be found!"
)
# TODO Add a unique exception
# raise DiscordGuildMemberNotFoundError(self.id, guild.id)
if discord_member is None:
raise RuntimeError(
f"Discord channel with ID {self.event_channels[str(event_id)]} in guild with ID {guild.id} could not be found!"
)
# TODO Add a unique exception
# raise DiscordChannelNotFoundError(self.event_channels[str(event_id)], guild.id)
permission_overwrite: PermissionOverwrite = PermissionOverwrite(
view_channel=not completely,
send_messages=False,
use_application_commands=False,
)
try:
await discord_channel.set_permissions(
discord_member, overwrite=permission_overwrite, reason="Invoked from the user method"
)
except Forbidden:
logger.error(
"Could not update channel permissions of %s for %s due to user having higher privileges.",
discord_channel.id,
self.id,
)
# TODO Add documentation
async def set_event_channel(
self, event_id: str | ObjectId, channel_id: int, cache: Optional[Cache] = None
) -> None:
self.event_channels[event_id if isinstance(event_id, str) else str(event_id)] = channel_id
await self._set(cache, event_channels=self.event_channels)