Esempio n. 1
0
    def __init__(self, client: Bot):
        self.emoji: str = get_cog(self.__class__.__name__)['emoji']

        async def after_ready_():
            await client.wait_until_ready()
            await self.after_ready()

        client.loop.create_task(after_ready_())
Esempio n. 2
0
 async def after_ready(self):
     with open(get_path('reactions'), 'r', encoding='utf-8') as f:
         self.reactions = f.read().split('\n')
     with open(get_path('greetings'), 'r', encoding='utf-8') as f:
         self.greetings = f.read().split('\n')
     self.protocol_cog = self.client.get_cog(get_cog('ProtocolCog')['name'])
     for initial in ('ㅁ', 'ㅇ', 'ㄹ', 'ㄴ'):
         for final in ('ㅁ', 'ㅇ', 'ㄴ', None):
             for medial in map(str, CHAR_MEDIALS):
                 self.characters.append(
                     join_jamos_char(initial, medial, final))
Esempio n. 3
0
 async def send_cog_list(self, ctx: Context):
     literal = literals('send_cog_list')
     states = list()
     count = len(self.client.cogs)
     message = None
     for i, cog in enumerate(sorted(self.client.cogs.items(),
                                    key=lambda item: get_cog(type(item[1]).__name__)['priority'])):
         name, cog = cog
         if isinstance(cog, CustomCog):
             name = cog.emoji + ' ' + name
         page_embed = ChainedEmbed(title=literal['title'], description=literal['description'])
         page_embed.set_thumbnail(url=self.client.user.avatar_url)
         page_embed.add_field(name=name, value=brief_cog(cog))
         page_embed.set_footer(text=literal['footer'] % (i + 1, count))
         if message is None:
             message = await ctx.send(embed=page_embed)
         states.append(InterfaceState(callback=message.edit, embed=page_embed))
     await attach_page_interface(self.client, message, states, user=ctx.author)
Esempio n. 4
0
class ProtocolCog(CustomCog, BotProtocol, name=get_cog('ProtocolCog')['name']):
    """
    다른 봇과 소통하기 위한 기능을 포함합니다.
    """

    def __init__(self, client: Bot):
        super().__init__(client)
        self.client: Bot = client
        self.holding_data: dict = dict()
        self.done: list = list()

    @CustomCog.listener()
    async def on_message(self, message):
        if message.author.id == get_constant('kenken_id'):
            return
        await super().on_message(message)

    @CustomCog.listener()
    async def on_command_error(self, ctx: commands.Context, _):
        if ctx.guild is not None and ctx.prefix in self.client.command_prefix:
            Log.command('pass protocol request generated.')
            request = Request(receiver=BotProtocol.ALL, signal=BotProtocol.PASS,
                              addition=f'{ctx.prefix} {ctx.channel.mention} {ctx.message.id}')
            await ctx.send(str(request), delete_after=1)

    async def on_echo(self, request: Request):
        Log.command('detected.')
        if request.addition:
            await request.message.channel.send(request.addition)

    async def on_pass(self, request: Request):
        Log.command('detected.')
        addition = request.addition.split(' ', 2)
        if len(addition) < 3:
            Log.error('lack of components')
            return
        self.client.command_prefix.insert(0, addition[0])
        request_ctx = await self.client.get_context(request.message)
        try:
            channel: TextChannel = await TextChannelConverter().convert(request_ctx, addition[1])
            message: Message = await channel.fetch_message(int(addition[2]))
            ctx: Context = await self.client.get_context(message)
            await self.client.invoke(ctx)
        except BadArgument:
            Log.error(f'channel {addition[1]} not found')
        except NotFound:
            Log.error(f'message {addition[2]} not found')
        self.client.command_prefix = self.client.command_prefix[-1:]

    async def on_send(self, request: Request):
        literal = literals('on_send')
        key = request.addition.strip()

        async def respond(data_, key_):
            here_request = request.generate_respond(signal=BotProtocol.HERE, addition=key_ + ' ')
            addition_length = MESSAGE_MAX_LENGTH - len(str(here_request)) - 1
            here_request.addition += data_[:addition_length]
            data_ = data_[addition_length:]
            await request.message.channel.send(str(here_request), delete_after=1)
            if data_:
                for d in split_by_length(data_):
                    await request.message.channel.send(d, delete_after=1)
            done_request = request.generate_respond(signal=BotProtocol.DONE, addition=key_)
            await request.message.channel.send(str(done_request), delete_after=1)

        if key == literal['application']:
            data = json.dumps(get_application_sheet(), ensure_ascii=False)
            await respond(data, key)
        if key == literal['regulation']:
            data = doc_read(get_constant('regulation')['doc_id'])
            await respond(data, key)

    async def on_here(self, request: Request):
        addition = request.addition.split(' ', 1)
        while len(addition) < 2:
            Log.error('lack of components')
            return
        key = addition[0]
        data = addition[1]
        while not self.done or self.done[-1].addition != key:
            message = await self.client.wait_for('message', check=lambda msg: msg.author == request.message.author)
            data += message.content
        self.done.pop(-1)
        if key not in self.holding_data:
            self.holding_data[key] = list()
        self.holding_data[key].append(FreshData(data))

    async def on_done(self, request: Request):
        self.done.append(request)
