A Python wrapper for the Discord API forked from discord.py
—
Webhook creation and management for external integrations and message delivery outside of bot connections, providing flexible communication channels.
Core webhook functionality for sending messages and managing webhook properties.
import nextcord
from nextcord import Webhook, SyncWebhook, WebhookMessage
from typing import Optional, List, Union, Any, Dict
import aiohttp
class Webhook:
"""Represents an async Discord webhook.
Webhooks allow external services to send messages to Discord channels
without needing a bot connection.
Attributes
----------
id: int
The webhook's ID.
type: WebhookType
The type of webhook.
token: Optional[str]
The webhook's token.
guild_id: Optional[int]
The guild ID the webhook belongs to.
channel_id: Optional[int]
The channel ID the webhook belongs to.
user: Optional[User]
The user who created this webhook.
name: Optional[str]
The webhook's name.
avatar: Optional[str]
The webhook's avatar hash.
source_guild: Optional[PartialWebhookGuild]
The source guild for channel follower webhooks.
source_channel: Optional[PartialWebhookChannel]
The source channel for channel follower webhooks.
url: str
The webhook's URL.
"""
@classmethod
def partial(
cls,
id: int,
token: str,
*,
session: Optional[aiohttp.ClientSession] = None
) -> Webhook:
"""Create a partial webhook from ID and token.
Parameters
----------
id: int
The webhook ID.
token: str
The webhook token.
session: Optional[aiohttp.ClientSession]
The session to use for requests.
Returns
-------
Webhook
A partial webhook instance.
"""
...
@classmethod
def from_url(
cls,
url: str,
*,
session: Optional[aiohttp.ClientSession] = None
) -> Webhook:
"""Create a webhook from a Discord webhook URL.
Parameters
----------
url: str
The webhook URL.
session: Optional[aiohttp.ClientSession]
The session to use for requests.
Returns
-------
Webhook
A webhook instance from the URL.
"""
...
async def fetch(self, *, prefer_auth: bool = True) -> Webhook:
"""Fetch the webhook's information.
Parameters
----------
prefer_auth: bool
Whether to prefer authenticated requests.
Returns
-------
Webhook
The updated webhook.
"""
...
async def delete(self, *, reason: Optional[str] = None) -> None:
"""Delete the webhook.
Parameters
----------
reason: Optional[str]
The reason for deleting the webhook.
"""
...
async def edit(
self,
*,
name: Optional[str] = MISSING,
avatar: Optional[bytes] = MISSING,
reason: Optional[str] = None
) -> Webhook:
"""Edit the webhook.
Parameters
----------
name: Optional[str]
The webhook's new name.
avatar: Optional[bytes]
The webhook's new avatar as bytes.
reason: Optional[str]
The reason for editing the webhook.
Returns
-------
Webhook
The updated webhook.
"""
...
async def send(
self,
content: Optional[str] = MISSING,
*,
username: Optional[str] = MISSING,
avatar_url: Optional[str] = MISSING,
tts: bool = False,
embed: Optional[nextcord.Embed] = MISSING,
embeds: Optional[List[nextcord.Embed]] = MISSING,
file: Optional[nextcord.File] = MISSING,
files: Optional[List[nextcord.File]] = MISSING,
allowed_mentions: Optional[nextcord.AllowedMentions] = MISSING,
thread: Optional[nextcord.abc.Snowflake] = MISSING,
wait: bool = False,
suppress_embeds: bool = False
) -> Optional[WebhookMessage]:
"""Send a message via the webhook.
Parameters
----------
content: Optional[str]
The message content.
username: Optional[str]
Override the webhook's username.
avatar_url: Optional[str]
Override the webhook's avatar URL.
tts: bool
Whether the message should be text-to-speech.
embed: Optional[nextcord.Embed]
An embed to send.
embeds: Optional[List[nextcord.Embed]]
A list of embeds to send (max 10).
file: Optional[nextcord.File]
A file to send.
files: Optional[List[nextcord.File]]
A list of files to send (max 10).
allowed_mentions: Optional[nextcord.AllowedMentions]
Controls which mentions are processed.
thread: Optional[nextcord.abc.Snowflake]
The thread to send the message to.
wait: bool
Whether to wait for the message and return it.
suppress_embeds: bool
Whether to suppress embeds in the message.
Returns
-------
Optional[WebhookMessage]
The sent message if wait=True, otherwise None.
"""
...
# Basic webhook usage examples
async def webhook_examples():
"""Examples of webhook usage."""
# Create webhook from URL
webhook_url = "https://discord.com/api/webhooks/123456789/abcdef123456"
webhook = nextcord.Webhook.from_url(webhook_url)
# Send simple message
await webhook.send("Hello from webhook!")
# Send message with custom username and avatar
await webhook.send(
"Custom webhook message",
username="Custom Bot",
avatar_url="https://example.com/avatar.png"
)
# Send message with embed
embed = nextcord.Embed(
title="Webhook Embed",
description="This message was sent via webhook",
color=nextcord.Color.blue()
)
embed.add_field(name="Field", value="Value", inline=False)
await webhook.send(embed=embed)
# Send message and get response
message = await webhook.send(
"Message with response",
wait=True # Wait for the message to be sent and return it
)
if message:
print(f"Sent message with ID: {message.id}")
# Webhook management
async def manage_webhook(channel: nextcord.TextChannel):
"""Create and manage webhooks."""
# Create a new webhook
webhook = await channel.create_webhook(
name="My Bot Webhook",
avatar=None, # Can provide avatar bytes here
reason="Created for bot notifications"
)
print(f"Created webhook: {webhook.url}")
# Edit webhook properties
await webhook.edit(
name="Updated Bot Webhook",
reason="Updated webhook name"
)
# Use the webhook
await webhook.send("Webhook created and configured!")
# Get webhook info
webhook_info = await webhook.fetch()
print(f"Webhook name: {webhook_info.name}")
print(f"Created by: {webhook_info.user}")
# Delete webhook when done
await webhook.delete(reason="No longer needed")class SyncWebhook:
"""Represents a synchronous Discord webhook.
This is useful for applications that don't use async/await
or need to send webhook messages from synchronous code.
All methods are synchronous versions of the async Webhook class.
"""
@classmethod
def partial(
cls,
id: int,
token: str,
*,
session: Optional[Any] = None
) -> SyncWebhook:
"""Create a partial sync webhook from ID and token."""
...
@classmethod
def from_url(
cls,
url: str,
*,
session: Optional[Any] = None
) -> SyncWebhook:
"""Create a sync webhook from a Discord webhook URL."""
...
def send(
self,
content: Optional[str] = MISSING,
*,
username: Optional[str] = MISSING,
avatar_url: Optional[str] = MISSING,
tts: bool = False,
embed: Optional[nextcord.Embed] = MISSING,
embeds: Optional[List[nextcord.Embed]] = MISSING,
file: Optional[nextcord.File] = MISSING,
files: Optional[List[nextcord.File]] = MISSING,
allowed_mentions: Optional[nextcord.AllowedMentions] = MISSING,
thread: Optional[nextcord.abc.Snowflake] = MISSING,
wait: bool = False
) -> Optional[WebhookMessage]:
"""Send a message via the webhook synchronously."""
...
def fetch(self, *, prefer_auth: bool = True) -> SyncWebhook:
"""Fetch the webhook's information synchronously."""
...
def edit(
self,
*,
name: Optional[str] = MISSING,
avatar: Optional[bytes] = MISSING,
reason: Optional[str] = None
) -> SyncWebhook:
"""Edit the webhook synchronously."""
...
def delete(self, *, reason: Optional[str] = None) -> None:
"""Delete the webhook synchronously."""
...
# Synchronous webhook usage
def sync_webhook_example():
"""Example of synchronous webhook usage."""
import requests
# Create sync webhook from URL
webhook_url = "https://discord.com/api/webhooks/123456789/abcdef123456"
webhook = nextcord.SyncWebhook.from_url(webhook_url)
# Send message synchronously
webhook.send("Synchronous webhook message!")
# Send with embed
embed = nextcord.Embed(
title="Sync Webhook",
description="Sent synchronously",
color=nextcord.Color.green()
)
message = webhook.send(embed=embed, wait=True)
if message:
print(f"Message sent with ID: {message.id}")
# Integration with web frameworks (Flask example)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/notify', methods=['POST'])
def send_discord_notification():
"""Flask endpoint to send Discord notifications via webhook."""
try:
data = request.json
# Get webhook URL from environment or config
webhook_url = "your_webhook_url_here"
webhook = nextcord.SyncWebhook.from_url(webhook_url)
# Create notification embed
embed = nextcord.Embed(
title=data.get('title', 'Notification'),
description=data.get('message', ''),
color=nextcord.Color.blue()
)
if data.get('url'):
embed.url = data['url']
if data.get('fields'):
for field in data['fields']:
embed.add_field(
name=field['name'],
value=field['value'],
inline=field.get('inline', False)
)
# Send notification
webhook.send(
embed=embed,
username=data.get('username', 'Notification Bot'),
avatar_url=data.get('avatar_url')
)
return jsonify({'success': True})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500Messages sent through webhooks with editing and deletion capabilities.
class WebhookMessage:
"""Represents a message sent by a webhook.
Attributes
----------
id: int
The message ID.
type: MessageType
The message type.
content: str
The message content.
channel_id: int
The channel ID the message was sent in.
author: WebhookAuthor
The webhook author information.
embeds: List[Embed]
The message embeds.
attachments: List[Attachment]
The message attachments.
edited_at: Optional[datetime.datetime]
When the message was last edited.
flags: MessageFlags
The message flags.
thread: Optional[Thread]
The thread the message was sent in.
"""
async def edit(
self,
*,
content: Optional[str] = MISSING,
embed: Optional[nextcord.Embed] = MISSING,
embeds: Optional[List[nextcord.Embed]] = MISSING,
file: Optional[nextcord.File] = MISSING,
files: Optional[List[nextcord.File]] = MISSING,
attachments: Optional[List[nextcord.Attachment]] = MISSING,
allowed_mentions: Optional[nextcord.AllowedMentions] = MISSING
) -> WebhookMessage:
"""Edit the webhook message.
Parameters
----------
content: Optional[str]
The new message content.
embed: Optional[nextcord.Embed]
The new embed for the message.
embeds: Optional[List[nextcord.Embed]]
The new embeds for the message.
file: Optional[nextcord.File]
A new file to add to the message.
files: Optional[List[nextcord.File]]
New files to add to the message.
attachments: Optional[List[nextcord.Attachment]]
Existing attachments to keep.
allowed_mentions: Optional[nextcord.AllowedMentions]
Controls which mentions are processed.
Returns
-------
WebhookMessage
The edited message.
"""
...
async def delete(self, *, delay: Optional[float] = None) -> None:
"""Delete the webhook message.
Parameters
----------
delay: Optional[float]
Number of seconds to wait before deleting.
"""
...
@property
def jump_url(self) -> str:
"""str: The jump URL for this message."""
...
@property
def created_at(self) -> datetime.datetime:
"""datetime.datetime: When the message was created."""
...
# Webhook message management examples
async def webhook_message_management():
"""Examples of managing webhook messages."""
webhook = nextcord.Webhook.from_url("webhook_url_here")
# Send message and keep reference
message = await webhook.send(
"This message will be edited later",
wait=True # Required to get message object
)
if message:
# Edit the message after 5 seconds
await asyncio.sleep(5)
await message.edit(content="This message has been edited!")
# Add an embed to the message
embed = nextcord.Embed(
title="Updated Message",
description="This embed was added later",
color=nextcord.Color.green()
)
await message.edit(embed=embed)
# Delete the message after 10 seconds
await message.delete(delay=10)
# Advanced webhook patterns
class WebhookNotificationSystem:
"""Advanced webhook notification system."""
def __init__(self, webhook_url: str):
self.webhook = nextcord.Webhook.from_url(webhook_url)
self.message_cache = {}
async def send_status_update(
self,
service: str,
status: str,
details: Optional[str] = None
) -> Optional[WebhookMessage]:
"""Send or update a service status message."""
# Determine embed color based on status
color_map = {
'operational': nextcord.Color.green(),
'degraded': nextcord.Color.orange(),
'outage': nextcord.Color.red(),
'maintenance': nextcord.Color.blue()
}
embed = nextcord.Embed(
title=f"🔧 {service} Status",
description=status.title(),
color=color_map.get(status.lower(), nextcord.Color.gray()),
timestamp=datetime.now()
)
if details:
embed.add_field(name="Details", value=details, inline=False)
# Check if we have an existing message for this service
if service in self.message_cache:
try:
# Update existing message
message = self.message_cache[service]
updated_message = await message.edit(embed=embed)
return updated_message
except nextcord.NotFound:
# Message was deleted, remove from cache
del self.message_cache[service]
# Send new message
message = await self.webhook.send(
embed=embed,
username=f"{service} Monitor",
wait=True
)
if message:
self.message_cache[service] = message
return message
async def send_alert(
self,
title: str,
message: str,
severity: str = 'info',
ping_role: Optional[str] = None
) -> Optional[WebhookMessage]:
"""Send an alert notification."""
severity_config = {
'info': {'emoji': 'ℹ️', 'color': nextcord.Color.blue()},
'warning': {'emoji': '⚠️', 'color': nextcord.Color.orange()},
'error': {'emoji': '❌', 'color': nextcord.Color.red()},
'critical': {'emoji': '🚨', 'color': nextcord.Color.from_rgb(139, 0, 0)}
}
config = severity_config.get(severity, severity_config['info'])
embed = nextcord.Embed(
title=f"{config['emoji']} {title}",
description=message,
color=config['color'],
timestamp=datetime.now()
)
embed.add_field(name="Severity", value=severity.upper(), inline=True)
content = ""
if ping_role and severity in ['error', 'critical']:
content = f"<@&{ping_role}>"
return await self.webhook.send(
content=content,
embed=embed,
username="Alert System",
wait=True
)
async def send_log_entry(
self,
level: str,
service: str,
message: str,
extra_data: Optional[Dict[str, Any]] = None
):
"""Send a log entry via webhook."""
level_colors = {
'DEBUG': nextcord.Color.light_gray(),
'INFO': nextcord.Color.blue(),
'WARNING': nextcord.Color.orange(),
'ERROR': nextcord.Color.red(),
'CRITICAL': nextcord.Color.from_rgb(139, 0, 0)
}
embed = nextcord.Embed(
title=f"📋 {level} - {service}",
description=f"```\n{message}\n```",
color=level_colors.get(level, nextcord.Color.default()),
timestamp=datetime.now()
)
if extra_data:
for key, value in extra_data.items():
embed.add_field(
name=key.replace('_', ' ').title(),
value=str(value)[:1024], # Discord field value limit
inline=True
)
await self.webhook.send(
embed=embed,
username=f"{service} Logger"
)
# Usage example
async def notification_system_example():
"""Example usage of the webhook notification system."""
webhook_url = "your_webhook_url_here"
notifier = WebhookNotificationSystem(webhook_url)
# Send initial status
await notifier.send_status_update(
service="API Server",
status="operational",
details="All systems running normally"
)
# Update status (will edit the existing message)
await notifier.send_status_update(
service="API Server",
status="degraded",
details="Experiencing higher than normal latency"
)
# Send alert
await notifier.send_alert(
title="High CPU Usage",
message="Server CPU usage has exceeded 80% for the past 5 minutes",
severity="warning"
)
# Send log entry
await notifier.send_log_entry(
level="ERROR",
service="Database",
message="Connection timeout occurred",
extra_data={
"query_time": "15.3s",
"affected_users": 42,
"retry_count": 3
}
)Advanced webhook management including creation, monitoring, and cleanup.
# Guild-level webhook management
async def manage_guild_webhooks(guild: nextcord.Guild):
"""Manage webhooks at the guild level."""
# Get all webhooks in the guild
webhooks = await guild.webhooks()
print(f"Found {len(webhooks)} webhooks in {guild.name}")
for webhook in webhooks:
print(f"- {webhook.name} (ID: {webhook.id})")
print(f" Channel: #{webhook.channel.name if webhook.channel else 'Unknown'}")
print(f" Created by: {webhook.user}")
print(f" Type: {webhook.type}")
print()
# Channel-specific webhook operations
async def manage_channel_webhooks(channel: nextcord.TextChannel):
"""Manage webhooks for a specific channel."""
# Get webhooks for this channel
webhooks = await channel.webhooks()
print(f"Webhooks in #{channel.name}:")
if not webhooks:
print("No webhooks found.")
return
for webhook in webhooks:
# Get detailed info
webhook_info = await webhook.fetch()
print(f"Name: {webhook_info.name}")
print(f"ID: {webhook_info.id}")
print(f"Token: {'***' + webhook_info.token[-4:] if webhook_info.token else 'No token'}")
print(f"Created by: {webhook_info.user}")
print(f"Avatar: {webhook_info.avatar}")
print("---")
# Webhook monitoring and cleanup
class WebhookManager:
"""Comprehensive webhook management system."""
def __init__(self, bot):
self.bot = bot
self.webhook_usage = {} # Track webhook usage
async def audit_webhooks(self, guild: nextcord.Guild) -> Dict[str, Any]:
"""Audit all webhooks in a guild."""
webhooks = await guild.webhooks()
audit_results = {
'total_webhooks': len(webhooks),
'active_webhooks': 0,
'inactive_webhooks': 0,
'unknown_webhooks': 0,
'webhook_details': []
}
for webhook in webhooks:
try:
# Fetch detailed information
webhook_info = await webhook.fetch()
details = {
'id': webhook_info.id,
'name': webhook_info.name,
'channel': webhook_info.channel.name if webhook_info.channel else 'Unknown',
'created_by': str(webhook_info.user) if webhook_info.user else 'Unknown',
'type': str(webhook_info.type),
'has_token': webhook_info.token is not None,
'status': 'active' # Assume active if fetchable
}
audit_results['active_webhooks'] += 1
audit_results['webhook_details'].append(details)
except nextcord.NotFound:
# Webhook was deleted or is inaccessible
audit_results['inactive_webhooks'] += 1
audit_results['webhook_details'].append({
'id': webhook.id,
'name': webhook.name or 'Unknown',
'status': 'inactive',
'error': 'Not found or no access'
})
except Exception as e:
audit_results['unknown_webhooks'] += 1
audit_results['webhook_details'].append({
'id': webhook.id,
'name': webhook.name or 'Unknown',
'status': 'error',
'error': str(e)
})
return audit_results
async def cleanup_unused_webhooks(
self,
guild: nextcord.Guild,
dry_run: bool = True
) -> Dict[str, Any]:
"""Clean up unused or orphaned webhooks."""
webhooks = await guild.webhooks()
cleanup_results = {
'total_checked': len(webhooks),
'deleted': [],
'kept': [],
'errors': []
}
for webhook in webhooks:
try:
webhook_info = await webhook.fetch()
# Check if webhook should be deleted
should_delete = False
reason = ""
# Check if channel still exists
if not webhook_info.channel:
should_delete = True
reason = "Channel no longer exists"
# Check if created by a bot that's no longer in the guild
elif webhook_info.user and webhook_info.user.bot:
if webhook_info.user not in guild.members:
should_delete = True
reason = "Created by bot no longer in guild"
# Check for specific naming patterns that indicate unused webhooks
elif webhook_info.name and any(pattern in webhook_info.name.lower() for pattern in ['test', 'temp', 'unused']):
should_delete = True
reason = "Appears to be temporary/test webhook"
if should_delete:
if not dry_run:
await webhook.delete(reason=f"Cleanup: {reason}")
cleanup_results['deleted'].append({
'id': webhook_info.id,
'name': webhook_info.name,
'reason': reason
})
else:
cleanup_results['deleted'].append({
'id': webhook_info.id,
'name': webhook_info.name,
'reason': f"Would delete: {reason}"
})
else:
cleanup_results['kept'].append({
'id': webhook_info.id,
'name': webhook_info.name
})
except Exception as e:
cleanup_results['errors'].append({
'webhook_id': webhook.id,
'error': str(e)
})
return cleanup_results
async def create_managed_webhook(
self,
channel: nextcord.TextChannel,
name: str,
avatar_path: Optional[str] = None,
reason: Optional[str] = None
) -> nextcord.Webhook:
"""Create a webhook with proper management tracking."""
# Read avatar if provided
avatar_bytes = None
if avatar_path:
try:
with open(avatar_path, 'rb') as f:
avatar_bytes = f.read()
except FileNotFoundError:
print(f"Avatar file not found: {avatar_path}")
# Create webhook
webhook = await channel.create_webhook(
name=name,
avatar=avatar_bytes,
reason=reason or f"Managed webhook created by {self.bot.user}"
)
# Track the webhook
self.webhook_usage[webhook.id] = {
'created_at': datetime.now(),
'channel_id': channel.id,
'guild_id': channel.guild.id,
'created_by_bot': True,
'last_used': None,
'use_count': 0
}
return webhook
def track_webhook_usage(self, webhook_id: int):
"""Track usage of a managed webhook."""
if webhook_id in self.webhook_usage:
self.webhook_usage[webhook_id]['last_used'] = datetime.now()
self.webhook_usage[webhook_id]['use_count'] += 1
async def get_webhook_statistics(self, guild: nextcord.Guild) -> Dict[str, Any]:
"""Get comprehensive webhook statistics for a guild."""
webhooks = await guild.webhooks()
stats = {
'total_webhooks': len(webhooks),
'webhooks_by_channel': {},
'webhooks_by_type': {},
'bot_created_webhooks': 0,
'user_created_webhooks': 0,
'managed_webhooks': len([wh_id for wh_id in self.webhook_usage if wh_id in [wh.id for wh in webhooks]])
}
for webhook in webhooks:
try:
webhook_info = await webhook.fetch()
# Count by channel
channel_name = webhook_info.channel.name if webhook_info.channel else 'Unknown'
stats['webhooks_by_channel'][channel_name] = stats['webhooks_by_channel'].get(channel_name, 0) + 1
# Count by type
webhook_type = str(webhook_info.type)
stats['webhooks_by_type'][webhook_type] = stats['webhooks_by_type'].get(webhook_type, 0) + 1
# Count by creator type
if webhook_info.user and webhook_info.user.bot:
stats['bot_created_webhooks'] += 1
else:
stats['user_created_webhooks'] += 1
except Exception:
pass # Skip webhooks we can't access
return stats
# Command examples for webhook management
class WebhookCommands:
"""Slash commands for webhook management."""
def __init__(self, bot, webhook_manager: WebhookManager):
self.bot = bot
self.webhook_manager = webhook_manager
@nextcord.slash_command(description="Audit server webhooks")
async def audit_webhooks(self, interaction: nextcord.Interaction):
"""Audit all webhooks in the server."""
if not interaction.user.guild_permissions.manage_webhooks:
await interaction.response.send_message(
"❌ You need 'Manage Webhooks' permission to use this command.",
ephemeral=True
)
return
await interaction.response.defer()
audit_results = await self.webhook_manager.audit_webhooks(interaction.guild)
embed = nextcord.Embed(
title="🔍 Webhook Audit Results",
color=nextcord.Color.blue()
)
embed.add_field(
name="Summary",
value=f"**Total:** {audit_results['total_webhooks']}\n"
f"**Active:** {audit_results['active_webhooks']}\n"
f"**Inactive:** {audit_results['inactive_webhooks']}\n"
f"**Errors:** {audit_results['unknown_webhooks']}",
inline=False
)
if audit_results['webhook_details']:
# Show first 10 webhooks
webhook_list = []
for webhook in audit_results['webhook_details'][:10]:
status_emoji = {"active": "✅", "inactive": "❌", "error": "⚠️"}
emoji = status_emoji.get(webhook['status'], "❓")
webhook_list.append(f"{emoji} **{webhook['name']}** (#{webhook.get('channel', 'Unknown')})")
embed.add_field(
name="Webhooks",
value="\n".join(webhook_list) +
(f"\n... and {len(audit_results['webhook_details']) - 10} more"
if len(audit_results['webhook_details']) > 10 else ""),
inline=False
)
await interaction.followup.send(embed=embed)
@nextcord.slash_command(description="Get webhook statistics")
async def webhook_stats(self, interaction: nextcord.Interaction):
"""Get comprehensive webhook statistics."""
if not interaction.user.guild_permissions.manage_webhooks:
await interaction.response.send_message(
"❌ You need 'Manage Webhooks' permission to use this command.",
ephemeral=True
)
return
await interaction.response.defer()
stats = await self.webhook_manager.get_webhook_statistics(interaction.guild)
embed = nextcord.Embed(
title="📊 Webhook Statistics",
color=nextcord.Color.green()
)
embed.add_field(
name="Overview",
value=f"**Total Webhooks:** {stats['total_webhooks']}\n"
f"**Bot Created:** {stats['bot_created_webhooks']}\n"
f"**User Created:** {stats['user_created_webhooks']}\n"
f"**Managed by Bot:** {stats['managed_webhooks']}",
inline=False
)
if stats['webhooks_by_channel']:
channels = list(stats['webhooks_by_channel'].items())[:5] # Top 5 channels
channel_text = "\n".join([f"#{channel}: {count}" for channel, count in channels])
embed.add_field(name="By Channel (Top 5)", value=channel_text, inline=True)
if stats['webhooks_by_type']:
type_text = "\n".join([f"{wh_type}: {count}" for wh_type, count in stats['webhooks_by_type'].items()])
embed.add_field(name="By Type", value=type_text, inline=True)
await interaction.followup.send(embed=embed)This comprehensive documentation covers all aspects of nextcord's webhook system, providing developers with the tools needed to implement flexible external integrations and messaging solutions.
Install with Tessl CLI
npx tessl i tessl/pypi-nextcord