A Python wrapper for the Discord API forked from discord.py
—
Utility functions, helper classes, and convenience methods for common Discord bot operations, providing powerful tools for bot development.
Essential utility functions for searching, filtering, and manipulating Discord objects.
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
}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}")Functions for generating OAuth URLs and managing invites.
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 NoneFunctions for text manipulation, formatting, and cleaning.
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']}")Helper functions for creating and manipulating embeds.
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
}Helper functions for file handling and data processing.
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