Esempio n. 5
0
class ShteloCog(CustomCog, name=get_cog('ShteloCog')['name']):
    """
    슈텔로의 관리를 위한 기능을 포함합니다.
    """
    def __init__(self, client: Bot):
        super().__init__(client)
        self.client: Bot = client
        self.regulation: Optional[FreshData] = None
        self.deck_handler: DeckHandler = DeckHandler(client)
        self.shtelo_guild: Optional[Guild] = None
        self.partner_channel: Optional[TextChannel] = None
        self.member_role: Optional[Role] = None
        self.tester_role: Optional[Role] = None
        self.title_div_role: Optional[Role] = None
        self.deck_div_role: Optional[Role] = None
        self.partner_role: Optional[Role] = None

    async def after_ready(self):
        self.shtelo_guild = self.client.get_guild(get_constant('shtelo_guild'))
        self.partner_channel = self.client.get_channel(
            get_constant('partner_channel'))
        self.member_role = self.shtelo_guild.get_role(
            get_constant('member_role'))
        self.tester_role = self.shtelo_guild.get_role(
            get_constant('tester_role'))
        self.title_div_role = self.shtelo_guild.get_role(
            get_constant('title_div_role'))
        self.deck_div_role = self.shtelo_guild.get_role(
            get_constant('deck_div_role'))
        self.partner_role = self.shtelo_guild.get_role(
            get_constant('partner_role'))

    def fetch_regulation(self):
        if self.regulation is None \
                or self.regulation.data is None:
            paragraphs = wrap_codeblock(doc_read(
                get_constant('regulation')['doc_id']),
                                        split_paragraph=True)
            self.regulation = FreshData(paragraphs, SECOND_PER_HOUR)
        else:
            paragraphs = self.regulation.data
        return paragraphs

    async def receive_application(self,
                                  member: Member,
                                  remarks: str,
                                  on_error=None,
                                  keys=None,
                                  rows=None):
        await update_application(member, APPLICATION_RECEIVED, remarks,
                                 on_error, keys, rows)
        tasks = list()
        if self.tester_role not in member.roles:
            tasks.append(member.add_roles(self.tester_role))
        if self.title_div_role not in member.roles:
            tasks.append(member.add_roles(self.title_div_role))
        if self.deck_div_role not in member.roles:
            tasks.append(member.add_roles(self.deck_div_role))
        if tasks:
            await asyncio.wait(tasks)

    @modules.CustomCog.listener(name='on_message')
    async def receive_automatically(self, message: Message):
        literal = literals('receive_automatically')

        async def failed():
            await self.partner_channel.send(literal['failed'] %
                                            message.author.mention)

        if message.channel.id != get_constant(
                'self_introduction_channel') or len(message.content) < 10:
            return
        keys, rows = get_application_sheet()
        application = get_application_of(message.author, rows)
        if application is None or application[APPLICATION_STATE]:
            return
        trigger_member_name = application[APPLICATION_INVITER]
        trigger_role = self.member_role
        if not trigger_member_name:
            trigger_member_name = application[APPLICATION_SUBACCOUNT]
            trigger_role = None
        try:
            trigger_member = await MemberConverter().convert(
                await self.client.get_context(message), trigger_member_name)
        except BadArgument as e:
            await failed()
            raise e
        if trigger_role is not None and trigger_role not in trigger_member.roles:
            await failed()
            return
        remark = str(message.author.id)
        if not application[APPLICATION_INVITER]:
            remark = literal['subaccount'] % (trigger_member.id, remark)
        await self.receive_application(message.author, remark, None, keys,
                                       rows)
        await message.add_reaction(CONFIRM_EMOJI)
        if application[APPLICATION_INVITER]:
            add_member(message.author, application[APPLICATION_NICKNAME])
        await self.partner_channel.send(
            literal['done'] % (message.author.mention, message.jump_url),
            embed=get_application_embed(application))

    @modules.group(name='가입신청서', aliases=('가입', '신청서'))
    @partner_only()
    async def applications(self, ctx: Context, *query: str):
        literal = literals('applications')
        start_message = await ctx.author.send(literal['start'])
        message = None
        _, replies = get_application_sheet()
        query = tuple(set(query))
        query_state = tuple(
            filter(lambda q: q in (APPLICATION_RECEIVED, APPLICATION_APPROVED),
                   query))
        query = tuple(
            filter(
                lambda q: q not in
                (APPLICATION_RECEIVED, APPLICATION_APPROVED), query))
        if not query_state:
            if not query:
                query_state = (APPLICATION_RECEIVED, )
            else:
                query_state = (APPLICATION_RECEIVED, APPLICATION_APPROVED)
        queried = list(
            filter(
                lambda r: (not r[APPLICATION_STATE] or r[APPLICATION_STATE] in
                           query_state) and
                (not query or tuple(filter(lambda q: q in str(r), query))),
                replies))
        query_str = ', '.join(query + query_state)
        count = len(queried)
        states = list()
        for i, reply in enumerate(reversed(queried)):
            reply_embed = get_application_embed(reply)
            reply_embed.set_footer(text=literal['footer'] % (i + 1, count))
            if message is None:
                await start_message.edit(content=literal['done'] %
                                         (query_str, count),
                                         embed=reply_embed)
                message = start_message
            states.append(InterfaceState(message.edit, embed=reply_embed))
        if message is None:
            await start_message.edit(content=literal['not_found'] % query_str)
        else:
            await attach_page_interface(self.client,
                                        message,
                                        states,
                                        user=ctx.author,
                                        after=message.delete())

    @applications.command(name='접수')
    @guild_only()
    @partner_only()
    async def application_receive(self,
                                  ctx: Context,
                                  member: Member,
                                  *,
                                  remarks: str = None):
        literal = literals('application_receive')
        message = await ctx.send(literal['start'])
        keys, rows = get_application_sheet()
        appilcation = get_application_of(member, rows)
        if appilcation is None:
            await message.edit(content=literal['failed'] % str(member))
            return
        if remarks is None:
            remarks = str(member.id)
        if appilcation[APPLICATION_SUBACCOUNT] is not NO:
            try:
                main_account = await MemberConverter().convert(
                    ctx, appilcation[APPLICATION_SUBACCOUNT])
            except BadArgument:
                pass
            else:
                remarks = literal['subaccount'] % (main_account.id, remarks)
        await self.receive_application(member, remarks, message.delete)
        await message.edit(content=literal['done'] % str(member))

    @applications.command(name='승인')
    @guild_only()
    @partner_only()
    async def application_approve(self,
                                  ctx: Context,
                                  member: Member,
                                  *,
                                  remarks: str = None):
        literal = literals('application_approve')
        message = await ctx.send(literal['start'])
        if remarks is None:
            remarks = member.id
        await update_application(member, APPLICATION_APPROVED, remarks,
                                 message.delete)
        tester_role = ctx.guild.get_role(get_constant('tester_role'))
        member_role = ctx.guild.get_role(get_constant('member_role'))
        tasks = list()
        if tester_role in member.roles:
            tasks.append(member.remove_roles(tester_role))
        if member_role not in member.roles:
            tasks.append(member.add_roles(member_role))
        tasks.append(message.edit(content=literal['done'] % member.mention))
        await asyncio.wait(tasks)

    @modules.group(name='회원', enabled=False)
    async def member(self, ctx: Context):
        pass

    @member.command(name='등록')
    @guild_only()
    @partner_only()
    async def member_register(self, ctx: Context, member: Member):
        literal = literals('member')
        message = await ctx.send(literal['start'])
        add_member(member)
        await message.edit(content=literal['done'])

    @member.group(name='수정', enabled=False)
    @guild_only()
    @partner_only()
    async def member_edit(self, ctx: Context):
        pass

    @member_edit.command(name='닉네임')
    @guild_only()
    @partner_only()
    async def member_edit_nickname(self, ctx: Context, query: str, *,
                                   nickname: str):
        literal = literals('member')
        message = await ctx.send(literal['start'])
        edit_member(query, nickname)
        await message.edit(content=literal['done'])

    @member_edit.command(name='상태')
    @guild_only()
    @partner_only()
    async def member_edit_state(self, ctx: Context, query: str, *, state: str):
        literal = literals('member')
        message = await ctx.send(literal['start'])
        edit_member(query, None, state)
        await message.edit(content=literal['done'])

    # @applications.command(name='기각')
    # @guild_only()
    # @partner_only()
    # async def application_reject(self, ctx: Context, member: Member, *, remarks: str = None):
    #     literal = literals('application_reject')
    #     message = await ctx.send(literal['start'])
    #     if remarks is None:
    #         remarks = member.id
    #     application = await update_application(member, STATE_REJECTED, remarks, message.delete())
    #     tester_role = ctx.guild.get_role(get_constant('tester_role'))
    #     if tester_role in member.roles:
    #         await member.remove_roles(tester_role)
    #     update_member_list(member, application[NICKNAME], STATE_QUIT)
    #     await message.edit(content=literal['done'] % member.mention)

    @applications.command(name='전체', aliases=('*', ))
    async def applications_all(self, ctx: Context):
        await self.applications(ctx, APPLICATION_RECEIVED,
                                APPLICATION_APPROVED)

    @modules.group(name='회칙')
    async def regulation(self, ctx: Context, *, keyword: str = ''):
        literal = literals('regulation')
        message = await ctx.send(literal['start'])
        paragraphs = self.fetch_regulation()
        await message.edit(content=literal['done'])
        if not keyword:
            await ctx.author.send(paragraphs[0])
            await ctx.author.send(literal['no_keyword'])
        else:
            found = [p for p in paragraphs[1:] if '# ' + keyword + '\n' in p]
            if not found:
                found = [p for p in paragraphs[1:] if keyword in p]
            if not found:
                await ctx.author.send(literal['not_found'] % keyword)
            else:
                for p in found:
                    await ctx.author.send(p)

    @regulation.command(name='전체', aliases=('*', ))
    async def regulation_all(self, ctx: Context):
        literal = literals('regulation_all')
        message = await ctx.send(literal['start'])
        paragraphs = wrap_codeblock(doc_read(
            get_constant('regulation')['doc_id']),
                                    split_paragraph=True)
        await message.edit(content=literal['done'])
        for p in paragraphs:
            await ctx.author.send(p)

    @modules.command(name='회의록')
    async def meeting_log(self, ctx: Context):
        await ctx.send(literals('meeting_log')['message'])
