CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-nextcord

A Python wrapper for the Discord API forked from discord.py

Pending
Overview
Eval results
Files

utilities.mddocs/

Nextcord Utilities

Utility functions, helper classes, and convenience methods for common Discord bot operations, providing powerful tools for bot development.

Core Utilities

Essential utility functions for searching, filtering, and manipulating Discord objects.

Search and Filter Functions { .api }

import nextcord
from nextcord import utils
from typing import Any, Callable, Iterable, Optional, TypeVar, Union, List
import re

T = TypeVar('T')

def find(predicate: Callable[[T], Any], iterable: Iterable[T]) -> Optional[T]:
    """Find the first element in an iterable that matches the predicate.
    
    Parameters
    ----------
    predicate: Callable[[T], Any]
        A function that returns True for the desired element.
    iterable: Iterable[T]
        The iterable to search through.
    
    Returns
    -------
    Optional[T]
        The first matching element, or None if no match found.
    
    Examples
    --------
    # Find a member by name
    member = nextcord.utils.find(lambda m: m.name == 'Alice', guild.members)
    
    # Find a channel by name
    channel = nextcord.utils.find(lambda c: c.name == 'general', guild.channels)
    
    # Find a role with specific permissions
    admin_role = nextcord.utils.find(lambda r: r.permissions.administrator, guild.roles)
    """
    return next((item for item in iterable if predicate(item)), None)

def get(iterable: Iterable[T], **attrs) -> Optional[T]:
    """Get the first element that matches all the given attributes.
    
    Parameters
    ----------
    iterable: Iterable[T]
        The iterable to search through.
    **attrs
        Keyword arguments representing attributes to match.
    
    Returns
    -------
    Optional[T]
        The first matching element, or None if no match found.
    
    Examples
    --------
    # Get a member by name and discriminator
    member = nextcord.utils.get(guild.members, name='Alice', discriminator='1234')
    
    # Get a channel by name and type
    voice_channel = nextcord.utils.get(guild.channels, name='General', type=nextcord.ChannelType.voice)
    
    # Get a role by name
    role = nextcord.utils.get(guild.roles, name='Moderator')
    
    # Get a message by author and content
    message = nextcord.utils.get(channel.history(limit=100), author=user, content='Hello')
    """
    def predicate(item):
        return all(getattr(item, attr, None) == value for attr, value in attrs.items())
    
    return find(predicate, iterable)

# Advanced search functions
def search_members_by_name(
    guild: nextcord.Guild,
    query: str,
    limit: int = 10,
    case_sensitive: bool = False
) -> List[nextcord.Member]:
    """Search for members by name with fuzzy matching.
    
    Parameters
    ----------
    guild: nextcord.Guild
        The guild to search in.
    query: str
        The search query.
    limit: int
        Maximum number of results to return.
    case_sensitive: bool
        Whether the search should be case sensitive.
    
    Returns
    -------
    List[nextcord.Member]
        List of matching members, sorted by relevance.
    """
    if not case_sensitive:
        query = query.lower()
    
    exact_matches = []
    startswith_matches = []
    contains_matches = []
    
    for member in guild.members:
        name = member.display_name if not case_sensitive else member.display_name
        username = member.name.lower() if not case_sensitive else member.name
        
        if not case_sensitive:
            name = name.lower()
        
        # Exact match (highest priority)
        if name == query or username == query:
            exact_matches.append(member)
        # Starts with query (medium priority)
        elif name.startswith(query) or username.startswith(query):
            startswith_matches.append(member)
        # Contains query (lowest priority)
        elif query in name or query in username:
            contains_matches.append(member)
    
    # Combine results with priority order
    results = exact_matches + startswith_matches + contains_matches
    return results[:limit]

def filter_channels_by_permissions(
    channels: List[nextcord.abc.GuildChannel],
    member: nextcord.Member,
    **required_permissions
) -> List[nextcord.abc.GuildChannel]:
    """Filter channels by member permissions.
    
    Parameters
    ----------
    channels: List[nextcord.abc.GuildChannel]
        The channels to filter.
    member: nextcord.Member
        The member to check permissions for.
    **required_permissions
        The required permissions as keyword arguments.
    
    Returns
    -------
    List[nextcord.abc.GuildChannel]
        Channels where the member has all required permissions.
    """
    filtered_channels = []
    
    for channel in channels:
        member_perms = channel.permissions_for(member)
        
        # Check if member has all required permissions
        if all(getattr(member_perms, perm, False) == value for perm, value in required_permissions.items()):
            filtered_channels.append(channel)
    
    return filtered_channels

