A modern, easy-to-use, feature-rich async-ready API wrapper for Discord written in Python
—
Comprehensive channel types and messaging functionality supporting all Discord channel types including text channels, voice channels, threads, forums, and direct messages. Includes full message management with rich content support.
Guild text channels for message-based communication with full message history and permission management.
class TextChannel:
def __init__(self): ...
id: int
name: str
guild: Guild
position: int
topic: Optional[str]
category: Optional[CategoryChannel]
slowmode_delay: int
nsfw: bool
default_auto_archive_duration: int
permissions_synced: bool
async def send(
self,
content: Optional[str] = None,
*,
tts: bool = False,
embed: Optional[Embed] = None,
embeds: Optional[List[Embed]] = None,
file: Optional[File] = None,
files: Optional[List[File]] = None,
allowed_mentions: Optional[AllowedMentions] = None,
reference: Optional[Union[Message, MessageReference, PartialMessage]] = None,
mention_author: Optional[bool] = None,
view: Optional[View] = None,
components: Optional[Union[ActionRow, List[ActionRow], List[List[Component]], List[Component]]] = None,
delete_after: Optional[float] = None,
suppress_embeds: bool = False,
flags: Optional[MessageFlags] = None
) -> Message:
"""
Send a message to this channel.
Parameters:
- content: Message text content
- tts: Whether message should be read with text-to-speech
- embed: Single embed to include
- embeds: List of embeds to include (max 10)
- file: Single file to attach
- files: List of files to attach (max 10)
- allowed_mentions: Controls @ mentions in the message
- reference: Message to reply to
- mention_author: Whether to mention the author when replying
- view: UI components view
- components: Raw components to include
- delete_after: Seconds after which to delete the message
- suppress_embeds: Whether to suppress embeds
- flags: Message flags
Returns:
The sent message
"""
async def fetch_message(self, id: int) -> Message:
"""
Fetch a specific message by ID.
Parameters:
- id: Message ID
Returns:
Message object
"""
def get_partial_message(self, message_id: int) -> PartialMessage:
"""
Create a partial message object for API calls.
Parameters:
- message_id: Message ID
Returns:
Partial message object
"""
def history(
self,
*,
limit: Optional[int] = 100,
before: Optional[Union[Snowflake, datetime]] = None,
after: Optional[Union[Snowflake, datetime]] = None,
around: Optional[Union[Snowflake, datetime]] = None,
oldest_first: Optional[bool] = None
) -> AsyncIterator[Message]:
"""
Iterate through message history.
Parameters:
- limit: Maximum messages to retrieve
- before: Retrieve messages before this message/time
- after: Retrieve messages after this message/time
- around: Retrieve messages around this message/time
- oldest_first: Whether to return oldest messages first
Returns:
Async iterator of messages
"""
async def purge(
self,
*,
limit: int = 100,
check: Optional[Callable[[Message], bool]] = None,
before: Optional[Union[Snowflake, datetime]] = None,
after: Optional[Union[Snowflake, datetime]] = None,
around: Optional[Union[Snowflake, datetime]] = None,
oldest_first: Optional[bool] = False,
bulk: Optional[bool] = True,
reason: Optional[str] = None
) -> List[Message]:
"""
Bulk delete messages from the channel.
Parameters:
- limit: Maximum messages to delete
- check: Function to check if message should be deleted
- before: Delete messages before this message/time
- after: Delete messages after this message/time
- around: Delete messages around this message/time
- oldest_first: Whether to delete oldest messages first
- bulk: Whether to use bulk delete API
- reason: Reason for deletion (audit log)
Returns:
List of deleted messages
"""
async def create_thread(
self,
*,
name: str,
message: Optional[Message] = None,
auto_archive_duration: Optional[int] = None,
type: Optional[ChannelType] = None,
reason: Optional[str] = None
) -> Thread:
"""
Create a thread in this channel.
Parameters:
- name: Thread name
- message: Message to create thread from (optional)
- auto_archive_duration: Thread auto-archive duration
- type: Thread type
- reason: Reason for creation (audit log)
Returns:
Created thread
"""
async def edit(
self,
*,
name: Optional[str] = None,
topic: Optional[str] = None,
position: Optional[int] = None,
nsfw: Optional[bool] = None,
sync_permissions: Optional[bool] = None,
category: Optional[CategoryChannel] = None,
slowmode_delay: Optional[int] = None,
type: Optional[ChannelType] = None,
default_auto_archive_duration: Optional[int] = None,
overwrites: Optional[Dict[Union[Role, Member], PermissionOverwrite]] = None,
reason: Optional[str] = None
) -> Optional[TextChannel]:
"""
Edit channel properties.
Parameters:
- name: New channel name
- topic: New channel topic
- position: New channel position
- nsfw: Whether channel is NSFW
- sync_permissions: Whether to sync with category permissions
- category: Channel category
- slowmode_delay: Slowmode delay in seconds
- type: Channel type
- default_auto_archive_duration: Default thread archive duration
- overwrites: Permission overwrites
- reason: Reason for edit (audit log)
Returns:
Updated channel
"""Guild voice channels for voice and video communication with connection management.
class VoiceChannel:
def __init__(self): ...
id: int
name: str
guild: Guild
position: int
category: Optional[CategoryChannel]
bitrate: int
user_limit: int
rtc_region: Optional[str]
video_quality_mode: VideoQualityMode
members: List[Member]
async def connect(
self,
*,
timeout: float = 60.0,
reconnect: bool = True,
cls: Type[VoiceProtocol] = VoiceClient
) -> VoiceClient:
"""
Connect to this voice channel.
Parameters:
- timeout: Connection timeout
- reconnect: Whether to reconnect on disconnect
- cls: Voice client class to use
Returns:
Voice client connection
"""
async def edit(
self,
*,
name: Optional[str] = None,
bitrate: Optional[int] = None,
user_limit: Optional[int] = None,
position: Optional[int] = None,
sync_permissions: Optional[bool] = None,
category: Optional[CategoryChannel] = None,
overwrites: Optional[Dict[Union[Role, Member], PermissionOverwrite]] = None,
rtc_region: Optional[Union[str, VoiceRegion]] = None,
video_quality_mode: Optional[VideoQualityMode] = None,
reason: Optional[str] = None
) -> Optional[VoiceChannel]:
"""
Edit voice channel properties.
Parameters:
- name: New channel name
- bitrate: Audio bitrate (8000-384000)
- user_limit: Maximum users (0 for unlimited)
- position: New channel position
- sync_permissions: Whether to sync with category permissions
- category: Channel category
- overwrites: Permission overwrites
- rtc_region: Voice region
- video_quality_mode: Video quality mode
- reason: Reason for edit (audit log)
Returns:
Updated channel
"""Special voice channels designed for stage events and presentations.
class StageChannel:
def __init__(self): ...
id: int
name: str
guild: Guild
topic: Optional[str]
bitrate: int
user_limit: int
rtc_region: Optional[str]
async def create_instance(
self,
*,
topic: str,
privacy_level: Optional[StagePrivacyLevel] = None,
reason: Optional[str] = None
) -> StageInstance:
"""
Create a stage instance for this channel.
Parameters:
- topic: Stage topic
- privacy_level: Privacy level for the stage
- reason: Reason for creation (audit log)
Returns:
Created stage instance
"""
@property
def instance(self) -> Optional[StageInstance]:
"""Current stage instance if active."""Private channels for direct messaging between users.
class DMChannel:
def __init__(self): ...
id: int
recipient: User
me: ClientUser
async def send(
self,
content: Optional[str] = None,
*,
tts: bool = False,
embed: Optional[Embed] = None,
embeds: Optional[List[Embed]] = None,
file: Optional[File] = None,
files: Optional[List[File]] = None,
allowed_mentions: Optional[AllowedMentions] = None,
reference: Optional[Union[Message, MessageReference, PartialMessage]] = None,
mention_author: Optional[bool] = None,
view: Optional[View] = None,
components: Optional[Union[ActionRow, List[ActionRow], List[List[Component]], List[Component]]] = None,
delete_after: Optional[float] = None,
suppress_embeds: bool = False,
flags: Optional[MessageFlags] = None
) -> Message:
"""Send a message to this DM channel."""Forum-style channels with posts and threads for organized discussions.
class ForumChannel:
def __init__(self): ...
id: int
name: str
guild: Guild
topic: Optional[str]
position: int
category: Optional[CategoryChannel]
slowmode_delay: int
nsfw: bool
default_auto_archive_duration: int
default_thread_slowmode_delay: int
available_tags: List[ForumTag]
default_reaction_emoji: Optional[Union[str, PartialEmoji]]
default_sort_order: Optional[ThreadSortOrder]
default_layout: ForumLayout
async def create_thread(
self,
*,
name: str,
content: Optional[str] = None,
embed: Optional[Embed] = None,
embeds: Optional[List[Embed]] = None,
file: Optional[File] = None,
files: Optional[List[File]] = None,
allowed_mentions: Optional[AllowedMentions] = None,
view: Optional[View] = None,
components: Optional[Union[ActionRow, List[ActionRow], List[List[Component]], List[Component]]] = None,
auto_archive_duration: Optional[int] = None,
slowmode_delay: Optional[int] = None,
applied_tags: Optional[List[ForumTag]] = None,
reason: Optional[str] = None
) -> Thread:
"""
Create a forum post (thread) with initial message.
Parameters:
- name: Thread/post name
- content: Initial message content
- embed: Single embed for initial message
- embeds: List of embeds for initial message
- file: Single file for initial message
- files: List of files for initial message
- allowed_mentions: Controls @ mentions
- view: UI components for initial message
- components: Raw components for initial message
- auto_archive_duration: Thread auto-archive duration
- slowmode_delay: Thread slowmode delay
- applied_tags: Forum tags to apply
- reason: Reason for creation (audit log)
Returns:
Created forum thread
"""Thread channels for organized conversations branching from main channels.
class Thread:
def __init__(self): ...
id: int
name: str
guild: Guild
parent: Optional[Union[TextChannel, ForumChannel]]
owner: Optional[Member]
slowmode_delay: int
message_count: int
member_count: int
archive_timestamp: Optional[datetime]
auto_archive_duration: int
archived: bool
locked: bool
invitable: bool
applied_tags: List[ForumTag]
async def edit(
self,
*,
name: Optional[str] = None,
archived: Optional[bool] = None,
auto_archive_duration: Optional[int] = None,
locked: Optional[bool] = None,
invitable: Optional[bool] = None,
slowmode_delay: Optional[int] = None,
applied_tags: Optional[List[ForumTag]] = None,
reason: Optional[str] = None
) -> Thread:
"""
Edit thread properties.
Parameters:
- name: New thread name
- archived: Whether thread is archived
- auto_archive_duration: Auto-archive duration
- locked: Whether thread is locked
- invitable: Whether non-moderators can add members
- slowmode_delay: Slowmode delay in seconds
- applied_tags: Forum tags (forum threads only)
- reason: Reason for edit (audit log)
Returns:
Updated thread
"""
async def add_user(self, user: Union[Member, User]) -> None:
"""
Add a user to this thread.
Parameters:
- user: User to add
"""
async def remove_user(self, user: Union[Member, User]) -> None:
"""
Remove a user from this thread.
Parameters:
- user: User to remove
"""
async def join(self) -> None:
"""Join this thread as the bot."""
async def leave(self) -> None:
"""Leave this thread as the bot."""Message objects representing individual messages with rich content support.
class Message:
def __init__(self): ...
id: int
content: str
channel: Union[TextChannel, DMChannel, GroupChannel, Thread, VoiceChannel, StageChannel, ForumChannel, PartialMessageable]
author: Union[User, Member]
attachments: List[Attachment]
embeds: List[Embed]
mentions: List[Union[User, Member]]
channel_mentions: List[GuildChannel]
role_mentions: List[Role]
mention_everyone: bool
pinned: bool
tts: bool
type: MessageType
flags: MessageFlags
reference: Optional[MessageReference]
interaction: Optional[MessageInteraction]
thread: Optional[Thread]
components: List[ActionRow]
stickers: List[StickerItem]
created_at: datetime
edited_at: Optional[datetime]
async def edit(
self,
content: Optional[str] = None,
*,
embed: Optional[Embed] = None,
embeds: Optional[List[Embed]] = None,
attachments: Optional[List[Union[Attachment, File]]] = None,
view: Optional[View] = None,
components: Optional[Union[ActionRow, List[ActionRow], List[List[Component]], List[Component]]] = None,
allowed_mentions: Optional[AllowedMentions] = None,
delete_after: Optional[float] = None,
suppress_embeds: Optional[bool] = None,
flags: Optional[MessageFlags] = None
) -> Message:
"""
Edit this message.
Parameters:
- content: New message content
- embed: Single embed to replace existing embeds
- embeds: List of embeds to replace existing embeds
- attachments: List of attachments/files to replace existing attachments
- view: UI components view
- components: Raw components
- allowed_mentions: Controls @ mentions
- delete_after: Seconds after which to delete the message
- suppress_embeds: Whether to suppress embeds
- flags: Message flags
Returns:
Updated message
"""
async def delete(self, *, delay: Optional[float] = None, reason: Optional[str] = None) -> None:
"""
Delete this message.
Parameters:
- delay: Delay before deletion in seconds
- reason: Reason for deletion (audit log)
"""
async def pin(self, *, reason: Optional[str] = None) -> None:
"""
Pin this message.
Parameters:
- reason: Reason for pinning (audit log)
"""
async def unpin(self, *, reason: Optional[str] = None) -> None:
"""
Unpin this message.
Parameters:
- reason: Reason for unpinning (audit log)
"""
async def add_reaction(self, emoji: Union[Emoji, PartialEmoji, str]) -> None:
"""
Add a reaction to this message.
Parameters:
- emoji: Emoji to react with
"""
async def remove_reaction(self, emoji: Union[Emoji, PartialEmoji, str], member: Union[Member, User]) -> None:
"""
Remove a reaction from this message.
Parameters:
- emoji: Emoji reaction to remove
- member: User whose reaction to remove
"""
async def clear_reaction(self, emoji: Union[Emoji, PartialEmoji, str]) -> None:
"""
Clear all reactions of a specific emoji.
Parameters:
- emoji: Emoji reactions to clear
"""
async def clear_reactions(self) -> None:
"""Clear all reactions from this message."""
async def reply(
self,
content: Optional[str] = None,
*,
tts: bool = False,
embed: Optional[Embed] = None,
embeds: Optional[List[Embed]] = None,
file: Optional[File] = None,
files: Optional[List[File]] = None,
allowed_mentions: Optional[AllowedMentions] = None,
mention_author: Optional[bool] = None,
view: Optional[View] = None,
components: Optional[Union[ActionRow, List[ActionRow], List[List[Component]], List[Component]]] = None,
delete_after: Optional[float] = None,
suppress_embeds: bool = False,
flags: Optional[MessageFlags] = None
) -> Message:
"""
Reply to this message.
Parameters:
- content: Reply content
- tts: Whether reply should use text-to-speech
- embed: Single embed
- embeds: List of embeds
- file: Single file
- files: List of files
- allowed_mentions: Controls @ mentions
- mention_author: Whether to mention the original author
- view: UI components
- components: Raw components
- delete_after: Seconds after which to delete reply
- suppress_embeds: Whether to suppress embeds
- flags: Message flags
Returns:
Reply message
"""
def to_reference(self, *, fail_if_not_exists: bool = True) -> MessageReference:
"""
Create a message reference for replying.
Parameters:
- fail_if_not_exists: Whether to fail if message doesn't exist
Returns:
Message reference object
"""Rich embed objects for formatted message content with multiple fields and media.
class Embed:
def __init__(
self,
*,
title: Optional[str] = None,
type: str = 'rich',
description: Optional[str] = None,
url: Optional[str] = None,
timestamp: Optional[datetime] = None,
color: Optional[Union[int, Color]] = None,
colour: Optional[Union[int, Colour]] = None
):
"""
Create a rich embed.
Parameters:
- title: Embed title
- type: Embed type (usually 'rich')
- description: Embed description
- url: URL for embed title
- timestamp: Embed timestamp
- color: Embed color
- colour: Embed colour (alias for color)
"""
title: Optional[str]
type: str
description: Optional[str]
url: Optional[str]
timestamp: Optional[datetime]
color: Optional[Color]
fields: List[EmbedField]
footer: Optional[EmbedFooter]
image: Optional[EmbedMedia]
thumbnail: Optional[EmbedMedia]
video: Optional[EmbedMedia]
provider: Optional[EmbedProvider]
author: Optional[EmbedAuthor]
def add_field(self, *, name: str, value: str, inline: bool = True) -> Self:
"""
Add a field to the embed.
Parameters:
- name: Field name
- value: Field value
- inline: Whether field should be inline
Returns:
Self for method chaining
"""
def insert_field_at(self, index: int, *, name: str, value: str, inline: bool = True) -> Self:
"""
Insert a field at a specific index.
Parameters:
- index: Index to insert at
- name: Field name
- value: Field value
- inline: Whether field should be inline
Returns:
Self for method chaining
"""
def set_field_at(self, index: int, *, name: str, value: str, inline: bool = True) -> Self:
"""
Set a field at a specific index.
Parameters:
- index: Index to set
- name: Field name
- value: Field value
- inline: Whether field should be inline
Returns:
Self for method chaining
"""
def remove_field(self, index: int) -> None:
"""
Remove a field by index.
Parameters:
- index: Field index to remove
"""
def set_footer(self, *, text: str, icon_url: Optional[str] = None) -> Self:
"""
Set embed footer.
Parameters:
- text: Footer text
- icon_url: Footer icon URL
Returns:
Self for method chaining
"""
def set_image(self, *, url: str) -> Self:
"""
Set embed image.
Parameters:
- url: Image URL
Returns:
Self for method chaining
"""
def set_thumbnail(self, *, url: str) -> Self:
"""
Set embed thumbnail.
Parameters:
- url: Thumbnail URL
Returns:
Self for method chaining
"""
def set_author(self, *, name: str, url: Optional[str] = None, icon_url: Optional[str] = None) -> Self:
"""
Set embed author.
Parameters:
- name: Author name
- url: Author URL
- icon_url: Author icon URL
Returns:
Self for method chaining
"""
def clear_fields(self) -> None:
"""Remove all fields from the embed."""
def copy(self) -> Self:
"""Create a copy of this embed."""
def to_dict(self) -> Dict[str, Any]:
"""Convert embed to dictionary for API calls."""import disnake
channel = bot.get_channel(123456789)
# Simple text message
await channel.send("Hello, world!")
# Message with embed
embed = disnake.Embed(
title="Status Update",
description="Bot is now online!",
color=disnake.Color.green()
)
embed.add_field(name="Version", value="2.10.1", inline=True)
embed.add_field(name="Uptime", value="5 minutes", inline=True)
embed.set_footer(text="Powered by Disnake")
await channel.send(embed=embed)
# Message with file attachment
with open('image.png', 'rb') as f:
file = disnake.File(f, filename='screenshot.png')
await channel.send("Here's a screenshot:", file=file)
# Reply to a message
@bot.event
async def on_message(message):
if message.content == "!ping":
await message.reply("Pong!")# Get last 50 messages
async for message in channel.history(limit=50):
print(f"{message.author}: {message.content}")
# Purge messages from a specific user
def is_spam(message):
return message.author.id == 123456789 and len(message.content) < 5
deleted = await channel.purge(limit=100, check=is_spam)
print(f"Deleted {len(deleted)} spam messages")
# Fetch a specific message
message = await channel.fetch_message(987654321)
await message.edit(content="Updated content!")# Create a thread from a message
message = await channel.send("Let's discuss this topic!")
thread = await message.create_thread(name="Discussion Thread")
# Create a standalone thread
thread = await channel.create_thread(
name="Announcements",
type=disnake.ChannelType.public_thread
)
# Join and manage thread
await thread.join()
await thread.add_user(member)
await thread.send("Welcome to the thread!")
# Archive thread
await thread.edit(archived=True)# Create a forum post
forum_channel = bot.get_channel(123456789)
thread = await forum_channel.create_thread(
name="Bug Report: Login Issues",
content="I'm experiencing login problems...",
applied_tags=[bug_tag, priority_high_tag]
)
# Add reaction to the initial post
initial_message = await thread.fetch_message(thread.id)
await initial_message.add_reaction("👍")Install with Tessl CLI
npx tessl i tessl/pypi-disnake