Exemple #1
0
 def render_state_0(self):
     other = self.other
     text = [
         'Type "new" to show this message up again.'
         'Type "A-J" "1-10" for coordinate.'
         'And "1-3" "1-3" for ship placement'
         'It always places the ship right-down from the source coordinate'
             ]
     text.extend(render_map(self.data, SHIP_VALUES))
     embed = Embed('', '\n'.join(text), 0x010101)
     embed.add_author(other.user.avatar_url_as(size=64), f'vs.: {other.user.full_name}')
     
     text.clear()
     if sum(self.ships_left):
         sub_text = []
         amount = self.ships_left[1]
         if amount:
             sub_text.append(f'{amount} size 1x3 ship left')
         amount = self.ships_left[2]
         if amount:
             sub_text.append(f'{amount} size 1x4 ship left')
         amount = self.ships_left[3]
         if amount:
             sub_text.append(f'{amount} size 2x2 ship left')
         text.append(', '.join(sub_text))
         text.append(' ship is left to place. ')
     text.append(self.text)
     embed.add_footer(''.join(text))
     return embed
Exemple #2
0
    def create_page(self, index):
        end = index * 10
        start = end - 9
        if end > len(self.source.history):
            end = len(self.source.history)

        shard = []
        embed = Embed('Statistics', f'{start} - {end}', color=KANAKO_COLOR)

        add_options = self.source.possibilities

        for question_index, element in enumerate(
                self.source.history[start - 1:end], start):
            shard.append('```diff')
            if add_options:
                shard.append('\n')
                shard.append(', '.join([
                    f'{index}. : {option}'
                    for index, option in enumerate(element.options, 1)
                ]))
            for user_index, user in enumerate(self.source.users):
                value, time = element.answers[user_index]
                shard.append(
                    f'\n{"+" if element.answer==value else "-"} {user:f} : {value} ( {time:.2f} s )'
                )
            shard.append('\n```')
            embed.add_field(
                f'{question_index}.: {element.question} - {element.answer}',
                ''.join(shard))
            shard.clear()

        embed.add_footer(f'Page {index+1} / {len(self.cache)}')

        self.cache[index] = embed
        return embed
Exemple #3
0
    def render_state_1(self):
        other = self.other
        text = []
        if self.state:
            text.append('**It is your turn!**')
        else:
            text.append('**It is your opponent\'s turn!**')
        
        text.append(
            'Type "new" to show this message up again.'
            'Type "A-J" "1-10" to torpedo a ship.'
            'If you hit your opponent, then it is your turn again.',)

        if self.page:
            text.append('**Your opponents ship:**')
            text.extend(render_map(other.data, HIDDEN_VALUES))
            footer = f'Your opponent has {sum(other.ships_left)} ships left on {len(other.ship_positions)} tiles. {self.text}'
        else:
            text.append('**Your ships:**')
            text.extend(render_map(self.data, SHIP_VALUES))
            footer = f'You have {sum(self.ships_left)} ships left on {len(self.ship_positions)} tiles. {self.text}'

        embed = Embed('', '\n'.join(text), 0x010101)
        embed.add_author(other.user.avatar_url_as(size=64), f'vs.: {other.user:f}')
        embed.add_footer(footer)
        return embed
Exemple #4
0
 def createpage0(self, guild):
     embed = Embed(f'Roles of **{guild.name}**:',
                   '\n'.join([role.mention for role in self.roles]),
                   color=(guild.icon_hash & 0xFFFFFF if
                          (guild.icon_type is ICON_TYPE_NONE) else
                          (guild.id >> 22) & 0xFFFFFF))
     embed.add_footer(f'Page 1 /  {len(self.cache)}')
     self.cache[0] = embed
def embed_template(user, titles=None, descript=None):
    """
    Template for error embeds
    """
    embeded = Embed(color=RED,
                    title=titles,
                    description=descript,
                    timestamp=datetime.utcnow())
    embeded.add_footer(user.id)
    embeded.add_author(user.avatar_url, user.full_name)

    return embeded
Exemple #6
0
 def render_state_2(self):
     other = self.other
     text = []
     if self.state:
         text.append('**You won!**\n')
     else:
         text.append('**You lost :cry:**\n')
         
     if self.page:
         text.append('Your opponent\'s ships:')
         text.extend(render_map(other.data, SHIP_VALUES))
     else:
         text.append('Your ships:')
         text.extend(render_map(self.data, SHIP_VALUES))
     
     embed = Embed('', '\n'.join(text), 0x010101)
     embed.add_author(other.user.avatar_url_as(size=64), f'vs.: {other.user:f}')
     embed.add_footer(self.text)
     return embed