# Usage examples
async def utility_examples(guild: nextcord.Guild):
    """Examples of utility function usage."""
    
    # Find examples
    owner = nextcord.utils.find(lambda m: m.id == guild.owner_id, guild.members)
    general_channel = nextcord.utils.find(lambda c: 'general' in c.name.lower(), guild.text_channels)
    muted_role = nextcord.utils.find(lambda r: 'mute' in r.name.lower(), guild.roles)
    
    # Get examples
    member = nextcord.utils.get(guild.members, name='Alice')
    voice_channel = nextcord.utils.get(guild.channels, name='General', type=nextcord.ChannelType.voice)
    admin_role = nextcord.utils.get(guild.roles, permissions=nextcord.Permissions(administrator=True))
    
    # Advanced search examples
    search_results = search_members_by_name(guild, 'ali', limit=5, case_sensitive=False)
    
    # Filter channels by permissions
    readable_channels = filter_channels_by_permissions(
        guild.text_channels,
        member,
        read_messages=True,
        send_messages=True
    )
    
    return {
        'owner': owner,
        'general_channel': general_channel,
        'search_results': search_results,
        'readable_channels': readable_channels
    }

Time and Date Utilities { .api }

from datetime import datetime, timedelta, timezone
import time
from typing import Optional, Union

def utcnow() -> datetime:
    """Get the current UTC datetime.
    
    Returns
    -------
    datetime
        Current UTC datetime.
    """
    return datetime.now(timezone.utc)

def snowflake_time(snowflake_id: int) -> datetime:
    """Extract the creation time from a Discord snowflake ID.
    
    Parameters
    ----------
    snowflake_id: int
        The Discord snowflake ID.
    
    Returns
    -------
    datetime
        The creation time of the snowflake.
    """
    # Discord epoch (2015-01-01T00:00:00.000Z)
    discord_epoch = 1420070400000
    
    # Extract timestamp from snowflake
    timestamp = ((snowflake_id >> 22) + discord_epoch) / 1000
    
    return datetime.fromtimestamp(timestamp, tz=timezone.utc)

def format_dt(dt: datetime, format_type: str = 'f') -> str:
    """Format a datetime for Discord's timestamp formatting.
    
    Parameters
    ----------
    dt: datetime
        The datetime to format.
    format_type: str
        The Discord timestamp format type:
        - 't': Short time (16:20)
        - 'T': Long time (16:20:30)
        - 'd': Short date (20/04/2021)
        - 'D': Long date (20 April 2021)
        - 'f': Short date/time (20 April 2021 16:20)
        - 'F': Long date/time (Tuesday, 20 April 2021 16:20)
        - 'R': Relative time (2 months ago)
    
    Returns
    -------
    str
        Discord-formatted timestamp string.
    """
    timestamp = int(dt.timestamp())
    return f"<t:{timestamp}:{format_type}>"

def parse_duration(duration_str: str) -> Optional[timedelta]:
    """Parse a human-readable duration string.
    
    Parameters
    ----------
    duration_str: str
        Duration string like '1h30m', '2d', '45s', etc.
    
    Returns
    -------
    Optional[timedelta]
        Parsed timedelta or None if invalid.
    
    Examples
    --------
    >>> parse_duration('1h30m')
    datetime.timedelta(seconds=5400)
    >>> parse_duration('2d12h')
    datetime.timedelta(days=2, seconds=43200)
    """
    import re
    
    # Pattern to match time units
    pattern = r'(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?'
    match = re.match(pattern, duration_str.lower().strip())
    
    if not match:
        return None
    
    days, hours, minutes, seconds = match.groups()
    
    total_seconds = 0
    if days:
        total_seconds += int(days) * 86400
    if hours:
        total_seconds += int(hours) * 3600
    if minutes:
        total_seconds += int(minutes) * 60
    if seconds:
        total_seconds += int(seconds)
    
    return timedelta(seconds=total_seconds) if total_seconds > 0 else None

def format_duration(td: timedelta, precision: str = 'seconds') -> str:
    """Format a timedelta into a human-readable string.
    
    Parameters
    ----------
    td: timedelta
        The timedelta to format.
    precision: str
        The precision level: 'days', 'hours', 'minutes', or 'seconds'.
    
    Returns
    -------
    str
        Human-readable duration string.
    """
    total_seconds = int(td.total_seconds())
    
    if total_seconds < 0:
        return "0 seconds"
    
    days, remainder = divmod(total_seconds, 86400)
    hours, remainder = divmod(remainder, 3600)
    minutes, seconds = divmod(remainder, 60)
    
    parts = []
    
    if days and precision in ['days', 'hours', 'minutes', 'seconds']:
        parts.append(f"{days} day{'s' if days != 1 else ''}")
    
    if hours and precision in ['hours', 'minutes', 'seconds']:
        parts.append(f"{hours} hour{'s' if hours != 1 else ''}")
    
    if minutes and precision in ['minutes', 'seconds']:
        parts.append(f"{minutes} minute{'s' if minutes != 1 else ''}")
    
    if seconds and precision == 'seconds':
        parts.append(f"{seconds} second{'s' if seconds != 1 else ''}")
    
    if not parts:
        return "0 seconds"
    
    return ", ".join(parts)

