@@ -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)
|
||||
|
Reference in New Issue
Block a user