Exemple #7
0
    async def command(client, message):
        chunks = []
        actual_chunk = []
        index = 0
        limit = len(CHESUTO_BGM_TRACKS_SORTED)
        collected = 0
        while True:
            if index == limit:
                break

            actual = CHESUTO_BGM_TRACKS_SORTED[index].display_name
            index += 1
            actual_chunk.append(repr(index))
            actual_chunk.append('.: ')
            actual_chunk.append(actual)
            actual_chunk.append('\n')

            collected += 1
            if collected == 20:
                del actual_chunk[-1]
                chunks.append(''.join(actual_chunk))
                actual_chunk.clear()
                collected = 0

        if collected:
            chunks.append(''.join(actual_chunk))

        actual_chunk = None

        embeds = []

        limit = len(chunks)
        index = 0
        while index < limit:
            embed = Embed('Chesuto BGMs:',
                          color=FLAN_HELP_COLOR,
                          description=chunks[index])
            index += 1
            embed.add_footer(f'page {index}/{limit}')
            embeds.append(embed)

        await Pagination(client, message.channel, embeds)
Exemple #8
0
    def create_page(self, index):
        role = self.roles[index - 1]
        embed = Embed(role.name,
                      '\n'.join([
                          f'id : {role.id!r}',
                          f'color : {role.color.as_html}',
                          f'permission number : {role.permissions:d}',
                          f'managed : {role.managed}',
                          f'separated : {role.separated}',
                          f'mentionable : {role.mentionable}',
                          '\nPermissions:\n```diff',
                          *(f'{"+" if value else "-"}{key.replace("_", "-")}'
                            for key, value in role.permissions.items()),
                          '```',
                      ]),
                      color=role.color)
        embed.add_footer(f'Page {index+1} /  {len(self.roles)+1}')

        self.cache[index] = embed
        return embed
Exemple #9
0
def render_showcase(name, map_):
    result = []
    element_index = 0
    element_limit = len(map_)

    page_index = 1
    page_limit = (element_limit + 29) // 30

    field_text = []

    while True:
        if page_index > page_limit:
            break

        embed = Embed(name.capitalize(), '', KANAKO_COLOR)
        embed.add_footer(f'page {page_index} / {page_limit}')

        for _ in range(((element_limit % 30) + 9) //
                       10 if page_index == page_limit else 3):
            field_index_limit = element_index + 10
            if field_index_limit > element_limit:
                field_index_limit = element_limit

            while element_index < field_index_limit:
                element = map_[element_index]
                element_index += 1
                field_text.append(
                    f'{element_index}.: **{element[0]} - {element[1]}**')

            embed.add_field(f'{element_index-9} - {element_index}',
                            '\n'.join(field_text),
                            inline=True)
            field_text.clear()

        result.append(embed)
        page_index += 1

    return result