Esempio n. 6
0
class BaseCog(CustomCog, name=get_cog('BaseCog')['name']):
    """
    기본적인 기능을 포함합니다.
    """
    def __init__(self, client: Bot):
        super().__init__(client)
        self.client: Bot = client
        self.reactions: list = list()
        self.greetings: list = list()
        self.characters: list = list()
        self.protocol_cog = None

    async def after_ready(self):
        with open(get_path('reactions'), 'r', encoding='utf-8') as f:
            self.reactions = f.read().split('\n')
        with open(get_path('greetings'), 'r', encoding='utf-8') as f:
            self.greetings = f.read().split('\n')
        self.protocol_cog = self.client.get_cog(get_cog('ProtocolCog')['name'])
        for initial in ('ㅁ', 'ㅇ', 'ㄹ', 'ㄴ'):
            for final in ('ㅁ', 'ㅇ', 'ㄴ', None):
                for medial in map(str, CHAR_MEDIALS):
                    self.characters.append(
                        join_jamos_char(initial, medial, final))

    def get_greeting(self, message):
        greeting = f'{choice(self.greetings)}'
        if random() >= 0.5:
            greeting += f' **{message.author.display_name}**!'
        else:
            greeting += '!'
        return greeting

    def kenken_called(self, message: str):
        count = 0
        for ken in ('켄', '캔', '켼', '컌', '꺤', '꼔', '껜', '깬'):
            count += message.count(ken)
        if count < 2:
            count = 0
        if not count and any(
                word in message.upper()
                for word in ('KENKEN', '켄켄', str(self.client.user.id),
                             self.client.user.display_name)):
            count = 2
        return count

    def get_custom_emoji_embed(self, emoji_id: int):
        emoji: PartialEmoji = self.client.get_emoji(emoji_id)
        embed = ChainedEmbed()
        embed.set_image(url=emoji.url)
        embed.set_author(name=f':{emoji.name}:')
        return embed

    @CustomCog.listener(name='on_message')
    async def react_to_mention(self, message: Message):
        ctx: commands.Context = await self.client.get_context(message)
        if ctx.valid or message.author.id == self.client.user.id or self.protocol_cog.get_request(
                message) is not None:
            return
        if count := self.kenken_called(message.content):
            if any(word in message.content.upper() for word in self.greetings):
                Log.command('kenkenjr greeted.')
                await ctx.send(self.get_greeting(message))
            elif count <= 2:
                Log.command('kenkenjr called.')
                await message.channel.send(f'{choice(self.reactions)}')
            else:
                await message.channel.send(
                    ''.join([choice(self.characters)
                             for _ in range(count)])[:1997] +
                    ''.join([choice(tuple('!?.')) for _ in range(3)]))