def time_since(dt: datetime) -> str:
    """Get a human-readable 'time since' string.
    
    Parameters
    ----------
    dt: datetime
        The datetime to compare against now.
    
    Returns
    -------
    str
        Human-readable time difference.
    """
    now = utcnow()
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    
    diff = now - dt
    return format_duration(diff, precision='seconds')

# Time utility examples
def time_utility_examples():
    """Examples of time utility usage."""
    
    # Current time
    now = utcnow()
    print(f"Current UTC time: {now}")
    
    # Snowflake time extraction
    message_id = 123456789012345678  # Example snowflake
    creation_time = snowflake_time(message_id)
    print(f"Message created at: {creation_time}")
    
    # Discord timestamp formatting
    future_time = now + timedelta(hours=2)
    discord_timestamp = format_dt(future_time, 'R')
    print(f"Future time: {discord_timestamp}")
    
    # Duration parsing
    duration = parse_duration('1h30m15s')
    if duration:
        print(f"Parsed duration: {duration}")
        print(f"Formatted: {format_duration(duration)}")
    
    # Time since
    past_time = now - timedelta(days=3, hours=2, minutes=30)
    time_ago = time_since(past_time)
    print(f"Time since past event: {time_ago}")

OAuth and Invite Utilities

Functions for generating OAuth URLs and managing invites.

OAuth URL Generation { .api }

def oauth_url(
    client_id: int,
    *,
    permissions: Optional[nextcord.Permissions] = None,
    guild: Optional[nextcord.abc.Snowflake] = None,
    redirect_uri: Optional[str] = None,
    scopes: Optional[List[str]] = None,
    disable_guild_select: bool = False,
    state: Optional[str] = None
) -> str:
    """Generate an OAuth2 authorization URL for inviting a bot.
    
    Parameters
    ----------
    client_id: int
        The client ID of the application.
    permissions: Optional[nextcord.Permissions]
        The permissions to request.
    guild: Optional[nextcord.abc.Snowflake]
        The guild to pre-select for invitation.
    redirect_uri: Optional[str]
        The redirect URI after authorization.
    scopes: Optional[List[str]]
        The OAuth2 scopes to request.
    disable_guild_select: bool
        Whether to disable guild selection.
    state: Optional[str]
        The state parameter for security.
    
    Returns
    -------
    str
        The OAuth2 authorization URL.
    
    Examples
    --------
    # Basic bot invite URL
    invite_url = nextcord.utils.oauth_url(
        client_id=123456789,
        permissions=nextcord.Permissions(send_messages=True, read_messages=True)
    )
    
    # Admin bot invite URL
    admin_url = nextcord.utils.oauth_url(
        client_id=123456789,
        permissions=nextcord.Permissions(administrator=True)
    )
    """
    from urllib.parse import urlencode
    
    base_url = "https://discord.com/api/oauth2/authorize"
    
    params = {
        'client_id': client_id,
        'scope': ' '.join(scopes or ['bot', 'applications.commands'])
    }
    
    if permissions is not None:
        params['permissions'] = permissions.value
    
    if guild is not None:
        params['guild_id'] = guild.id
    
    if redirect_uri is not None:
        params['redirect_uri'] = redirect_uri
    
    if disable_guild_select:
        params['disable_guild_select'] = 'true'
    
    if state is not None:
        params['state'] = state
    
    params['response_type'] = 'code'
    
    return f"{base_url}?{urlencode(params)}"

def create_invite_embed(
    bot_name: str,
    client_id: int,
    permissions: Optional[nextcord.Permissions] = None,
    description: Optional[str] = None
) -> nextcord.Embed:
    """Create an embed with bot invite information.
    
    Parameters
    ----------
    bot_name: str
        The name of the bot.
    client_id: int
        The client ID of the bot.
    permissions: Optional[nextcord.Permissions]
        The permissions the bot needs.
    description: Optional[str]
        Additional description for the bot.
    
    Returns
    -------
    nextcord.Embed
        Embed containing invite information.
    """
    invite_url = oauth_url(client_id, permissions=permissions)
    
    embed = nextcord.Embed(
        title=f"🤖 Invite {bot_name}",
        description=description or f"Click the link below to add {bot_name} to your server!",
        color=nextcord.Color.blue()
    )
    
    embed.add_field(
        name="📋 Invite Link",
        value=f"[Click here to invite]({invite_url})",
        inline=False
    )
    
    if permissions:
        # List key permissions
        key_perms = []
        perm_names = {
            'administrator': '👑 Administrator',
            'manage_guild': '⚙️ Manage Server',
            'manage_roles': '🎭 Manage Roles',
            'manage_channels': '📋 Manage Channels',
            'kick_members': '👢 Kick Members',
            'ban_members': '🔨 Ban Members',
            'send_messages': '💬 Send Messages',
            'read_messages': '👀 Read Messages',
            'manage_messages': '🗑️ Manage Messages',
            'connect': '🔊 Connect to Voice',
            'speak': '🎤 Speak in Voice'
        }
        
        for perm, display_name in perm_names.items():
            if getattr(permissions, perm, False):
                key_perms.append(display_name)
        
        if key_perms:
            embed.add_field(
                name="🔑 Key Permissions",
                value="\n".join(key_perms[:10]),  # Show first 10
                inline=True
            )
    
    embed.set_footer(text="Make sure you have Manage Server permission in the target server")
    
    return embed

