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

webhooks.mddocs/

Nextcord Webhooks

Webhook creation and management for external integrations and message delivery outside of bot connections, providing flexible communication channels.

Webhook Class

Core webhook functionality for sending messages and managing webhook properties.

Async Webhook { .api }

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")

Sync Webhook { .api }

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)}), 500

Webhook Message

Messages sent through webhooks with editing and deletion capabilities.

WebhookMessage Class { .api }

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
        }
    )

Webhook Management

Advanced webhook management including creation, monitoring, and cleanup.

Guild Webhook Operations { .api }

# 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

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