Exemple #10
0
async def buy(client, event,
        item : ([(item.name, item.id) for item in BUYABLE], 'Select the item to buy nya!'),
        amount : (int, 'How much items would you want to buy?'),
            ):
    """Buy?"""
    try:
        item = ITEMS[item]
    except KeyError:
        abort('Item not available.')
    
    permissions = event.channel.cached_permissions_for(client)
    if (not permissions.can_send_messages) or (not permissions.can_add_reactions):
        abort('I need `send messages` and `add reactions` permissions to execute the command.')
    
    yield
    
    user = event.user
    async with DB_ENGINE.connect() as connector:
        response = await connector.execute(
            select([currency_model.total_love]). \
                where(currency_model.user_id==user.id))
        
        results = await response.fetchall()
        if results:
            total_love = results[0]
        else:
            total_love = 0
    
    embed = Embed('Confirm buying',
        f'Selected item: {item.emoji:e} **{item.name}**\n'
        f'Amount: **{amount}**\n'
        f'\n'
        f'Price: {calculate_buy_cost(item.market_cost, amount)} {EMOJI__HEART_CURRENCY:e}\n'
        f'Budget: {total_love} {EMOJI__HEART_CURRENCY:e}'
    )
    
    embed.add_author(user.avaar_url, user.full_name)
    embed.add_footer('The prices of context of demand and supply.')
    
    message = await client.message_create(event.channel, embed=embed)
    await client.reaction_add(message, item.emoji)
    await client.reaction_add(message, CONFIRM_NAH)
    
    try:
        event = await wait_for_reaction(client, message, partial_func(check_confirm_emoji, item.emoji), 300.0)
    except TimeoutError:
        return
    
    if event.emoji is CONFIRM_NAH:
        embed.title = 'Buying cancelled'
    else:
        user = event.user
        async with DB_ENGINE.connect() as connector:
            response = await connector.execute(
                select([currency_model.total_love, currency_model.total_allocated]). \
                    where(currency_model.user_id==user.id))
            
            results = await response.fetchall()
            if results:
                total_love, total_allocated = results[0]
            else:
                total_love = total_allocated = 0
            
            if total_love == 0:
                amount = cost = 0
            else:
                amount, cost = calculate_buyable_and_cost(item.market_cost, amount, total_love-total_allocated)
                
                item.market_cost += amount
            
            if cost == 0:
                new_love = total_love
            else:
                new_love = total_love-cost
                await connector.execute(update(currency_model.user_id==user.id). \
                    values(total_love = new_love))
                
                response = await connector.execute(select([item_model.id, item_model.amount]). \
                    where(item_model.user_id==user.id).where(item_model.type==item.id))
                
                results = await response.fetchall()
                if results:
                    row_id, actual_amount = results[0]
                    new_amount = actual_amount+amount
                    to_execute = ITEM_TABLE.update().values(
                        amount=new_amount
                            ).where(item_model.id==row_id)
                else:
                    to_execute = ITEM_TABLE.insert().values(
                        user_id = user.id,
                        amount  = amount,
                        type    = item.id
                    )
                
                await connector.execute(to_execute)
        
        embed.title = 'Buying confirmed'
        embed.description = (
            f'Selected item: {item.emoji:e} **{item.name}**\n'
            f'Bought mount: **{amount}**\n'
            f'\n'
            f'Hearts: {total_love} {EMOJI__HEART_CURRENCY:e} -> {new_love} {EMOJI__HEART_CURRENCY:e}'
        )
    
    await client.message_edit(message, embed=embed)