# Invite management utilities
async def get_invite_info(invite_code: str) -> Optional[dict]:
    """Get information about an invite.
    
    Parameters
    ----------
    invite_code: str
        The invite code (e.g., 'abc123' from discord.gg/abc123).
    
    Returns
    -------
    Optional[dict]
        Dictionary containing invite information.
    """
    try:
        invite = await bot.fetch_invite(invite_code)
        
        return {
            'code': invite.code,
            'guild_name': invite.guild.name if invite.guild else None,
            'guild_id': invite.guild.id if invite.guild else None,
            'channel_name': invite.channel.name if invite.channel else None,
            'inviter': str(invite.inviter) if invite.inviter else None,
            'member_count': invite.approximate_member_count,
            'presence_count': invite.approximate_presence_count,
            'expires_at': invite.expires_at,
            'max_uses': invite.max_uses,
            'uses': invite.uses,
            'temporary': invite.temporary,
            'created_at': invite.created_at,
            'url': invite.url
        }
    except nextcord.NotFound:
        return None
    except nextcord.Forbidden:
        return None

async def create_guild_invite(
    channel: nextcord.TextChannel,
    max_age: int = 0,
    max_uses: int = 0,
    temporary: bool = False,
    unique: bool = True,
    reason: Optional[str] = None
) -> Optional[nextcord.Invite]:
    """Create a guild invite with specified parameters.
    
    Parameters
    ----------
    channel: nextcord.TextChannel
        The channel to create the invite for.
    max_age: int
        How long the invite should last in seconds (0 = forever).
    max_uses: int
        How many times the invite can be used (0 = unlimited).
    temporary: bool
        Whether members should be kicked when they disconnect without a role.
    unique: bool
        Whether to create a unique invite or reuse existing.
    reason: Optional[str]
        The reason for creating the invite.
    
    Returns
    -------
    Optional[nextcord.Invite]
        The created invite or None if failed.
    """
    try:
        invite = await channel.create_invite(
            max_age=max_age,
            max_uses=max_uses,
            temporary=temporary,
            unique=unique,
            reason=reason
        )
        return invite
    except nextcord.Forbidden:
        return None
    except nextcord.HTTPException:
        return None

Text Processing Utilities

Functions for text manipulation, formatting, and cleaning.

Text Formatting and Cleaning { .api }

import re
from typing import List, Optional, Dict, Any

def escape_markdown(text: str) -> str:
    """Escape Discord markdown formatting in text.
    
    Parameters
    ----------
    text: str
        The text to escape.
    
    Returns
    -------
    str
        Text with Discord markdown characters escaped.
    """
    # Characters that need escaping in Discord markdown
    chars_to_escape = ['*', '_', '`', '~', '|', '\\']
    
    for char in chars_to_escape:
        text = text.replace(char, '\\' + char)
    
    return text

def escape_mentions(text: str) -> str:
    """Escape Discord mentions in text.
    
    Parameters
    ----------
    text: str
        The text to escape mentions in.
    
    Returns
    -------
    str
        Text with mentions escaped.
    """
    # Escape user mentions
    text = re.sub(r'<@!?(\d+)>', r'<@\\\1>', text)
    
    # Escape role mentions
    text = re.sub(r'<@&(\d+)>', r'<@&\\\1>', text)
    
    # Escape channel mentions
    text = re.sub(r'<#(\d+)>', r'<#\\\1>', text)
    
    # Escape @everyone and @here
    text = text.replace('@everyone', '@\u200beveryone')
    text = text.replace('@here', '@\u200bhere')
    
    return text