Esempio n. 7
0
class GameCog(CustomCog, name=get_cog('GameCog')['name']):
    """
    심심할 때 한 번 쯤 시험삼아 써 볼만한 기능들을 포함합니다.
    """
    def __init__(self, client: Bot):
        super().__init__(client)
        self.client: Bot = client

    @modules.command(name='왕', aliases=('왕게임', 'king'))
    @guild_only()
    async def king(self, ctx: Context, player1: Member, player2: Member,
                   player3: Member, *players: Member):
        players = list(players)
        players.extend((player1, player2, player3))
        tasks = list()
        king = None
        i = 0
        count_description = literals('king')['count'] % (len(players) - 1)
        footer = literals('king')['footer']
        while len(players):
            player1 = players.pop(randrange(0, len(players)))
            if i == 0:
                king = player1
            else:
                embed = ChainedEmbed(title=literals('king')['number'] % i,
                                     description=count_description)
                embed.set_footer(text=footer)
                tasks.append(player1.send(embed=embed))
            i = i + 1
        embed = ChainedEmbed(title=literals('king')['king'] %
                             king.display_name,
                             description=count_description)
        embed.set_image(url=king.avatar_url)
        embed.set_footer(text=footer)
        tasks.append(
            ctx.send(' '.join(
                [member.mention for member in ctx.message.mentions]),
                     embed=embed))
        tasks.append(ctx.message.delete())
        await asyncio.wait(tasks)

    @modules.command(name='인디언포커', aliases=('인디언', ))
    @guild_only()
    async def indian_poker(self,
                           ctx: Context,
                           player1: User,
                           player2: User,
                           chip: int = 15):
        if IndianPoker.get_game(player1) is not None:
            await ctx.send(ALREADY_PLAYING % player1.mention)
        elif IndianPoker.get_game(player2) is not None:
            await ctx.send(ALREADY_PLAYING % player2.mention)
        else:
            game = IndianPoker(ctx, player1, player2, chip)
            await game.run()

    @modules.group(name='요트')
    async def yacht(self, ctx: Context):
        game = Yacht.get_game(ctx.author)
        if game is not None and isinstance(game, Yacht):
            await ctx.send(ALREADY_PLAYING % ctx.author.mention)
        else:
            game = Yacht(ctx, ctx.author)
            await game.run()

    @yacht.command(name='도움말', aliases=('규칙', ))
    async def yacht_help(self, ctx: Context):
        literal = literals('yacht_help')
        help_embed: ChainedEmbed = ChainedEmbed(
            title=literal['title'], description=literal['description'])
        for field in literal['fields']:
            help_embed.add_field(name=field['name'], value=field['value'])
        await ctx.send(embed=help_embed)

    @modules.group(name='게임')
    async def game(self, ctx: Context):
        pass

    @game.command(name='중단', aliases=('종료', '포기'))
    async def game_close(self, ctx: Context):
        literal = literals('game_close')
        game = Game.get_game(ctx.author)
        if game is None or not game.stop():
            await ctx.send(literal['not_found'])
        else:
            await ctx.send(
                literal['done'] %
                ' '.join([player.mention for player in game.players]))