Exemple #11
0
    def create_page_0(self):
        user_count = len(self.source.users)
        win_counts = [0 for _ in range(user_count)]
        lose_counts = win_counts.copy()
        win_firsts = win_counts.copy()
        lose_firsts = win_counts.copy()
        win_times = [[] for _ in range(user_count)]
        lose_times = [[] for _ in range(user_count)]

        for element in self.source.history:
            answer = element.answer
            answers = element.answers
            first_time = CIRCLE_TIME
            first_index = 0
            first_won = True
            for index in range(user_count):
                value, time = answers[index]
                if value == answer:
                    win_counts[index] += 1
                    win_times[index].append(time)
                    if time < first_time:
                        first_time = time
                        first_index = index
                        first_won = True
                else:
                    lose_counts[index] += 1
                    lose_times[index].append(time)
                    if time < first_time:
                        first_time = time
                        first_index = index
                        first_won = False

            if first_time != CIRCLE_TIME:
                if first_won:
                    win_firsts[first_index] += 1
                else:
                    lose_firsts[first_index] += 1

        win_medians = [
            value[len(value) // 2] if value else CIRCLE_TIME
            for value in win_times
        ]
        lose_medians = [
            value[len(value) // 2] if value else CIRCLE_TIME
            for value in lose_times
        ]

        embed = Embed('Statistics', color=KANAKO_COLOR)

        for index, user in enumerate(self.source.users):
            win_count = win_counts[index]
            lose_count = lose_counts[index]
            win_median = win_medians[index]
            lose_median = lose_medians[index]
            win_first = win_firsts[index]
            lose_first = lose_firsts[index]

            total = float(win_count)
            total += (((2**.5) - 1.) -
                      ((((CIRCLE_TIME + win_median) / CIRCLE_TIME)**.5) -
                       1.)) * win_count
            total += win_first / 5.
            total -= (((2**.5) - 1.) -
                      ((((CIRCLE_TIME + lose_median) / CIRCLE_TIME)**.5) -
                       1.)) * lose_count * 2.
            total -= lose_first / 2.5

            embed.add_field(
                f'{user:f} :', f'Correct answers : {win_count}\n'
                f'Bad answers : {lose_count}\n'
                f'Good answer time median : {win_median:.2f} s\n'
                f'Bad answer time median : {lose_median:.2f} s\n'
                f'Answered first: {win_first} GOOD / {lose_first} BAD\n'
                f'Rated : {total:.2f}')

        embed.add_footer(f'Page 1 /  {len(self.cache)}')

        self.cache[0] = embed
Exemple #12
0
async def receive_sync(client, partner):
    try:
        async with SYNC_LOCK:
            # some delay is needed or Koishi might answer too fast.
            await sleep(0.4, KOKORO)
            await client.message_create(CHANNEL__SYSTEM__SYNC,
                                        REQUEST_APPROVED)

            while True:
                try:
                    message = await wait_for_message(client,
                                                     CHANNEL__SYSTEM__SYNC,
                                                     check_any(partner), 60.)
                except TimeoutError:
                    sys.stderr.write('Sync request failed, timeout.\n')
                    return

                content = message.content
                if content == SYNC_DONE:
                    break

                path_full, file_name = content.split(':')
                path_parts = path_full.split('.')
                if not path_parts:
                    sys.stderr.write(
                        'Empty content received, aborting sync.\n')
                    return

                source_path = path_parts[0]
                try:
                    source_path = RELATIONS[source_path]
                except KeyError:
                    sys.stderr.write(
                        f'Source path not found: {source_path!r}, aborting sync.\n'
                    )
                    return

                for path_part in path_parts[1:]:
                    source_path = join(source_path, path_part)
                    if not exists(source_path):
                        make_dir(source_path)

                attachments = message.attachments
                if (attachments is not None):
                    attachment = attachments[0]
                    binary = await client.download_attachment(attachment)
                    if binary is None:
                        sys.stdout.write(
                            f'{attachment!r} yielded empty binary.\n')
                        continue

                    source_path = join(source_path, file_name)

                    with (await AsyncIO(source_path, 'wb')) as file:
                        await file.write(binary)

                # Wait some. It can happen that we send this message, before the other side gets it's answer.
                await client.message_create(CHANNEL__SYSTEM__SYNC, RECEIVED)
    except BaseException as err:
        with StringIO() as buffer:
            await KOKORO.render_exc_async(err, ['```'], file=buffer)

            buffer.seek(0)
            lines = buffer.readlines()

        pages = []

        page_length = 0
        page_contents = []

        index = 0
        limit = len(lines)

        while True:
            if index == limit:
                embed = Embed(description=''.join(page_contents))
                pages.append(embed)
                page_contents = None
                break

            line = lines[index]
            index = index + 1

            line_length = len(line)
            # long line check, should not happen
            if line_length > 500:
                line = line[:500] + '...\n'
                line_length = 504

            if page_length + line_length > 1997:
                if index == limit:
                    # If we are at the last element, we don't need to shard up,
                    # because the last element is always '```'
                    page_contents.append(line)
                    embed = Embed(description=''.join(page_contents))
                    pages.append(embed)
                    page_contents = None
                    break

                page_contents.append('```')
                embed = Embed(description=''.join(page_contents))
                pages.append(embed)

                page_contents.clear()
                page_contents.append('```py\n')
                page_contents.append(line)

                page_length = 6 + line_length
                continue

            page_contents.append(line)
            page_length += line_length
            continue

        limit = len(pages)
        index = 0
        while index < limit:
            embed = pages[index]
            index += 1
            embed.add_footer(f'page {index}/{limit}')

        await Pagination(client, message.channel, pages)
Exemple #13
0
async def command_error_handler(ctx, exception):
    if ctx.guild is not GUILD__NEKO_DUNGEON:
        return False
    
    with StringIO() as buffer:
        await KOKORO.render_exc_async(exception,[
            ctx.client.full_name,
            ' ignores an occurred exception at command ',
            repr(ctx.command),
            '\n\nMessage details:\nGuild: ',
            repr(ctx.guild),
            '\nChannel: ',
            repr(ctx.channel),
            '\nAuthor: ',
            ctx.author.full_name,
            ' (',
            repr(ctx.author.id),
            ')\nContent: ',
            repr(ctx.content),
            '\n```py\n'], '```', file=buffer)
        
        buffer.seek(0)
        lines = buffer.readlines()
    
    pages = []
    
    page_length = 0
    page_contents = []
    
    index = 0
    limit = len(lines)
    
    while True:
        if index == limit:
            embed = Embed(description=''.join(page_contents))
            pages.append(embed)
            page_contents = None
            break
        
        line = lines[index]
        index = index+1
        
        line_length = len(line)
        # long line check, should not happen
        if line_length > 500:
            line = line[:500]+'...\n'
            line_length = 504
        
        if page_length+line_length > 1997:
            if index == limit:
                # If we are at the last element, we don\'t need to shard up,
                # because the last element is always '```'
                page_contents.append(line)
                embed = Embed(description=''.join(page_contents))
                pages.append(embed)
                page_contents = None
                break
            
            page_contents.append('```')
            embed = Embed(description=''.join(page_contents))
            pages.append(embed)
            
            page_contents.clear()
            page_contents.append('```py\n')
            page_contents.append(line)
            
            page_length = 6+line_length
            continue
        
        page_contents.append(line)
        page_length += line_length
        continue
    
    limit = len(pages)
    index = 0
    while index < limit:
        embed = pages[index]
        index += 1
        embed.add_footer(f'page {index}/{limit}')
    
    await Pagination(ctx.client, ctx.channel, pages)
    return True
Exemple #14
0
async def add_bot_channel_name(client, message, weight: int, name):
    """
    Adds the given channel name to the bot channel names.
    
    When adding a command please also define weight and not only name as: `weight | name`
    """
    if EDIT_LOCK.locked():
        await Closer(
            client, message.channel,
            Embed('Ohoho', 'A bot channel editing is already taking place.'))
        return

    async with EDIT_LOCK:
        name = escape_name(name)
        if not 2 <= len(name) <= 100:
            await Closer(client, message.channell,
                         Embed(f'Too long or short name', name))
            return

        names = await read_channels()
        close_matches = get_close_matches(
            name, [describer.name for describer in names], n=1, cutoff=0.8)
        if not close_matches:
            overwrite = False
            embed = Embed(
                'Add bot channel name',
                f'Would you like to add a channel name:\n{name}\nWith weight of {weight}.'
            )
        elif close_matches[0] == name:
            overwrite = True
            embed = Embed(
                'Add bot channel name',
                f'Would you like to overwrite the following bot channel name:\n'
                f'{name}\n'
                f'To weight of {weight}.')
        else:
            overwrite = False
            embed = Embed(
                'Add bot channel name',
                f'There is a familiar channel name already added: {close_matches[0]}\n'
                f'Would you like to overwrite the following bot channel name:\n'
                f'{name}\n'
                f'To weight of {weight}.')

        message = await client.message_create(message.channel,
                                              embed=embed,
                                              components=ADD_COMPONENTS)

        try:
            event = await wait_for_component_interaction(
                message, timeout=300., check=check_staff_role)
        except TimeoutError:
            event = None
            cancelled = False
        else:
            cancelled = (event.interaction == ADD_BUTTON_CANCEL)

        if cancelled:
            footer = 'Name adding cancelled.'
        else:
            if overwrite:
                for describer in names:
                    if describer.name == describer:
                        describer.weight = weight

                footer = 'Name overwritten successfully.'
            else:
                describer = ChannelNameDescriber.from_name_and_weight(
                    name, weight)
                names.append(describer)
                footer = 'Name added successfully.'
            await write_channels(names)

        embed.add_footer(footer)

        if event is None:
            await client.message_edit(message, embed=embed, components=None)
        else:
            await client.interaction_component_message_edit(event,
                                                            embed=embed,
                                                            components=None)
Exemple #15
0
async def set_bgm_name(client, message, content):
    bgm = get_bgm(content)
    
    if bgm is None:
        await client.message_create(message.channel, embed=Embed(None, '*Nothing found.*', CHESUTO_COLOR))
        return
    
    embed = Embed(f'Renaming: *{bgm.display_name}*', bgm.description, color=CHESUTO_COLOR) \
        .add_footer('Your next message will be captured as the new display name of the bgm.')
    
    message = await client.message_create(message.channel, embed=embed)
    
    try:
        response = await wait_for_message(client, message.channel, check_has_cards_role, 300.0)
    except TimeoutError:
        content = None
        footer = 'Timeout occurred.'
    else:
        content = response.content
        if len(content) > 100:
            content = None
            footer = '*That\'s pretty long*. That\'s what she said. Please give a display name with maximum of 100 ' \
                     'characters.'
        else:
            footer = f'Are you sure to set the bgm\'s display name as: {content!r}?'
    
    embed.add_footer(footer)
    await client.message_edit(message, embed=embed)
    if content is None:
        return
    
    if message.channel.cached_permissions_for(client).can_manage_messages:
        try:
            await client.message_delete(response)
        except BaseException as err:
            if isinstance(err, ConnectionError):
                # no internet
                return
            
            if isinstance(err, DiscordException):
                if err.code in (
                        ERROR_CODES.missing_access, # client removed
                        ERROR_CODES.unknown_message, # message deleted
                        ERROR_CODES.unknown_channel, # channel deleted
                        ERROR_CODES.missing_permissions, # permissions changed meanwhile
                            ):
                    return
            
            raise
    
    for emoji_ in SET_BGM_NAME_EMOJI_EMOJIS:
        await client.reaction_add(message, emoji_)
    
    try:
        event = await wait_for_reaction(client, message, check_reaction_cards_role, 300.)
    except TimeoutError:
        emoji_ = None
    else:
        emoji_ = event.emoji
    
        if message.channel.cached_permissions_for(client).can_manage_messages:
            try:
                await client.reaction_clear(message)
            except BaseException as err:
                if isinstance(err, ConnectionError):
                    # no internet
                    return
                
                if isinstance(err, DiscordException):
                    if err.code in (
                            ERROR_CODES.missing_access, # client removed
                            ERROR_CODES.unknown_message, # message deleted
                            ERROR_CODES.unknown_channel, # channel deleted
                            ERROR_CODES.missing_permissions, # permissions changed meanwhile
                                ):
                        return
                
                raise
    
    if emoji_ is None:
        footer = 'Timeout occurred.'
    elif emoji_ is SET_BGM_NAME_EMOJI_OK:
        BGM_NAMES[bgm.source_name] = content
        await write_bgm_names()
        bgm.display_name = content
        footer = 'Rename done.'
    else:
        footer = 'Rename cancelled.'
    
    embed.add_footer(footer)
    await client.message_edit(message, embed=embed)
Exemple #16
0
 async def command(client, message):
     guild = message.channel.guild
     if (guild is None):
         return
     
     if not guild.cached_permissions_for(client).can_ban_users:
         await client.message_create(message.channel, embed = Embed(
             description = 'I have no permissions at the guild.',
             color=ADMINISTRATION_COLOR))
         return
     
     ban_data = await client.guild_bans(guild)
     
     if not ban_data:
         await client.message_create(message.channel, 'None')
         return
     
     embeds = []
     maintext = f'Guild bans for {guild.name} {guild.id}:'
     limit = len(ban_data)
     index = 0
 
     while True:
         field_count = 0
         embed_length = len(maintext)
         embed = Embed(title=maintext)
         embeds.append(embed)
         while True:
             user, reason = ban_data[index]
             if reason is None:
                 reason = 'Not defined.'
             name = f'{user:f} {user.id}'
             embed_length += len(reason)+len(name)
             if embed_length > 5900:
                 break
             embed.add_field(name,reason)
             field_count += 1
             if field_count == 25:
                 break
             index +=1
             if index == limit:
                 break
         if index == limit:
             break
     
     index = 0
     field_count = 0
     embed_ln = len(embeds)
     result = []
     while True:
         embed = embeds[index]
         index +=1
         embed.add_footer(f'Page: {index}/{embed_ln}. Bans {field_count+1}-{field_count+len(embed.fields)}/{limit}')
         field_count += len(embed.fields)
         
         result.append(embed)
         
         if index == embed_ln:
             break
     
     await Pagination(client, message.channel, result)
Exemple #17
0
async def yeet(
    client,
    event,
    user: ('user', 'Select the user to yeet!'),
    reason: ('str', 'Any reason why you would want to yeet?') = None,
    delete_message_days: (range(8), 'Delete previous messages?') = 0,
    notify_user: ('bool',
                  'Whether the user should get DM about the ban.') = True,
):
    """Yeets someone out of the guild. You must have ban users permission."""
    # Check permissions
    guild = event.guild
    if guild is None:
        abort('Guild only command.')

    if guild not in client.guild_profiles:
        abort('I must be in the guild to do this.')

    if not event.user_permissions.can_ban_users:
        abort('You must have yeet users permission to use this command.')

    if not guild.cached_permissions_for(client).can_ban_users:
        abort(f'{client.name_at(guild)} cannot yeet in the guild.')

    if not event.user.has_higher_role_than_at(user, guild):
        abort('You must have higher role than the person to be yeeted.')

    if not client.has_higher_role_than_at(user, guild):
        abort('I must have higher role than the person to yeeted.')

    # Ask, whether the user should be banned.
    if (reason is not None) and (not reason):
        reason = None

    embed = Embed('Confirmation', f'Are you sure to yeet {user.mention} from {guild.name}?'). \
        add_field('Delete message day', str(delete_message_days), inline=True). \
        add_field('Notify user', 'true' if notify_user else 'false', inline=True). \
        add_field('Reason', '*No reason provided.*' if reason is None else reason)

    message = yield InteractionResponse(embed=embed,
                                        components=BAN_COMPONENTS,
                                        allowed_mentions=None)

    # Wait for user input

    try:
        component_interaction = await wait_for_component_interaction(
            message,
            timeout=300.0,
            check=partial_func(check_banner, event.user))

    except TimeoutError:
        embed.title = 'Timeout'
        embed.description = f'{user.mention} was not yeeted from {guild.name}.'

        # Edit the source message with the source interaction
        yield InteractionResponse(embed=embed,
                                  components=None,
                                  allowed_mentions=None,
                                  message=message)
        return

    if component_interaction.interaction == BAN_BUTTON_CANCEL:
        embed.title = 'Cancelled'
        embed.description = f'{user.mention} was not yeeted from {guild.name}.'

        # Edit the source message with the component interaction
        yield InteractionResponse(embed=embed,
                                  components=None,
                                  allowed_mentions=None,
                                  event=component_interaction)
        return

    # Acknowledge the event
    await client.interaction_component_acknowledge(component_interaction)

    # Try to notify the user. Ignore bot notifications.
    if notify_user:
        if user.is_bot:
            notify_note = None
        else:

            try:
                channel = await client.channel_private_create(user)
            except BaseException as err:
                if isinstance(err, ConnectionError):
                    return  # We cannot help no internet

                raise

            embed = Embed('Yeeted', f'You were yeeted from {guild.name}.'). \
                add_field('Reason', '*No reason provided.*' if reason is None else reason)

            try:
                await client.message_create(channel, embed=embed)
            except BaseException as err:
                if isinstance(err, ConnectionError):
                    return  # We cannot help no internet

                elif isinstance(err, DiscordException) and (
                        err.code == ERROR_CODES.cannot_message_user):
                    notify_note = 'Notification cannot be delivered: user has DM disabled.'
                else:
                    raise
            else:
                notify_note = None
    else:
        notify_note = None

    if reason is None:
        caller = event.user
        reason = f'Requested by: {caller.full_name} [{caller.id}]'

    await client.guild_ban_add(guild,
                               user,
                               delete_message_days=delete_message_days,
                               reason=reason)

    embed = Embed('Hecatia yeah!', f'{user.full_name} has been yeeted.')
    if (notify_note is not None):
        embed.add_footer(notify_note)

    # Edit the source message
    yield InteractionResponse(embed=embed, message=message, components=None)
Exemple #18
0
async def bans(client, event):
    """Lists the guild's bans."""
    guild = event.guild
    if guild is None:
        abort('Guild only command')

    if guild not in client.guild_profiles:
        abort('I must be in the guild to execute the command.')

    if not event.user_permissions.can_ban_users:
        abort('You must have `ban users` permission to invoke this command.')

    if not guild.cached_permissions_for(client).can_ban_users:
        abort(
            'I must have `ban users` permission invite to execute this command.'
        )

    yield

    ban_data = await client.guild_ban_get_all(guild)

    embeds = []
    main_text = f'Guild bans for {guild.name} {guild.id}:'
    limit = len(ban_data)
    if limit:
        index = 0

        while True:
            field_count = 0
            embed_length = len(main_text)
            embed = Embed(main_text)
            embeds.append(embed)

            while True:
                user, reason = ban_data[index]
                if reason is None:
                    reason = 'Not defined.'
                name = f'{user:f} {user.id}'
                embed_length += len(reason) + len(name)
                if embed_length > 5900:
                    break
                embed.add_field(name, reason)
                field_count += 1
                if field_count == 25:
                    break
                index += 1
                if index == limit:
                    break
            if index == limit:
                break
    else:
        embed = Embed(main_text, '*none*')
        embeds.append(embed)

    index = 0
    field_count = 0
    embed_ln = len(embeds)
    result = []
    while True:
        embed = embeds[index]
        index += 1
        embed.add_footer(
            f'Page: {index}/{embed_ln}. Bans {field_count+1}-{field_count+len(embed.fields)}/{limit}'
        )
        field_count += len(embed.fields)

        result.append(embed)

        if index == embed_ln:
            break

    await Pagination(client, event, result, check=bans_pagination_check)
Exemple #19
0
 async def command(client, message, emoji:Emoji, *roles:'role'):
     permissions = message.channel.cached_permissions_for(client)
     if (not permissions.can_manage_emojis) or (not permissions.can_add_reactions):
         await client.message_create(message.channel,
             embed = Embed(description='I have no permissions to edit emojis, or to add reactions.'))
         return
     
     roles = sorted(roles)
     roles_ = emoji.roles
     
     embed = Embed().add_author(emoji.url, emoji.name)
     
     if (roles_ is None) or (not roles_):
         role_text = '*none*'
     else:
         role_text = ', '.join([role.mention for role in roles_])
     
     embed.add_field('Roles before:', role_text)
     
     if (not roles):
         role_text = '*none*'
     else:
         role_text = ', '.join([role.mention for role in roles])
     
     embed.add_field('Roles after:', role_text)
     
     message = await client.message_create(message.channel, embed=embed)
     for emoji_ in ROLE_EMOJI_EMOJIS:
         await client.reaction_add(message, emoji_)
     
     try:
         event = await wait_for_reaction(client, message, _role_emoji_emoji_checker(message.guild), 300.)
     except TimeoutError:
         emoji_ = ROLE_EMOJI_CANCEL
     else:
         emoji_ = event.emoji
     
     if message.channel.cached_permissions_for(client).can_manage_messages:
         try:
             await client.reaction_clear(message)
         except BaseException as err:
             if isinstance(err, ConnectionError):
                 # no internet
                 return
             
             if isinstance(err, DiscordException):
                 if err.code in (
                         ERROR_CODES.invalid_access, # client removed
                         ERROR_CODES.unknown_message, # message deleted
                         ERROR_CODES.invalid_permissions, # permissions changed meanwhile
                             ):
                     return
             
             raise
     
     if emoji_ is ROLE_EMOJI_OK:
         try:
             await client.emoji_edit(emoji, roles=roles)
         except DiscordException as err:
             footer = repr(err)
         else:
             footer = 'Emoji edited succesfully.'
     
     elif emoji_ is ROLE_EMOJI_CANCEL:
         footer = 'Emoji edit cancelled'
     
     else: #should not happen
         return
     
     embed.add_footer(footer)
     
     await client.message_edit(message, embed=embed)
Exemple #20
0
    async def run(self):
        client = self.client
        channel = self.channel
        answers = self.answers
        buffer = ReuBytesIO()
        embed = Embed(color=KANAKO_COLOR)
        embed.add_image('attachment://guessme.png')
        embed.add_footer('')
        time_till_notify = CIRCLE_TIME - 10

        for index, (question, answer) in enumerate(self.map, 1):
            embed.footer.text = f'{index} / {len(self.map)}'
            if self.possibilities:
                self.options = self.generate_options(answer)
                embed.description = '\n'.join([
                    f'**{index}.: {value}**'
                    for index, value in enumerate(self.options, 1)
                ])

            try:
                await client.message_create(channel,
                                            embed=embed,
                                            file=('guessme.png',
                                                  draw(buffer, question)))
            except DiscordException:
                return self.cancel()

            circle_start = LOOP_TIME()
            waiter = sleep(time_till_notify, client.loop)
            self.waiter = waiter
            try:
                await waiter
                Task(
                    self.send_or_except(
                        Embed(
                            'Hurry! Only 10 seconds left!', '\n'.join([
                                user.full_name for user in self.users
                                if user.id not in answers
                            ]), KANAKO_COLOR)), client.loop)
                waiter = sleep(time_till_notify, client.loop)
                self.waiter = waiter
                await waiter
                self.calculate_leavers()
            except CancelledError:
                pass
            except InterruptedError as err:
                return self.cancel()

            element = history_element()
            element.question = question
            element.answer = answer
            element.options = self.options
            element.answers = [(value[0], value[1] - circle_start)
                               for value in (answers[user.id]
                                             for user in self.users)]
            self.history.append(element)

            answers.clear()

            embed.title = f'Last answer: {answer}'

        await self.send_or_except(Embed(embed.title, '', KANAKO_COLOR))

        del ACTIVE_GAMES[channel.id]
        client.events.message_create.remove(self.channel, self)
        self.running = False

        await game_statistics(self)