def clean_content(content: str, *, guild: Optional[nextcord.Guild] = None) -> str:
    """Clean message content by replacing mentions with names.
    
    Parameters
    ----------
    content: str
        The message content to clean.
    guild: Optional[nextcord.Guild]
        The guild context for resolving mentions.
    
    Returns
    -------
    str
        Cleaned content with mentions replaced by names.
    """
    if not guild:
        return content
    
    # Replace user mentions
    def replace_user_mention(match):
        user_id = int(match.group(1))
        member = guild.get_member(user_id)
        return f'@{member.display_name}' if member else match.group(0)
    
    content = re.sub(r'<@!?(\d+)>', replace_user_mention, content)
    
    # Replace role mentions
    def replace_role_mention(match):
        role_id = int(match.group(1))
        role = guild.get_role(role_id)
        return f'@{role.name}' if role else match.group(0)
    
    content = re.sub(r'<@&(\d+)>', replace_role_mention, content)
    
    # Replace channel mentions
    def replace_channel_mention(match):
        channel_id = int(match.group(1))
        channel = guild.get_channel(channel_id)
        return f'#{channel.name}' if channel else match.group(0)
    
    content = re.sub(r'<#(\d+)>', replace_channel_mention, content)
    
    return content

def truncate_text(text: str, max_length: int, suffix: str = '...') -> str:
    """Truncate text to a maximum length.
    
    Parameters
    ----------
    text: str
        The text to truncate.
    max_length: int
        Maximum length including suffix.
    suffix: str
        Suffix to add when truncating.
    
    Returns
    -------
    str
        Truncated text.
    """
    if len(text) <= max_length:
        return text
    
    return text[:max_length - len(suffix)] + suffix

def format_list(
    items: List[str],
    max_items: int = 10,
    conjunction: str = 'and',
    format_func: Optional[callable] = None
) -> str:
    """Format a list of items into a readable string.
    
    Parameters
    ----------
    items: List[str]
        The items to format.
    max_items: int
        Maximum number of items to display.
    conjunction: str
        Word to use before the last item ('and' or 'or').
    format_func: Optional[callable]
        Function to format each item.
    
    Returns
    -------
    str
        Formatted list string.
    """
    if not items:
        return "none"
    
    if format_func:
        items = [format_func(item) for item in items]
    
    # Truncate if too many items
    displayed_items = items[:max_items]
    remaining = len(items) - max_items
    
    if len(displayed_items) == 1:
        result = displayed_items[0]
    elif len(displayed_items) == 2:
        result = f"{displayed_items[0]} {conjunction} {displayed_items[1]}"
    else:
        result = ", ".join(displayed_items[:-1]) + f", {conjunction} {displayed_items[-1]}"
    
    if remaining > 0:
        result += f" {conjunction} {remaining} more"
    
    return result

def pluralize(count: int, singular: str, plural: Optional[str] = None) -> str:
    """Return the singular or plural form based on count.
    
    Parameters
    ----------
    count: int
        The count to check.
    singular: str
        The singular form.
    plural: Optional[str]
        The plural form (defaults to singular + 's').
    
    Returns
    -------
    str
        The appropriate form.
    """
    if plural is None:
        plural = singular + 's'
    
    return singular if count == 1 else plural

def extract_code_blocks(content: str) -> List[Dict[str, str]]:
    """Extract code blocks from message content.
    
    Parameters
    ----------
    content: str
        The message content.
    
    Returns
    -------
    List[Dict[str, str]]
        List of code blocks with 'language' and 'code' keys.
    """
    # Pattern for code blocks with optional language
    pattern = r'```(?:(\w+)\n)?(.*?)```'
    
    blocks = []
    for match in re.finditer(pattern, content, re.DOTALL):
        language = match.group(1) or 'text'
        code = match.group(2).strip()
        
        blocks.append({
            'language': language,
            'code': code
        })
    
    return blocks

def create_progress_bar(
    current: int,
    total: int,
    length: int = 20,
    fill_char: str = '█',
    empty_char: str = '░'
) -> str:
    """Create a text-based progress bar.
    
    Parameters
    ----------
    current: int
        Current progress value.
    total: int
        Total/maximum value.
    length: int
        Length of the progress bar.
    fill_char: str
        Character to use for filled portion.
    empty_char: str
        Character to use for empty portion.
    
    Returns
    -------
    str
        Progress bar string.
    """
    if total <= 0:
        return empty_char * length
    
    progress = min(current / total, 1.0)  # Clamp to 1.0
    filled_length = int(length * progress)
    
    bar = fill_char * filled_length + empty_char * (length - filled_length)
    percentage = int(progress * 100)
    
    return f"{bar} {percentage}%"