Esempio n. 8
0
class ControlCog(CustomCog, name=get_cog('ControlCog')['name']):
    """
    봇의 관리와 직결되는 기능들을 포함합니다.
    """
    def __init__(self, client: CustomBot):
        super().__init__(client)
        self.client: CustomBot = client

    @modules.group(name='테스트', aliases=('test', 't'))
    @owner_only()
    async def test(self, ctx: Context):
        pass

    @modules.command(name='따라해', aliases=('echo', 'e'))
    @partner_only()
    async def echo(self, ctx: Context, *, content: str):
        await ctx.send(content)

    @modules.command(name='삭제', aliases=('delete', ))
    @partner_only()
    @guild_only()
    async def delete(self, ctx: Context, count: int):
        count = min(max(1, count), 100)
        messages = await ctx.channel.purge(limit=count, bulk=True)
        try:
            await ctx.channel.delete_messages(messages)
        except NotFound:
            if count != 1:
                await ctx.channel.send(literals('delete')['failed'])
        except (ClientException, Forbidden, HTTPException) as e:
            await ctx.channel.send(literals('delete')['failed'])
            raise e
        await ctx.channel.send(literals('delete')['done'] % count,
                               delete_after=10)

    @modules.group(name='리로드', enabled=False)
    @owner_only()
    async def reload(self, ctx: Context):
        await self.reload_literals(ctx)
        await self.reload_cogs(ctx)

    @reload.command(name='리터럴', enabled=False)
    @owner_only()
    async def reload_literals(self, ctx: Context):
        reload_literals()
        await ctx.send(literals('reload_literals')['done'])

    @reload.command(name='코그', aliases=('기능', ), enabled=False)
    @owner_only()
    async def reload_cogs(self, ctx: Context):
        message = await ctx.send(literals('reload_cogs')['start'])
        try:
            done = self.client.reload_all_extensions()
        except Exception as e:
            await message.edit(content=(literals('reload_cogs')['failed'] +
                                        '```\n' + str(e) + '```'))
            Log.error(e)
        else:
            if done:
                await message.edit(content=literals('reload_cogs')['done'])
            else:
                await message.edit(content=(literals('reload_cogs')['failed']))
