async def reset_settings(self, ctx): settings = Settings.get_for(ctx.guild.id) settings = Settings(Settings.defaults, guild_id=ctx.guild.id, language=settings.language, prefix=settings.prefix) await ctx.send(settings.get_text('reset_settings'))
async def determine_prefix(bot, message): guild = message.guild if guild: settings = Settings.get_for(guild.id) if settings and settings.prefix: return settings.prefix return Settings.get_default_value('prefix')
async def delete_inactive(cls, bot): for room_data in cls.find(): r = cls.from_query(room_data) if r.timeout and r.timeout > 0: guild = bot.get_guild(r.guild) birth_channel = guild.get_channel(r.birth_channel) if guild else None channel = guild.get_channel(r.channel_id) if guild else None if (channel): history = (await channel.history(limit=1).flatten()) if len(history) > 0: last_message = history[0] last_message_datetime = utime(last_message.created_at) voice_channel = guild.get_channel(r.voice_channel_id) if guild else None if voice_channel and len(voice_channel.members) > 0: r.update_active() if last_message_datetime > utime(r.last_active): r.update('last_active', last_message_datetime) time_diff = now() - utime(r.last_active) if time_diff.total_seconds()/60 >= r.timeout: # timeout is in minutes if guild: await r.disband(guild) if birth_channel: settings = Settings.get_for(guild.id) try: await birth_channel.send(settings.get_text('disband_from_inactivity').format(r.activity)) except: pass else: db.rooms.delete(role_id=r.role_id) db.invites.delete(room_id=r.role_id)
async def try_leave(self, ctx, room, player): settings = Settings.get_for(ctx.guild.id) room.update_active() if room.host == player.id: role = ctx.guild.get_role(room.role_id) await room.disband(ctx.guild) return (True, settings.get_text('disband_room').format( player.display_name, room.activity)) elif player.id in room.players: (success, response) = await room.remove_player(player) if success: try: room_channel = ctx.guild.get_channel(room.channel_id) await room_channel.send( choice(settings.leave_messages).format( player.display_name)) if response: await ctx.send(response) except: pass return (True, settings.get_text('left_room').format( player.name, room.activity)) else: return (True, settings.get_text('retry_error')) return (False, None)
async def look(self, ctx, *args): settings = Settings.get_for(ctx.guild.id) room = Room.get_by_any(ctx, args) if room: await RoomEmbed(ctx, room, 'request', settings).send() else: await ctx.send(settings.get_text('no_room'))
async def leave(self, ctx, *args): settings = Settings.get_for(ctx.guild.id) player = ctx.message.author rooms = Room.get_player_rooms(player.id, ctx.guild.id) room = None if len(rooms) > 1: role_mention_filter = ctx.message.role_mentions[ 0].id if ctx.message.role_mentions else None text_filter = ' '.join(args).lower() if args else None for r in rooms: match_channel = ctx.channel.id == r.channel_id match_text = text_filter and text_filter in r.activity.lower() match_role = role_mention_filter == r.role_id if match_channel or match_text or match_role: room = r break if not room: return await ctx.send(settings.get_text('in_multiple_rooms')) elif len(rooms) == 1: room = rooms[0] else: return await ctx.send(settings.get_text('not_in_room')) if room: (success, response) = await self.try_leave(ctx, room, player) if success and response and ctx.channel.id != room.channel_id: try: await ctx.send(response) except: pass else: return await ctx.send(settings.get_text('no_room'))
def passes_role_restriction(ctx): member = ctx.message.author settings = Settings.get_for(ctx.guild.id) if len(settings.role_restriction) > 0: role_ids = [ role.id for role in member.roles ] return has_common_element(role_ids, settings.role_restriction) or member.guild_permissions.administrator return True
async def on_command(ctx): settings = Settings.get_for(ctx.guild.id) if settings.delete_command_message: try: await ctx.message.delete() except Exception as e: log(e)
def get_room(cls, ctx, args): settings = Settings.get_for(ctx.guild.id) player = ctx.message.author rooms = Room.get_player_rooms(player.id, ctx.guild.id) room = None if len(rooms) > 1: role_mention_filter = ctx.message.role_mentions[ 0].id if ctx.message.role_mentions and ctx.message.role_mentions[ 0] else None string = ' '.join(args).lower() rx = re.search(r'\((.*?)\)', string) text_filter = rx.group(1) if rx else remove_mentions(string) for r in rooms: match_channel = ctx.channel.id == r.channel_id if ctx.channel else False match_text = text_filter and text_filter in r.activity.lower() match_role = role_mention_filter == r.role_id if match_channel or match_text or match_role: room = r break if not room: return (None, settings.get_text('in_multiple_rooms')) elif len(rooms) == 1: room = rooms[0] else: return (None, settings.get_text('not_in_room')) return (room, None)
async def cog_check(self, ctx): s = Settings.get_for(ctx.guild.id) is_enabled_command = ctx.command.name in s.allowed_host_commands if not is_enabled_command: await ctx.send(s.get_text('host_command_disabled')) return False return True
def __init__(self, ctx, total, per): self.ctx = ctx self.settings = Settings.get_for(ctx.guild.id) self.per = per self.pages = ceil(total / per) self.page = 1 self.m = None self.time = now()
async def cog_check(self, ctx): s = Settings.get_for(ctx.guild.id) is_enabled_command = ctx.command.name in s.allowed_host_commands is_host = Room.get_hosted(ctx.message.author.id, ctx.guild.id) is_admin = ctx.message.author.guild_permissions.administrator searched_room = Room.get_by_mention(ctx, ctx.message.content.split(' ')[1:]) return (is_host and is_enabled_command) or (is_admin and searched_room)
async def purge(self, ctx, *args): settings = Settings.get_for(ctx.guild.id) player = ctx.message.author if not player.guild_permissions.administrator: return await ctx.send(settings.get_text('not_admin')) (flags, words) = pop_flags(args) if 'a' not in flags and 'b' not in flags: return await ctx.send(settings.get_text('purge_missing_flag')) if 'a' in flags: rooms_data = Room.find(guild=ctx.guild.id) count = 0 for room_data in rooms_data: r = Room.from_query(room_data) guild = self.bot.get_guild(r.guild) await r.disband(guild) count += 1 await ctx.send(settings.get_text('purged_a').format(count)) if 'b' in flags: deleted_channels = 0 deleted_roles = 0 failed_channels = 0 failed_roles = 0 category = discord.utils.get(player.guild.categories, name=settings.category_name) if not category: return await ctx.send(settings.get_text('no_category')) for channel in category.channels: if iter_len( Room.find(guild=ctx.guild.id, channel_id=channel.id)) < 1: try: await channel.delete() deleted_channels += 1 except: failed_channels += 1 for role in ctx.guild.roles: if iter_len(Room.find(guild=ctx.guild.id, role_id=role.id)) < 1: if any([ role.name.startswith('({})'.format( get_text('room', lang=l))) for l in langs ]): try: await role.delete() deleted_roles += 1 except: failed_roles += 1 await ctx.send( settings.get_text('purged_b').format(deleted_channels, deleted_roles)) if failed_channels > 0 or failed_roles > 0: await ctx.send( settings.get_text('purged_b_fail').format( failed_channels, failed_roles))
async def settings(self, ctx, *args): settings = Settings.get_for(ctx.guild.id) settings_info = {} for key in Settings.defaults.keys(): text = settings.get_text('_commands')[key] settings_info[key] = { 'name': text['_name'], 'flags': text['_aliases'], 'description': text['_help'] } (flags, flag_args) = pop_flags(args) if flags: # set settings for i, flag in enumerate(flags): for field_name, field in settings_info.items(): if flag in field['flags'] + [field['name']]: (success, message) = settings.set(ctx, field_name, flag_args[i]) await ctx.send(message) else: # show settings embed embed = discord.Embed( color=discord.Color.blurple(), title=settings.get_text('settings'), description=settings.get_text('settings_instructions').format( settings.prefix)) for field_name, field in settings_info.items(): field_value = settings.get(field_name) if isinstance(field_value, bool): field_value = str(int(field_value)) elif isinstance(field_value, list): field_value = '[`\n' + '\n'.join([ ' `' + str(s).replace('`{}`', '__') + '`,' for s in field_value ]) + '\n`]' if len(field_value) > 0 else '[]' embed_desc = "{}: `-{}`\n{}".format( settings.get_text('flags'), "`, `-".join(field['flags']), '\n'.join(field['description'])) if isinstance(field_value, str) and len(field_value) > 200: embed.add_field( inline=False, name="**{}** : `{}`".format( field['name'], settings.get_text('see_below')), value=(f'{embed_desc}\n`{field_value}')[:1023 - 4] + '`') else: embed.add_field(inline=False, name="**{}** : `{}`".format( field['name'], field_value), value=embed_desc) await FieldPagesEmbed(ctx, embed).send()
async def remove_player(self, player): s = Settings.get_for(self.guild) if player.id in self.players: role = player.guild.get_role(self.role_id) await player.remove_roles(role) self.players.remove(player.id) self.update('players', ids_to_str(self.players)) if len(self.players) < 1: await self.disband(player.guild) return (True, s.get_text('disband_empty_room')) return (True, None) return (False, None)
async def join(self, ctx, *args): settings = Settings.get_for(ctx.guild.id) if len(args) < 1: return await ctx.send(settings.get_text('missing_target_room')) room = Room.get_by_any(ctx, args) if room: joined = await self.try_join(ctx, room, ctx.author) if joined: await RoomEmbed(ctx, room, 'room_joined', settings).send() else: await channel.send(settings.get_text('retry_error')) else: await ctx.send(settings.get_text('room_not_exist'))
async def add_player(self, player): s = Settings.get_for(self.guild) role = player.guild.get_role(self.role_id) channel = player.guild.get_channel(self.channel_id) if not channel or not role: return (False, s.get_text('retry_error')) if player.id in self.players: return (False, s.get_text('already_joined')) await player.add_roles(role) self.players.append(player.id) self.update('players', ids_to_str(self.players)) await channel.edit(topic="({}/{}) {}".format(len(self.players), self.size, self.description)) return True
async def on_command_error(ctx, error): settings = Settings.get_for(ctx.guild.id) if not passes_role_restriction(ctx): return elif type(error) == commands.errors.MissingPermissions: return await ctx.send(settings.get_text('not_admin')) elif type(error) == discord.Forbidden: await logc("===== FORBIDDEN Error raised from: " + ctx.message.content) await logc(error.text) return await ctx.send(settings.get_text('not_admin')) # return await ctx.send(settings.get_text('missing_permission').format('`, `'.join(missing_permissions))) elif type(error) == commands.NoPrivateMessage: return elif type(error) == commands.errors.CheckFailure: return elif type(error) == commands.errors.CommandNotFound: if settings.respond_to_invalid: await ctx.send( settings.get_text('invalid_command').format( ctx.message.content, settings.prefix)) if settings.delete_command_message: await ctx.message.delete() return elif type(error) == commands.errors.CommandInvokeError: missing_permissions = [] if not ctx.guild.me.guild_permissions.manage_channels: missing_permissions.append("ManageChannels") if not ctx.guild.me.guild_permissions.manage_roles: missing_permissions.append("ManageRoles") if not ctx.guild.me.guild_permissions.manage_messages: missing_permissions.append("ManageMessages") if missing_permissions: return await ctx.send( settings.get_text('missing_permission').format( '`, `'.join(missing_permissions))) await logc("===== Error raised from: " + ctx.message.content) await logc(error) errorText = '' try: errorText = '```' + str(error) + '```' except: pass finally: await ctx.send(errorText + settings.get_text('fatal_error').format( settings.prefix + settings.get_text('_commands')['support']['_name']))
async def try_invite_response(self, reaction, user): channel = reaction.message.channel accept = str(reaction.emoji) == ACCEPT_EMOJI decline = str(reaction.emoji) == DECLINE_EMOJI valid_invite_emoji = accept or decline from_dm = type(channel) is discord.channel.DMChannel room_id = None lang = langs[0] for field in reaction.message.embeds[0].fields: if field.name == ID_EMOJI: room_id = field.value elif field.name == LANGUAGE_EMOJI: lang = field.value search = self.invites.find_one(user=user.id, room=room_id) if not valid_invite_emoji or not search or not from_dm: return room = None room_data = Room.find_one(role_id=room_id) if room_data: room = Room.from_query(room_data) if not room: return await channel.send(get_text('room_not_exist', lang=lang)) self.invites.delete(user=user.id, room=room_id) settings = Settings.get_for(room.guild) if (accept): room_channel = self.bot.get_channel(room.channel_id) guild = self.bot.get_guild(room.guild) member = guild.get_member(user.id) if not room_channel or not guild or not member: return await channel.send(get_text('room_not_exist', lang=lang)) await channel.send(get_text('invite_accepted', lang=lang)) room.lock = False joined = await self.try_join(room_channel, room, member) if joined: await RoomEmbed(reaction.message, room, 'room_joined', settings).send() else: await channel.send(settings.get_text('retry_error')) else: await channel.send(get_text('invite_declined', lang=lang))
async def force_disband(self, ctx, *args): settings = Settings.get_for(ctx.guild.id) rooms = Room.find(guild=ctx.guild.id) activity_filter = " ".join(args) if args else None role_mention_filter = ctx.message.role_mentions[ 0].id if ctx.message.role_mentions else None rooms = Room.find(guild=ctx.guild.id) if rooms: for room_data in rooms: r = Room.from_query(room_data) if r.activity == activity_filter or r.role_id == role_mention_filter: await r.disband(ctx.guild) try: await ctx.send( settings.get_text('disband_room').format( '<@' + str(r.host) + '>', r.activity)) except discord.errors.NotFound as e: pass return return await ctx.send(settings.get_text('room_not_exist'))
async def on_voice_state_update(member, before, after): s = Settings.get_for(member.guild.id) joined = not before.channel and after.channel left = before.channel and not after.channel try: if joined: if after.channel.id == s.creation_channel: await member.move_to(None) await Room.create(member) elif after.channel.id == s.voice_creation_channel: voice_channel = await member.guild.create_voice_channel( name='\u231b '+member.display_name, bitrate=s.bitrate * 1000, category=after.channel.category, position=0 ) await member.move_to(voice_channel) elif left and len(before.channel.members) < 1 and before.channel.name.startswith('\u231b'): await before.channel.delete() except: # likely permissions error pass
def get_context(self, ctx, *args): is_admin = ctx.message.author.guild_permissions.administrator mentions = len(ctx.message.mentions) role_mentions = ctx.message.role_mentions player = ctx.message.author context = RoomContext(ctx=ctx, settings=Settings.get_for(ctx.guild.id), args=list(list(args)[0]), player=player) if is_admin and (len(role_mentions) >= 1): room = Room.get_by_role(role_mentions[0].id) else: room = Room.get_hosted(player.id, ctx.guild.id) if room: context.room = room context.mentioned_player = ctx.message.mentions[ 0] if ctx.message.mentions else None context.channel = ctx.guild.get_channel(room.channel_id) context.voice_channel = ctx.guild.get_channel( room.voice_channel_id) context.role = ctx.guild.get_role(room.role_id) return context
async def ls(self, ctx): settings = Settings.get_for(ctx.guild.id) rooms = Room.find(guild=ctx.guild.id) embed = discord.Embed(color=discord.Color.blurple()) count = 0 for room_data in rooms: count += 1 room = Room.from_query(room_data) description = room.description if room.description else "{}: {}".format( settings.get_text('players'), ', '.join(room.players)) embed.add_field(name="{}{} ({}/{})".format( ":lock: " if room.lock else "", room.activity, len(room.players), room.size), value=description, inline=False) if count > 0: embed.title = "{} ({})".format(settings.get_text('rooms'), count) await ctx.send(embed=embed) else: await ctx.send(settings.get_text('no_rooms'))
async def help(self, ctx, *args): s = Settings.get_for(ctx.guild.id) filtered_commands = [] for arg in args: for c in self.bot.commands: if (c.name == arg or arg in c.aliases) and c not in filtered_commands: filtered_commands.append(c) if len(filtered_commands) > 0: embed = discord.Embed(color=discord.Color.blurple(), title=s.get_text('help')) for command in filtered_commands: text = s.get_text('_commands')[command.name] embed.add_field(name="**{}** {} `{}`".format( text['_name'], s.get_text('alias'), "`, `".join(text['_aliases'])), value='\n'.join(text['_help']), inline=False) return await ctx.send(embed=embed) embeds = [] for cog_name, cog in self.bot.cogs.items(): cog_text = s.get_text('_cog') embed = discord.Embed(color=cog.color, title=s.get_text('help'), description='**{}**'.format( cog_text[cog_name])) for command in sorted(cog.get_commands(), key=lambda c: c.name): text = s.get_text('_commands')[command.name] embed.add_field(name="**{}** {} `{}`".format( text['_name'], s.get_text('alias'), "`, `".join(text['_aliases'])), value='\n'.join(text['_help']), inline=False) embeds.append(embed) timed_out_embed = discord.Embed(color=discord.Color.blurple(), title=s.get_text('help')) await EmbedPagesEmbed(ctx, embeds, timed_out_embed).send()
async def try_join(self, ctx, room, player): settings = Settings.get_for(ctx.guild.id) room.update_active() if not settings.allow_multiple_rooms and Room.player_is_in_any( player.id, ctx.guild.id): return (False, settings.get_text('already_in_room')) if room.lock: return (False, settings.get_text('join_locked_room')) if room.size <= len(room.players): return (False, settings.get_text('join_full_room')) if await room.add_player(player): room_channel = ctx.guild.get_channel(room.channel_id) await room_channel.send( choice(settings.join_messages).format(player.display_name)) if len(room.players) >= room.size: role = ctx.guild.get_role(room.role_id) if role: await ctx.send( settings.get_text('full_room_notification').format( role.mention, len(room.players))) return True return False
async def get_context(self, ctx, args): is_admin = ctx.message.author.guild_permissions.administrator mentions = len(ctx.message.mentions) role_mentions = ctx.message.role_mentions player = ctx.message.author context = RoomContext( ctx=ctx, settings=Settings.get_for(ctx.guild.id), args=list(args) if args else [], player=player ) if is_admin and (len(role_mentions) >= 1): room = Room.get_by_role(role_mentions[0].id) else: (room, m) = Room.get_hosted_rooms(ctx, context.args) if m: await ctx.send(m) raise discord.ext.commands.errors.CheckFailure() if room: context.room = room context.channel = ctx.guild.get_channel(room.channel_id) context.voice_channel = ctx.guild.get_channel(room.voice_channel_id) context.role = ctx.guild.get_role(room.role_id) return context
async def create(cls, member, ctx=None, **flags): player = member guild = member.guild settings = Settings.get_for(guild.id) def flag(key): return cls.unpack_value( flags[key], cls.props[key] ) if key in settings.allowed_host_commands and key in flags and len( flags[key]) > 0 else None if not guild.me.guild_permissions.manage_channels or not guild.me.guild_permissions.manage_roles: raise discord.ext.commands.errors.CommandInvokeError( "Missing Permissons") # check if able to make room if not settings.allow_multiple_rooms and cls.player_is_in_any( player.id, guild.id): if ctx: await ctx.send(settings.get_text('already_in_room')) return # activity (room name) name = player.display_name top = player.top_role.name bottom = player.roles[1].name if len(player.roles) > 1 else top activity = flag('activity') or choice(settings.default_names).format( name, top, bottom) activity = activity[0:90].strip() # color if flag('color'): color = get_color(flag('color')) elif settings.use_role_color and player.top_role.color != discord.Color.default( ): color = player.top_role.color else: color = discord.Color(int(choice(settings.default_colors))) # role role = await guild.create_role(name="({}) {}".format( settings.get_text('room'), activity), color=color, hoist=True, mentionable=True) # overwrites accessors_ids = settings.access_all_rooms_role accessors = [] for accessor_id in accessors_ids: accessor_player = guild.get_member(accessor_id) accessor_role = guild.get_role(accessor_id) if accessor_player: accessors.append(accessor_player) elif accessor_role: accessors.append(accessor_role) if len(accessors) < 1: accessors = list(filter(lambda m: m.bot, guild.members)) overwrites = { guild.default_role: discord.PermissionOverwrite(read_messages=False), guild.me: discord.PermissionOverwrite(read_messages=True, manage_channels=True), role: discord.PermissionOverwrite(read_messages=True) } for accessor in accessors: overwrites[accessor] = discord.PermissionOverwrite( read_messages=True) # channel category = await get_rooms_category(guild, settings) o = category.overwrites o.update(overwrites) overwrites = o channel = await category.create_text_channel(name=activity, position=0, overwrites=overwrites) voice_channel = None if settings.default_voice_channel: voice_channel = await guild.create_voice_channel( name=activity, bitrate=settings.bitrate * 1000, category=category, position=0, overwrites=overwrites) # new room room = Room(role_id=role.id, channel_id=channel.id, voice_channel_id=voice_channel.id if voice_channel else 0, guild=guild.id, birth_channel=ctx.message.channel.id if ctx else 0, host=player.id, players=[player.id], activity=activity, color=color, lock=flag('lock') or settings.default_lock, nsfw=flag('nsfw') or settings.default_nsfw, description=flag('description') or choice(settings.default_descriptions), size=flag('size') or settings.default_size, timeout=flag('timeout') or settings.default_timeout, created=now(), last_active=now()) await player.add_roles(role) await channel.edit(topic="({}/{}) {}".format(len(room.players), room.size, room.description), nsfw=room.nsfw) await channel.send( choice(settings.join_messages).format(player.display_name)) if ctx: await RoomEmbed(ctx, room, 'new_room', settings).send()
async def ping(self, ctx): s = Settings.get_for(ctx.guild.id) m = await ctx.send(s.get_text('ping')) ms = (m.created_at-ctx.message.created_at).total_seconds() * 1000 await m.edit(content=s.get_text('pong').format(int(ms)))
async def support(self, ctx): s = Settings.get_for(ctx.guild.id) return await ctx.send(s.get_text('support'))
async def cog_command_error(self, ctx, error): s = Settings.get_for(ctx.guild.id) if type(error) == discord.ext.commands.errors.CheckFailure: await ctx.send(s.get_text('host_command_fail'))