# Text processing examples
def text_processing_examples():
    """Examples of text processing utilities."""
    
    # Markdown escaping
    text_with_markdown = "This has **bold** and *italic* text"
    escaped = escape_markdown(text_with_markdown)
    print(f"Escaped: {escaped}")
    
    # Mention escaping
    text_with_mentions = "Hello <@123456> and @everyone!"
    safe_text = escape_mentions(text_with_mentions)
    print(f"Safe text: {safe_text}")
    
    # Text truncation
    long_text = "This is a very long piece of text that needs to be truncated"
    short_text = truncate_text(long_text, 30)
    print(f"Truncated: {short_text}")
    
    # List formatting
    items = ["apple", "banana", "cherry", "date"]
    formatted_list = format_list(items, conjunction='and')
    print(f"Formatted list: {formatted_list}")
    
    # Pluralization
    count = 5
    word = pluralize(count, "item")
    print(f"You have {count} {word}")
    
    # Progress bar
    progress = create_progress_bar(75, 100, length=15)
    print(f"Progress: {progress}")
    
    # Code block extraction
    message_content = """
    Here's some Python code:
    ```python
    def hello():
        print("Hello, world!")
    ```
    
    And some JavaScript:
    ```js
    console.log("Hello, world!");
    ```
    """
    
    code_blocks = extract_code_blocks(message_content)
    for block in code_blocks:
        print(f"Language: {block['language']}")
        print(f"Code: {block['code']}")

Embed Utilities

Helper functions for creating and manipulating embeds.

Embed Creation Helpers { .api }

def create_error_embed(
    title: str = "Error",
    description: str = "An error occurred",
    **kwargs
) -> nextcord.Embed:
    """Create a standardized error embed.
    
    Parameters
    ----------
    title: str
        The error title.
    description: str
        The error description.
    **kwargs
        Additional embed parameters.
    
    Returns
    -------
    nextcord.Embed
        Error embed with red color.
    """
    embed = nextcord.Embed(
        title=f"❌ {title}",
        description=description,
        color=nextcord.Color.red(),
        **kwargs
    )
    return embed

def create_success_embed(
    title: str = "Success",
    description: str = "Operation completed successfully",
    **kwargs
) -> nextcord.Embed:
    """Create a standardized success embed.
    
    Parameters
    ----------
    title: str
        The success title.
    description: str
        The success description.
    **kwargs
        Additional embed parameters.
    
    Returns
    -------
    nextcord.Embed
        Success embed with green color.
    """
    embed = nextcord.Embed(
        title=f"✅ {title}",
        description=description,
        color=nextcord.Color.green(),
        **kwargs
    )
    return embed

def create_info_embed(
    title: str = "Information",
    description: str = "Here's some information",
    **kwargs
) -> nextcord.Embed:
    """Create a standardized info embed.
    
    Parameters
    ----------
    title: str
        The info title.
    description: str
        The info description.
    **kwargs
        Additional embed parameters.
    
    Returns
    -------
    nextcord.Embed
        Info embed with blue color.
    """
    embed = nextcord.Embed(
        title=f"ℹ️ {title}",
        description=description,
        color=nextcord.Color.blue(),
        **kwargs
    )
    return embed

def create_warning_embed(
    title: str = "Warning",
    description: str = "Please pay attention to this warning",
    **kwargs
) -> nextcord.Embed:
    """Create a standardized warning embed.
    
    Parameters
    ----------
    title: str
        The warning title.
    description: str
        The warning description.
    **kwargs
        Additional embed parameters.
    
    Returns
    -------
    nextcord.Embed
        Warning embed with orange color.
    """
    embed = nextcord.Embed(
        title=f"⚠️ {title}",
        description=description,
        color=nextcord.Color.orange(),
        **kwargs
    )
    return embed

def paginate_embed_fields(
    title: str,
    fields: List[Dict[str, Any]],
    fields_per_page: int = 25,
    **embed_kwargs
) -> List[nextcord.Embed]:
    """Paginate embed fields across multiple embeds.
    
    Parameters
    ----------
    title: str
        Base title for all embeds.
    fields: List[Dict[str, Any]]
        List of field dictionaries with 'name', 'value', and optional 'inline' keys.
    fields_per_page: int
        Maximum fields per embed (Discord limit is 25).
    **embed_kwargs
        Additional embed parameters.
    
    Returns
    -------
    List[nextcord.Embed]
        List of paginated embeds.
    """
    if fields_per_page > 25:
        fields_per_page = 25  # Discord limit
    
    embeds = []
    total_pages = (len(fields) + fields_per_page - 1) // fields_per_page
    
    for page in range(total_pages):
        start_idx = page * fields_per_page
        end_idx = start_idx + fields_per_page
        page_fields = fields[start_idx:end_idx]
        
        embed = nextcord.Embed(
            title=f"{title} (Page {page + 1}/{total_pages})",
            **embed_kwargs
        )
        
        for field in page_fields:
            embed.add_field(
                name=field['name'],
                value=field['value'],
                inline=field.get('inline', True)
            )
        
        embeds.append(embed)
    
    return embeds