Esempio n. 9
0
class HelpCog(CustomCog, name=get_cog('HelpCog')['name']):
    """
    필요한 명령어를 찾거나 사용볍을 확인하기 위한 기능을 포함합니다.
    """

    def __init__(self, client: Bot):
        super().__init__(client)
        self.client: Bot = client

    @modules.command(name='검색', aliases=('찾기', 'search', 's'))
    async def search(self, ctx: Context, keyword: str, *keywords: str):
        literal = literals('search')
        keywords = list(keywords)
        keywords.append(keyword)
        description = literal['found']
        embeds = ChainedEmbed(title=literal['title'], description=description)
        embeds.set_thumbnail(url=self.client.user.avatar_url)
        found = 0
        for command in self.client.commands:
            found += check_correlation(command, keywords, embeds)
        embeds.description = description % (found, ', '.join(keywords)) if found \
            else literal['not_found'] % ', '.join(keywords)
        for embed in embeds.to_list():
            await ctx.send(embed=embed)

    @modules.command(name='명령어', aliases=('commands', 'cmd', 'cmds'))
    async def commands(self, ctx: Context, *, category: str = ''):
        cog: Cog = self.client.get_cog(category)
        if cog is not None:
            await self.send_cog_info(ctx, cog)
        else:
            await self.send_cog_list(ctx)

    @modules.command(name='도움말', aliases=('help', 'h'))
    async def help(self, ctx: Context, *, command_name: str = ''):
        if not command_name:
            command_name = '도움말'
        command: Command = self.client.get_command(command_name)
        cog: Cog = self.client.get_cog(command_name)
        if command is not None:
            await self.send_command_help(ctx, command)
        elif cog is not None:
            await self.send_cog_info(ctx, cog)
        else:
            raise BadArgument(f'command "{command_name}" is not found')

    async def send_cog_info(self, ctx: Context, cog: Cog):
        cog_name = cog.qualified_name
        if isinstance(cog, CustomCog):
            cog_name = cog.emoji + ' ' + cog_name
        brief = brief_cog(cog)
        embeds = ChainedEmbed(title=cog_name, description=brief)
        embeds.set_thumbnail(url=self.client.user.avatar_url)
        for embed in embeds.to_list():
            await ctx.send(embed=embed)

    async def send_cog_list(self, ctx: Context):
        literal = literals('send_cog_list')
        states = list()
        count = len(self.client.cogs)
        message = None
        for i, cog in enumerate(sorted(self.client.cogs.items(),
                                       key=lambda item: get_cog(type(item[1]).__name__)['priority'])):
            name, cog = cog
            if isinstance(cog, CustomCog):
                name = cog.emoji + ' ' + name
            page_embed = ChainedEmbed(title=literal['title'], description=literal['description'])
            page_embed.set_thumbnail(url=self.client.user.avatar_url)
            page_embed.add_field(name=name, value=brief_cog(cog))
            page_embed.set_footer(text=literal['footer'] % (i + 1, count))
            if message is None:
                message = await ctx.send(embed=page_embed)
            states.append(InterfaceState(callback=message.edit, embed=page_embed))
        await attach_page_interface(self.client, message, states, user=ctx.author)

    async def send_command_help(self, ctx: Context, command: Command):
        literal = literals('send_command_help')
        command_name = command.qualified_name
        default_signature = get_command_default_signature(command)
        footer = get_command_signature(command)
        description = ''
        if command.help is not None:
            description = command.help + '\n'
        elif command.brief is not None:
            description = command.brief + '\n'
        description += f'`{default_signature}`'
        embeds = ChainedEmbed(title=get_constant('default_prefix') + command_name, description=description)
        embeds.set_thumbnail(url=self.client.user.avatar_url)
        if not command.enabled:
            embeds.add_field(name=literal['disabled_name'], value=literal['disabled_value'])
        if isinstance(command, CustomGroup):
            embeds.add_field(name=literal['subcommand'],
                             value=f'\n{brief_group(command)}\n')
        for check in command.checks:
            data = get_check(check.name)
            if data is None:
                continue
            embeds.add_field(name=f'{data["emoji"]} {data["name"]}', value=data["description"])
        if command.cog is not None:
            category = command.cog.qualified_name
            if isinstance(command.cog, CustomCog):
                category = command.cog.emoji + ' ' + category
            footer += ' · ' + category
        embeds.set_footer(text=footer)
        for embed in embeds.to_list():
            await ctx.send(embed=embed)
