async def toggle_key( self, message: Message, room1: str, room2: str, user: str ): connection = self.roleplay.get_connection(room1, room2) if not connection: await message.channel.send( f'No connection from {room1} to {room2}.' ) return config = State.get_config(message.guild.id) keys = config['connections'][connection.name]['k'] for member in message.mentions: if member.id not in keys: keys.append(member.id) await message.channel.send( f'{member.mention} can now lock and unlock the connection ' f'from {room1} to {room2}.' ) else: keys.remove(member.id) await message.channel.send( f'{member.mention} can no longer lock and unlock the ' f'connection from {room1} to {room2}.' ) State.save_config(message.guild.id, config) await self.bot.save_guild_config(message.guild, config) await message.delete()
async def start_game(self, message: Message, roleplay: str, players: str): config = State.get_config(message.guild.id) if config and 'rp' in config and config['rp']: await message.channel.send( f'Cannot start roleplay, {config["rp"]} is already in progress.' ) return if roleplay not in self.bot.roleplays: await message.channel.send( f'Cannot start roleplay, unknown roleplay name {roleplay}' ) return loading_message = await message.channel.send(f'Setting up new game...') config = {'rp': roleplay, 'connections': {}} await self.bot.save_guild_config(message.guild, config) await self.bot.refresh_from_config(message.guild, config, True) await message.author.add_roles(State.get_admin_role(message.guild.id)) self.roleplay = self.bot.roleplays[roleplay] player_role = State.get_player_role(message.guild.id) for member in message.mentions: await member.add_roles(player_role) await self.move_force(message, self.roleplay.starting_room, None) await message.channel.send(f'The game begins.') await loading_message.delete() await message.delete()
async def hide(self, message: Message, location: str): config = State.get_config(message.guild.id) channel: TextChannel = message.channel connection = self.roleplay.get_connection(channel.name, location) if not connection: await channel.send( f'No connection from {channel.name} to {location}.', delete_after=60*60 ) return is_hidden = config['connections'][connection.name].get('h', False) if is_hidden: await channel.send( f'Connection from {channel.name} to {location} is already ' 'hidden.', delete_after=60*60 ) else: config['connections'][connection.name]['h'] = True State.save_config(message.guild.id, config) await self.bot.save_guild_config(message.guild, config) text = f'A connection between {channel.name} and {location} has ' \ f'been hidden.' await channel.send(text) await message.delete() await self.bot.get_chronicle(message.guild).log_announcement( channel, text )
async def view_remove(self, message: Message, room: str) -> None: config = State.get_config(message.guild.id) if 'views' not in config: config['views'] = {} if room in config['views'] \ and message.channel.name in config['views'][room]: config['views'][room].remove(message.channel.name) await self.bot.save_guild_config(message.guild, config) await message.channel.send(f'Remote view to {room} removed.') else: await message.channel.send( f'No remote view to {room} set up in this channel.' )
async def view_add(self, message: Message, room: str) -> None: config = State.get_config(message.guild.id) if 'views' not in config: config['views'] = {} if room not in config['views']: config['views'][room] = [] if message.channel.name not in config['views'][room]: config['views'][room].append(message.channel.name) await self.bot.save_guild_config(message.guild, config) await message.channel.send(f'Remote view to {room} added.') else: await message.channel.send( f'There is already a remote view to {room} in this channel.' )
async def view_list(self, message: Message) -> None: config = State.get_config(message.guild.id) all_views = [] for user_id, views in config.get('views', {}).items(): user: Member = message.guild.get_member(user_id) if user and views: all_views.append( f'**{user.display_name}:** ' + ', '.join(views) ) if all_views: await message.channel.send( 'The following remote views are set up:\n' + '\n'.join(all_views) ) else: await message.channel.send('No remote views are set up.')
async def _lock_or_unlock( self, message: Message, location: str, lock: bool = True ): config = State.get_config(message.guild.id) channel: TextChannel = message.channel connection = self.roleplay.get_connection(channel.name, location) if not connection: await channel.send( f'No connection from {channel.name} to {location}.', delete_after=60*60 ) return connection_config = config['connections'][connection.name] if not State.is_admin(message.author) \ and message.author.id not in connection_config['k']: await channel.send( f'{message.author.mention} does not have the key to ' f'{location}.', delete_after=60*60 ) return locked = connection_config['l'] if locked and lock or not locked and not lock: await channel.send( f'Access to {location} is already ' f'{"locked" if lock else "unlocked"}.', delete_after=60*60 ) return self._update_connection( config["connections"], channel.name, location, locked=lock ) State.save_config(message.guild.id, config) await self.bot.save_guild_config(message.guild, config) await channel.send( f'{"Locked" if lock else "Unlocked"} access to {location}.' ) await message.delete() name = 'the GM' \ if State.is_admin(message.author) else message.author.display_name await self.bot.get_chronicle(message.guild).log_announcement( channel, f'Access from **{message.channel.name}** to **{location}** ' f'{"" if lock else "un"}locked by **{name}**' )
async def global_variables(request: Request): bot: RoleplayBot = request.app['bot'] roleplays = [] for guild in bot.guilds: if bot.get_roleplay_for_guild(guild.id): roleplays.append({'id': guild.id, 'name': guild.name}) try: guild_id = int(request.match_info['guild_id']) except (KeyError, ValueError): guild_id = None roleplay = None if guild_id is not None: config = State.get_config(guild_id) roleplay_data = bot.get_roleplay_for_guild(guild_id) if roleplay_data: guild = bot.get_guild(guild_id) roleplay = { 'id': guild_id, 'name': guild.name, 'description': roleplay_data.description, 'characters': [{ 'user_id': user_id, 'id': character_id, **character, } for user_id, user_characters in config.get( 'characters', {}).items() for character_id, character in user_characters['characters'].items()], 'commands': [ command for plugin in bot.get_all_plugins(guild) for command in sorted(plugin.commands.values(), key=lambda c: c.name) if command.enabled and not command.requires_admin and not command.hidden ] } return { 'base_url': bot_config['rpbot']['base_url'], 'roleplay': roleplay, 'roleplays': sorted(roleplays, key=itemgetter('name')), }
async def log( self, source_channel: Optional[str], message: str, extra_only: bool = False, ) -> None: config = State.get_config(self.guild.id) if not config: return views = config.get('views', {}) dest_channels = set() if extra_only else {self.channel_name} if source_channel in views: dest_channels.update(views[source_channel]) for channel in self.guild.text_channels: if channel.name in dest_channels: await channel.send(message[:MAX_MESSAGE_LENGTH]) if message[MAX_MESSAGE_LENGTH:]: await channel.send(message[MAX_MESSAGE_LENGTH:])
async def character(request: Request): try: guild_id = int(request.match_info['guild_id']) except (KeyError, ValueError): guild_id = None char = None if guild_id is not None: user_id = request.match_info['user_id'] character_id = request.match_info['character_id'] config = State.get_config(guild_id) characters_data = config.get('characters', {}) char = characters_data.get(user_id, {}).get('characters', {}).get(character_id) if char: move_timers = State.get_var(guild_id, 'move_timers') move_countdown_time = None if move_timers: move_countdown_time = move_timers.get(int(user_id)) char = { **char, "move_countdown_time": move_countdown_time.astimezone().isoformat() if move_countdown_time else "" } return {'character': char}
async def reload(self, message: Message) -> None: self.bot.reload() await self.bot.refresh_from_config( message.guild, State.get_config(message.guild.id) ) await message.channel.send('Roleplay definition and plugins reloaded.')
async def move(self, message: Message, room: Optional[str]): connections = State.get_config(message.guild.id)['connections'] channel: TextChannel = message.channel destinations = self._list_destinations(connections, channel.name) if not room: destination_list = '\n'.join( destination + (' *(locked)*' if locked else '') for destination, locked in destinations ) await channel.send( ( 'The following destinations are available from here:\n' + destination_list ) if destination_list else 'No destinations are currently available.', delete_after=60*60 ) await message.delete() return for destination, locked in destinations: if destination == room: if locked: await channel.send( f'{room} is currently locked off.', delete_after=60*60 ) await message.delete() return break else: await channel.send( f'Cannot reach {room} from here.', delete_after=60*60 ) return move_timers = State.get_var(message.guild.id, 'move_timers') if not move_timers: move_timers = defaultdict(lambda: datetime.min) time_remaining = ( move_timers[message.author.id] - datetime.now() ).total_seconds() if time_remaining > 0: minutes = time_remaining // 60 await channel.send( 'Must wait ' + ( f'{int(minutes)} minutes' if minutes else f'{int(time_remaining)} seconds' ) + ' before moving again.', delete_after=60*60 ) return connection = self.roleplay.get_connection(channel.name, room) new_channel = await self._move_player( message.author, room, message.channel ) move_timers[message.author.id] = datetime.now() + timedelta( minutes=connection.timer ) State.set_var(message.guild.id, 'move_timers', move_timers) await channel.send(f'{message.author.mention} moves to {room}') await new_channel.send( f'{message.author.mention} moves in from {channel.name}' ) await message.delete()
def get_roleplay_for_guild(self, guild_id: int): config = State.get_config(guild_id) return self.roleplays[config['rp']] \ if config and 'rp' in config and config['rp'] else None
def _get_config(guild: Guild) -> Dict[str, Any]: config = State.get_config(guild.id) if not config or not config.get('rp'): raise CommandException( 'No active roleplay, characters not available.') return config
async def _save_config(self, guild: Guild) -> None: await self.bot.save_guild_config(guild, State.get_config(guild.id))