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'))
Exemple #2
0
 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'))
Exemple #3
0
 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
Exemple #4
0
    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 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 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)
Exemple #7
0
 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)
Exemple #8
0
    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))
Exemple #9
0
    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 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'))
Exemple #11
0
    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
Exemple #12
0
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))
Exemple #14
0
    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'))
Exemple #15
0
 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'))
Exemple #17
0
 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 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