Esempio n. 10
0
class DeckCog(CustomCog, name=get_cog('DeckCog')['name']):
    """
    슈텔로 데크의 운영을 위한 기능을 포함합니다.
    """
    def __init__(self, client: Bot):
        super().__init__(client)
        self.client: Bot = client
        self.deck_handler: DeckHandler = DeckHandler(client)

    async def get_deck_embed(self,
                             deck: Deck,
                             brief: bool = True) -> ChainedEmbed:
        literal = literals('get_deck_embed')
        deck_embed = ChainedEmbed(title=literal['title'] % deck.name,
                                  description=deck.topic)
        deck_role = discord.utils.get(await
                                      self.deck_handler.guild.fetch_roles(),
                                      name=deck.name)
        deck_members = list()
        async for member in self.deck_handler.guild.fetch_members():
            if deck_role in member.roles:
                deck_members.append(str(member))
        deck_embed.set_thumbnail(url=deck.manager.avatar_url)
        deck_embed.add_field(name=literal['manager'], value=str(deck.manager))
        if deck.public:
            deck_embed.add_field(name=literal['public_name'],
                                 value=literal['public_value'])
        if deck.nsfw:
            deck_embed.add_field(name=literal['nsfw_name'],
                                 value=literal['nsfw_value'])
        if deck.auto:
            deck_embed.add_field(name=literal['auto_name'],
                                 value=literal['auto_value'])
        if deck.lock:
            deck_embed.add_field(name=literal['lock_name'],
                                 value=literal['lock_value'])
        if deck.pending:
            deck_embed.add_field(name=literal['pending'] % len(deck.pending),
                                 value=' '.join(
                                     [str(member) for member in deck.pending]))
        if not brief:
            if deck_members:
                deck_embed.add_field(name=literal['members'] %
                                     len(deck_members),
                                     value='\n'.join(deck_members),
                                     inline=True)
            channels = list()
            for channel in deck.category_channel.channels:
                channels.append(
                    (literal['voice'] if isinstance(channel, VoiceChannel
                                                    ) else '') +
                    (channel.name if channel != deck.default_channel else
                     f'**__{channel.name}__**'))
            deck_embed.add_field(name=literal['channels'] %
                                 len(deck.category_channel.channels),
                                 value='\n'.join(channels),
                                 inline=True)
        deck_embed.set_footer(text=literal['id'] % deck.id)
        return deck_embed

    async def accept_joining(self, ctx: Context, deck: Deck, *members: Member):
        check_deck_manager(deck, ctx.author)
        literal = literals('accept_joining')

        async def accept_joining_(member: Member):
            await member.add_roles(deck.role)
            deck.pending.remove(member)

        pending = [member for member in members if member in deck.pending]
        if not pending:
            raise BadArgument('no pending found')
        tasks = [accept_joining_(member) for member in pending]
        if tasks:
            message = await ctx.send(literal['start'] % len(tasks))
            done, yet = await asyncio.wait(tasks,
                                           return_when=asyncio.FIRST_EXCEPTION)
            for coro in done:
                if (e := coro.exception()) is not None:
                    await self.deck_handler.fetch_deck(deck.default_channel)
                    raise e
            await self.deck_handler.update_deck(deck)
            await message.edit(content=literal['done'] %
                               (' '.join([str(member)
                                          for member in pending]), deck.name))