def create_user_embed(user: nextcord.User, **kwargs) -> nextcord.Embed:
    """Create an embed with user information.
    
    Parameters
    ----------
    user: nextcord.User
        The user to create an embed for.
    **kwargs
        Additional embed parameters.
    
    Returns
    -------
    nextcord.Embed
        User information embed.
    """
    embed = nextcord.Embed(
        title=f"User: {user.display_name}",
        color=getattr(user, 'color', nextcord.Color.blue()),
        **kwargs
    )
    
    embed.set_thumbnail(url=user.display_avatar.url)
    embed.add_field(name="Username", value=str(user), inline=True)
    embed.add_field(name="ID", value=user.id, inline=True)
    embed.add_field(name="Bot", value="Yes" if user.bot else "No", inline=True)
    embed.add_field(name="Created", value=format_dt(user.created_at, 'D'), inline=True)
    
    return embed

def create_guild_embed(guild: nextcord.Guild, **kwargs) -> nextcord.Embed:
    """Create an embed with guild information.
    
    Parameters
    ----------
    guild: nextcord.Guild
        The guild to create an embed for.
    **kwargs
        Additional embed parameters.
    
    Returns
    -------
    nextcord.Embed
        Guild information embed.
    """
    embed = nextcord.Embed(
        title=f"Server: {guild.name}",
        description=guild.description or "No description",
        color=nextcord.Color.blue(),
        **kwargs
    )
    
    if guild.icon:
        embed.set_thumbnail(url=guild.icon.url)
    
    embed.add_field(name="Owner", value=guild.owner.mention if guild.owner else "Unknown", inline=True)
    embed.add_field(name="Members", value=f"{guild.member_count:,}", inline=True)
    embed.add_field(name="Channels", value=len(guild.channels), inline=True)
    embed.add_field(name="Roles", value=len(guild.roles), inline=True)
    embed.add_field(name="Boosts", value=guild.premium_subscription_count, inline=True)
    embed.add_field(name="Boost Level", value=guild.premium_tier, inline=True)
    embed.add_field(name="Created", value=format_dt(guild.created_at, 'D'), inline=True)
    
    return embed

# Embed utility examples
def embed_utility_examples():
    """Examples of embed utility usage."""
    
    # Standard embed types
    error_embed = create_error_embed("Command Failed", "Invalid arguments provided")
    success_embed = create_success_embed("Action Complete", "User has been banned successfully")
    info_embed = create_info_embed("Bot Information", "This bot helps manage your server")
    warning_embed = create_warning_embed("Rate Limit", "You're sending messages too quickly")
    
    # Paginated fields
    many_fields = [
        {"name": f"Field {i}", "value": f"Value {i}", "inline": True}
        for i in range(50)
    ]
    
    paginated_embeds = paginate_embed_fields(
        "Large Dataset",
        many_fields,
        fields_per_page=10,
        color=nextcord.Color.purple()
    )
    
    print(f"Created {len(paginated_embeds)} paginated embeds")
    
    return {
        'error': error_embed,
        'success': success_embed,
        'info': info_embed,
        'warning': warning_embed,
        'paginated': paginated_embeds
    }

File and Data Utilities

Helper functions for file handling and data processing.

File Operations { .api }

import json
import csv
import io
from pathlib import Path
from typing import Any, Dict, List, Union, Optional

def safe_json_load(file_path: Union[str, Path], default: Any = None) -> Any:
    """Safely load JSON from a file.
    
    Parameters
    ----------
    file_path: Union[str, Path]
        Path to the JSON file.
    default: Any
        Default value to return if file doesn't exist or is invalid.
    
    Returns
    -------
    Any
        Loaded JSON data or default value.
    """
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except (FileNotFoundError, json.JSONDecodeError, IOError):
        return default

def safe_json_save(data: Any, file_path: Union[str, Path], indent: int = 2) -> bool:
    """Safely save data to a JSON file.
    
    Parameters
    ----------
    data: Any
        Data to save.
    file_path: Union[str, Path]
        Path to save the JSON file.
    indent: int
        JSON indentation.
    
    Returns
    -------
    bool
        True if successful, False otherwise.
    """
    try:
        # Ensure directory exists
        Path(file_path).parent.mkdir(parents=True, exist_ok=True)
        
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=indent, ensure_ascii=False)
        return True
    except (IOError, TypeError):
        return False

