예제 #1
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)
예제 #2
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))
예제 #3
0
 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'))
예제 #4
0
    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'))
예제 #5
0
 async def on_reaction_remove(self, reaction, user):
     if str(
             reaction
     ) == JOIN_EMOJI and reaction.message.author.id == self.bot.user.id and not user.bot:
         room = Room.from_message(reaction.message)
         if room:
             await self.try_leave(reaction.message.channel, room, user)
예제 #6
0
    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))
예제 #7
0
 async def on_reaction_add(self, reaction, user):
     if reaction.message.author.id == self.bot.user.id and not user.bot:
         if hasattr(user, 'guild'):
             if str(reaction) == JOIN_EMOJI:
                 room = Room.from_message(reaction.message)
                 if room:
                     await self.try_join(reaction.message.channel, room,
                                         user)
         else:
             await self.try_invite_response(reaction, user)
예제 #8
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'))
예제 #9
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
예제 #10
0
 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'))
예제 #11
0
    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'))
예제 #12
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
예제 #13
0
    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
예제 #14
0
    async def invite(self, ctx, *args):
        settings = Settings.get_for(ctx.guild.id)
        if len(args) < 1:
            return await ctx.send(settings.get_text('missing_target'))
        user_mentions = ctx.message.mentions
        role_mentions = ctx.message.role_mentions
        player = ctx.message.author
        invitees = []
        room = None

        for invitee in user_mentions:
            if invitee.id not in invitees:
                invitees.append(invitee.id)

        for role in role_mentions:
            for member in role.members:
                if member.id not in invitees:
                    invitees.append(member.id)

        player_names = []
        for member in ctx.guild.members:
            player_names.append(member.display_name.lower())
            player_names.append(member.name.lower())

        for arg in args:
            p = discord.utils.find(lambda p: p.name.lower() == arg.lower(),
                                   ctx.guild.members)
            if p and p.id not in invitees:
                invitees.append(p.id)

        rooms = Room.find(guild=ctx.guild.id)
        room_match = None
        if rooms:
            for room_data in rooms:
                r = Room.from_query(room_data)
                if player.id in r.players:
                    room = r
        if not room:
            return await ctx.send(settings.get_text('not_in_room'))

        if not invitees:
            return await ctx.send(settings.get_text('missing_target_invitees'))

        room.update_active()
        embed = discord.Embed(color=discord.Color.blurple(),
                              timestamp=now(),
                              title=choice(
                                  settings.get_text('invite_messages')).format(
                                      player.display_name, room.activity))
        embed.add_field(inline=False,
                        name=room.activity,
                        value=room.description)
        embed.add_field(inline=False,
                        name="{} ({}/{})".format(settings.get_text('players'),
                                                 len(room.players), room.size),
                        value="<@{}>".format(">, <@".join(
                            [str(id) for id in room.players])))
        embed.add_field(
            inline=False,
            name=settings.get_text('inviter') + ": " + player.display_name,
            value=settings.get_text('server') + ": " + ctx.guild.name)
        embed.add_field(inline=True, name=ID_EMOJI, value=room.role_id)
        embed.add_field(inline=True,
                        name=LANGUAGE_EMOJI,
                        value=settings.language)
        embed.set_footer(text=settings.get_text('invite_instructions'),
                         icon_url=discord.Embed.Empty)

        result_embed = discord.Embed(color=discord.Color.blurple(),
                                     description="{}: `{}`".format(
                                         settings.get_text('room'),
                                         room.activity),
                                     timestamp=now(),
                                     title=settings.get_text('invites_sent'))
        result_embed.set_footer(text="{}: {}".format(
            settings.get_text('inviter'), player.display_name),
                                icon_url=discord.Embed.Empty)
        invitee_success = []
        invitee_fail = []
        invitee_already_joined = []
        for invitee_id in invitees:
            try:
                if invitee_id in room.players:
                    invitee_already_joined.append(invitee_id)
                    continue
                invitee = self.bot.get_user(invitee_id)
                m = await invitee.send(embed=embed)
                await m.add_reaction(ACCEPT_EMOJI)
                await m.add_reaction(DECLINE_EMOJI)
                self.invites.insert(dict(user=invitee_id, room=room.role_id))
                invitee_success.append(invitee_id)
            except discord.errors.Forbidden as e:
                invitee_fail.append(invitee_id)

        if invitee_success:
            result_embed.add_field(name=settings.get_text('invitees'),
                                   value="<@{}>".format(">, <@".join(
                                       [str(id) for id in invitee_success])))
        if invitee_fail:
            result_embed.add_field(
                name=settings.get_text('failed_invites'),
                value="{}\n<@{}>".format(
                    settings.get_text('failed_invites_description'),
                    ">, <@".join([str(id) for id in invitee_fail])))
        if invitee_already_joined:
            result_embed.add_field(name=settings.get_text('already_joined'),
                                   value="<@{}>".format(">, <@".join([
                                       str(id) for id in invitee_already_joined
                                   ])))

        return await ctx.send(embed=result_embed)