import logging from typing import Dict, Callable, List, Union import discord logger = logging.getLogger(__name__) class Game: """ Game state for one guild """ def __init__(self, config_dict: Dict, save_function: Callable, guild: discord.Guild): self.config = config_dict self.save_function = save_function self.guild = guild @staticmethod def new_dict(): return { "game_started": False, } def is_started(self): return self.config["game_started"] def get_players_id(self) -> List[int]: return self.config["players"] def get_players(self) -> List[discord.Member]: return [self.guild.get_member(player) for player in self.get_players_id()] def get_player_info(self, player: Union[int, discord.Member]): if isinstance(player, discord.Member): player = player.id return self.config["player_info"][str(player)] def get_gm_role_id(self) -> int: return self.config["gm_role"] def get_gm_role(self) -> discord.Role: return self.guild.get_role(self.get_gm_role_id()) def is_gm(self, user: discord.Member) -> bool: return self.get_gm_role() in user.roles def get_game_category_id(self) -> int: return self.config["category"] def get_game_category(self) -> discord.CategoryChannel: return self.guild.get_channel(self.get_game_category_id()) async def start(self, gm_role: discord.Role, player_role: discord.Role): if self.is_started(): raise ValueError("Game already started") logger.info(f"[{self.guild.name}] Starting game") self.config["gm_role"] = gm_role.id self.config["player_role"] = player_role.id self.config["players"] = [member.id for member in player_role.members] self.config["player_info"] = {str(player): {} for player in self.config["players"]} permissions = { self.guild.default_role: discord.PermissionOverwrite(send_messages = False), gm_role: discord.PermissionOverwrite(send_messages = True), player_role: discord.PermissionOverwrite(send_messages = True), } game_category = await self.guild.create_category("In-game", overwrites = permissions) self.config["category"] = game_category.id logger.debug(f"[{self.guild.name}] Created game category") permissions = { self.guild.default_role: discord.PermissionOverwrite(read_messages = False), gm_role: discord.PermissionOverwrite(read_messages = True), } self.config["admin_chan"] = (await game_category.create_text_channel("admin", overwrites = permissions)).id logger.debug(f"[{self.guild.name}] Created admin channel") permissions = { self.guild.default_role: discord.PermissionOverwrite(send_messages = False), gm_role: discord.PermissionOverwrite(send_messages = True), } self.config["announce_chan"] = (await game_category.create_text_channel("announce", overwrites = permissions)).id self.config["votes_chan"] = (await game_category.create_text_channel("votes", overwrites = permissions)).id logger.debug(f"[{self.guild.name}] Created announcements and votes channels") self.config["discussion_chan"] = (await game_category.create_text_channel("discussion")).id # Permissions are inherited from the category logger.debug(f"[{self.guild.name}] Created discussion channel") for player in self.get_players(): channel_permissions = { self.guild.default_role: discord.PermissionOverwrite(read_messages = False), player: discord.PermissionOverwrite(read_messages = True), gm_role: discord.PermissionOverwrite(read_messages = True), } player_channel = await game_category.create_text_channel(player.name, overwrites = channel_permissions) self.get_player_info(player)["channel"] = player_channel.id logger.debug(f"[{self.guild.name}] Created player channels") self.config["game_started"] = True self.save_function() async def delete(self): category = self.get_game_category() for channel in category.channels: await channel.delete() await category.delete() self.config.clear() self.config.update(self.new_dict()) self.save_function()