def create_data_file(
    data: List[Dict[str, Any]],
    filename: str,
    format_type: str = 'json'
) -> nextcord.File:
    """Create a Discord file from data.
    
    Parameters
    ----------
    data: List[Dict[str, Any]]
        Data to include in the file.
    filename: str
        Name for the file.
    format_type: str
        Format type: 'json' or 'csv'.
    
    Returns
    -------
    nextcord.File
        Discord file object.
    """
    if format_type.lower() == 'json':
        content = json.dumps(data, indent=2, ensure_ascii=False)
        file_extension = '.json'
        
    elif format_type.lower() == 'csv':
        if not data:
            content = ""
        else:
            output = io.StringIO()
            writer = csv.DictWriter(output, fieldnames=data[0].keys())
            writer.writeheader()
            writer.writerows(data)
            content = output.getvalue()
        file_extension = '.csv'
        
    else:
        raise ValueError(f"Unsupported format: {format_type}")
    
    # Add extension if not present
    if not filename.endswith(file_extension):
        filename += file_extension
    
    file_bytes = content.encode('utf-8')
    return nextcord.File(io.BytesIO(file_bytes), filename=filename)

def format_file_size(size_bytes: int) -> str:
    """Format file size in human-readable format.
    
    Parameters
    ----------
    size_bytes: int
        Size in bytes.
    
    Returns
    -------
    str
        Human-readable size string.
    """
    if size_bytes == 0:
        return "0 B"
    
    size_names = ["B", "KB", "MB", "GB", "TB"]
    i = 0
    
    while size_bytes >= 1024 and i < len(size_names) - 1:
        size_bytes /= 1024.0
        i += 1
    
    return f"{size_bytes:.1f} {size_names[i]}"

def backup_data(data: Dict[str, Any], backup_dir: str = "backups") -> bool:
    """Create a timestamped backup of data.
    
    Parameters
    ----------
    data: Dict[str, Any]
        Data to backup.
    backup_dir: str
        Directory to store backups.
    
    Returns
    -------
    bool
        True if backup was successful.
    """
    from datetime import datetime
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup_path = Path(backup_dir) / f"backup_{timestamp}.json"
    
    return safe_json_save(data, backup_path)

# Data processing utilities
def chunk_list(lst: List[Any], chunk_size: int) -> List[List[Any]]:
    """Split a list into chunks of specified size.
    
    Parameters
    ----------
    lst: List[Any]
        The list to chunk.
    chunk_size: int
        Size of each chunk.
    
    Returns
    -------
    List[List[Any]]
        List of chunks.
    """
    return [lst[i:i + chunk_size] for i in range(0, len(lst), chunk_size)]

def flatten_dict(d: Dict[str, Any], parent_key: str = '', sep: str = '.') -> Dict[str, Any]:
    """Flatten a nested dictionary.
    
    Parameters
    ----------
    d: Dict[str, Any]
        Dictionary to flatten.
    parent_key: str
        Parent key prefix.
    sep: str
        Separator for nested keys.
    
    Returns
    -------
    Dict[str, Any]
        Flattened dictionary.
    """
    items = []
    
    for k, v in d.items():
        new_key = f"{parent_key}{sep}{k}" if parent_key else k
        
        if isinstance(v, dict):
            items.extend(flatten_dict(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    
    return dict(items)

# File utility examples
async def file_utility_examples(channel: nextcord.TextChannel):
    """Examples of file utility usage."""
    
    # Create data file
    sample_data = [
        {"name": "Alice", "age": 25, "role": "Admin"},
        {"name": "Bob", "age": 30, "role": "Moderator"},
        {"name": "Charlie", "age": 22, "role": "Member"}
    ]
    
    # Create JSON file
    json_file = create_data_file(sample_data, "members", "json")
    await channel.send("Here's the member data:", file=json_file)
    
    # Create CSV file
    csv_file = create_data_file(sample_data, "members", "csv")
    await channel.send("Here's the same data in CSV format:", file=csv_file)
    
    # File size formatting
    file_size = format_file_size(1024 * 1024 * 2.5)  # 2.5 MB
    print(f"File size: {file_size}")
    
    # List chunking
    large_list = list(range(100))
    chunks = chunk_list(large_list, 10)
    print(f"Split list into {len(chunks)} chunks of 10")
    
    # Dictionary flattening
    nested_dict = {
        "user": {
            "profile": {
                "name": "Alice",
                "age": 25
            },
            "settings": {
                "theme": "dark",
                "notifications": True
            }
        }
    }
    
    flat_dict = flatten_dict(nested_dict)
    print("Flattened dictionary:", flat_dict)

This comprehensive documentation covers all major utility functions in nextcord, providing developers with powerful tools for common bot development tasks including search operations, text processing, embed creation, time handling, and file operations.

Install with Tessl CLI

npx tessl i tessl/pypi-nextcord

docs

application-commands.md

channels.md

client.md

commands.md

errors.md

events.md

guild.md

index.md

messages.md

permissions.md

tasks.md

ui.md

users.md

utilities.md

voice.md

webhooks.md

tile.json