0
# Nextcord Message and Communication API
1
2
Comprehensive documentation for nextcord's message handling and communication capabilities.
3
4
## Message Class
5
6
The core message representation with content, embeds, and attachments.
7
8
```python { .api }
9
import nextcord
10
from nextcord import Message, Embed, File
11
12
class Message:
13
"""Represents a message from Discord.
14
15
Attributes
16
----------
17
id: int
18
The message ID.
19
content: str
20
The actual contents of the message.
21
author: Union[Member, User]
22
The user or member who sent the message.
23
channel: Union[TextChannel, Thread, DMChannel, GroupChannel, PartialMessageable]
24
The channel the message was sent in.
25
guild: Optional[Guild]
26
The guild that the message belongs to, if applicable.
27
embeds: List[Embed]
28
A list of embeds the message has.
29
attachments: List[Attachment]
30
A list of attachments given to a message.
31
reactions: List[Reaction]
32
Reactions to a message.
33
reference: Optional[MessageReference]
34
The message that this message references (for replies).
35
mention_everyone: bool
36
Specifies if the message mentions everyone.
37
mentions: List[Union[User, Member]]
38
A list of users that were mentioned.
39
channel_mentions: List[GuildChannel]
40
A list of channels that were mentioned.
41
role_mentions: List[Role]
42
A list of roles that were mentioned.
43
pinned: bool
44
Specifies if the message is currently pinned.
45
tts: bool
46
Specifies if the message was done with text-to-speech.
47
type: MessageType
48
The type of message.
49
flags: MessageFlags
50
Extra features of the message.
51
created_at: datetime.datetime
52
The message's creation time in UTC.
53
edited_at: Optional[datetime.datetime]
54
The message's last edit time in UTC, if edited.
55
jump_url: str
56
Returns a URL that allows the client to jump to this message.
57
"""
58
59
# Message properties
60
@property
61
def clean_content(self) -> str:
62
"""str: A property that returns the content in a "cleaned up" manner.
63
64
This transforms mentions into the way the client shows it.
65
e.g. <#id> will transform into #name.
66
"""
67
...
68
69
@property
70
def system_content(self) -> str:
71
"""str: A property that returns the content that is rendered
72
regardless of the Message.type.
73
"""
74
...
75
76
@property
77
def raw_mentions(self) -> List[int]:
78
"""List[int]: A property that returns an array of user IDs matched
79
with the syntax of <@user_id> in the message content.
80
"""
81
...
82
83
@property
84
def raw_channel_mentions(self) -> List[int]:
85
"""List[int]: A property that returns an array of channel IDs matched
86
with the syntax of <#channel_id> in the message content.
87
"""
88
...
89
90
@property
91
def raw_role_mentions(self) -> List[int]:
92
"""List[int]: A property that returns an array of role IDs matched
93
with the syntax of <@&role_id> in the message content.
94
"""
95
...
96
97
def is_system(self) -> bool:
98
"""bool: Whether the message is a system message."""
99
...
100
101
def to_reference(self, *, fail_if_not_exists: bool = True) -> MessageReference:
102
"""Creates a MessageReference from the current message.
103
104
Parameters
105
----------
106
fail_if_not_exists: bool
107
Whether replying using the message reference should raise HTTPException
108
if the message no longer exists.
109
"""
110
...
111
```
112
113
## Message Sending
114
115
Sending messages with various content types through the Messageable interface.
116
117
```python { .api }
118
from typing import Optional, List, Sequence, Union
119
from nextcord import (
120
Embed, File, AllowedMentions, MessageReference, MessageFlags,
121
GuildSticker, StickerItem, View
122
)
123
from nextcord.abc import Messageable
124
125
class Messageable:
126
"""An ABC that details the common operations on a model that can send messages."""
127
128
async def send(
129
self,
130
content: Optional[str] = None,
131
*,
132
tts: bool = False,
133
embed: Optional[Embed] = None,
134
embeds: Optional[List[Embed]] = None,
135
file: Optional[File] = None,
136
files: Optional[List[File]] = None,
137
stickers: Optional[Sequence[Union[GuildSticker, StickerItem]]] = None,
138
delete_after: Optional[float] = None,
139
nonce: Optional[Union[str, int]] = None,
140
allowed_mentions: Optional[AllowedMentions] = None,
141
reference: Optional[Union[Message, MessageReference, PartialMessage]] = None,
142
mention_author: Optional[bool] = None,
143
view: Optional[View] = None,
144
flags: Optional[MessageFlags] = None,
145
suppress_embeds: Optional[bool] = None,
146
) -> Message:
147
"""Sends a message to the destination.
148
149
Parameters
150
----------
151
content: Optional[str]
152
The content of the message to send.
153
tts: bool
154
Indicates if the message should be sent using text-to-speech.
155
embed: Optional[Embed]
156
The rich embed for the content.
157
embeds: Optional[List[Embed]]
158
A list of embeds to send with the content. Maximum of 10.
159
file: Optional[File]
160
The file to upload.
161
files: Optional[List[File]]
162
A list of files to upload. Must be a maximum of 10.
163
stickers: Optional[Sequence[Union[GuildSticker, StickerItem]]]
164
A list of stickers to send with the message. Maximum of 3.
165
delete_after: Optional[float]
166
If provided, the number of seconds to wait before deleting the message.
167
nonce: Optional[Union[str, int]]
168
The nonce to use for sending this message.
169
allowed_mentions: Optional[AllowedMentions]
170
Controls the mentions being processed in this message.
171
reference: Optional[Union[Message, MessageReference, PartialMessage]]
172
A reference to the Message to which you are replying.
173
mention_author: Optional[bool]
174
If set, overrides the mention_author setting of reference.
175
view: Optional[View]
176
A UI view to add to the message.
177
flags: Optional[MessageFlags]
178
The flags to set for this message.
179
suppress_embeds: Optional[bool]
180
Whether to suppress embeds for the message.
181
182
Returns
183
-------
184
Message
185
The message that was sent.
186
"""
187
...
188
189
def typing(self) -> Typing:
190
"""Returns a context manager that allows you to send a typing indicator.
191
192
Example
193
-------
194
async with channel.typing():
195
# do expensive stuff here
196
await channel.send('done!')
197
"""
198
...
199
200
# Usage Examples
201
async def send_basic_message(channel):
202
"""Send a simple text message."""
203
await channel.send("Hello, world!")
204
205
async def send_message_with_embed(channel):
206
"""Send a message with an embed."""
207
embed = nextcord.Embed(title="My Embed", description="This is an embed!")
208
await channel.send("Check out this embed:", embed=embed)
209
210
async def send_message_with_file(channel):
211
"""Send a message with a file attachment."""
212
with open('image.png', 'rb') as f:
213
await channel.send("Here's an image:", file=nextcord.File(f, 'image.png'))
214
215
async def send_reply(message):
216
"""Reply to a message."""
217
await message.reply("This is a reply!")
218
```
219
220
## Message Editing
221
222
Modifying existing messages after they've been sent.
223
224
```python { .api }
225
class Message:
226
async def edit(
227
self,
228
*,
229
content: Optional[str] = MISSING,
230
embed: Optional[Embed] = MISSING,
231
embeds: Optional[List[Embed]] = MISSING,
232
attachments: Optional[List[Attachment]] = MISSING,
233
suppress: Optional[bool] = MISSING,
234
delete_after: Optional[float] = None,
235
allowed_mentions: Optional[AllowedMentions] = MISSING,
236
view: Optional[View] = MISSING,
237
file: Optional[File] = MISSING,
238
files: Optional[List[File]] = MISSING,
239
) -> Message:
240
"""Edits the message.
241
242
Parameters
243
----------
244
content: Optional[str]
245
The new content to replace the message with. Could be None to remove content.
246
embed: Optional[Embed]
247
The new embed to replace the original with. Could be None to remove embed.
248
embeds: Optional[List[Embed]]
249
The new embeds to replace the original with. Maximum of 10.
250
attachments: Optional[List[Attachment]]
251
A list of attachments to keep in the message.
252
suppress: Optional[bool]
253
Whether to suppress embeds for the message.
254
delete_after: Optional[float]
255
If provided, the number of seconds to wait before deleting the message.
256
allowed_mentions: Optional[AllowedMentions]
257
Controls the mentions being processed in this message.
258
view: Optional[View]
259
The updated view to update this message with.
260
file: Optional[File]
261
If provided, a new file to add to the message.
262
files: Optional[List[File]]
263
If provided, a list of new files to add to the message.
264
265
Returns
266
-------
267
Message
268
The edited message.
269
"""
270
...
271
272
async def delete(self, *, delay: Optional[float] = None) -> None:
273
"""Deletes the message.
274
275
Parameters
276
----------
277
delay: Optional[float]
278
If provided, the number of seconds to wait before deleting the message.
279
"""
280
...
281
282
class PartialMessage:
283
async def edit(self, **fields) -> Optional[Message]:
284
"""Edits the partial message.
285
286
Same parameters as Message.edit().
287
"""
288
...
289
290
# Usage Examples
291
async def edit_message_content(message):
292
"""Edit a message's content."""
293
await message.edit(content="This message has been edited!")
294
295
async def edit_message_embed(message):
296
"""Edit a message's embed."""
297
new_embed = nextcord.Embed(title="Updated", description="This embed was updated!")
298
await message.edit(embed=new_embed)
299
300
async def suppress_message_embeds(message):
301
"""Suppress embeds in a message."""
302
await message.edit(suppress=True)
303
```
304
305
## Embeds
306
307
Rich message formatting with fields, images, and styling.
308
309
```python { .api }
310
from nextcord import Embed, Colour
311
from datetime import datetime
312
from typing import Optional, Any, List
313
314
class Embed:
315
"""Represents a Discord embed.
316
317
Attributes
318
----------
319
title: Optional[str]
320
The title of the embed.
321
type: str
322
The type of embed. Usually "rich".
323
description: Optional[str]
324
The description of the embed.
325
url: Optional[str]
326
The hyperlink of the embed title.
327
timestamp: Optional[datetime.datetime]
328
The timestamp of the embed content.
329
colour: Optional[Colour]
330
The colour code of the embed. Aliased to color.
331
"""
332
333
def __init__(
334
self,
335
*,
336
colour: Optional[Union[int, Colour]] = None,
337
color: Optional[Union[int, Colour]] = None,
338
title: Optional[Any] = None,
339
type: str = "rich",
340
url: Optional[Any] = None,
341
description: Optional[Any] = None,
342
timestamp: Optional[datetime.datetime] = None,
343
):
344
"""Creates an embed object.
345
346
Parameters
347
----------
348
colour: Optional[Union[int, Colour]]
349
The colour code of the embed.
350
color: Optional[Union[int, Colour]]
351
Alias for colour.
352
title: Optional[str]
353
The title of the embed.
354
type: str
355
The type of embed. Defaults to "rich".
356
url: Optional[str]
357
The hyperlink of the embed title.
358
description: Optional[str]
359
The description of the embed.
360
timestamp: Optional[datetime.datetime]
361
The timestamp of the embed content.
362
"""
363
...
364
365
# Author methods
366
def set_author(
367
self,
368
*,
369
name: str,
370
url: Optional[str] = None,
371
icon_url: Optional[str] = None,
372
) -> Self:
373
"""Sets the author for the embed content.
374
375
Parameters
376
----------
377
name: str
378
The name of the author.
379
url: Optional[str]
380
The URL for the author.
381
icon_url: Optional[str]
382
The URL of the author icon.
383
"""
384
...
385
386
def remove_author(self) -> Self:
387
"""Clears embed's author information."""
388
...
389
390
# Footer methods
391
def set_footer(
392
self,
393
*,
394
text: Optional[str] = None,
395
icon_url: Optional[str] = None
396
) -> Self:
397
"""Sets the footer for the embed content.
398
399
Parameters
400
----------
401
text: Optional[str]
402
The footer text.
403
icon_url: Optional[str]
404
The URL of the footer icon.
405
"""
406
...
407
408
def remove_footer(self) -> Self:
409
"""Clears embed's footer information."""
410
...
411
412
# Image methods
413
def set_image(self, url: Optional[str]) -> Self:
414
"""Sets the image for the embed content.
415
416
Parameters
417
----------
418
url: Optional[str]
419
The source URL for the image. Pass None to remove.
420
"""
421
...
422
423
def set_thumbnail(self, url: Optional[str]) -> Self:
424
"""Sets the thumbnail for the embed content.
425
426
Parameters
427
----------
428
url: Optional[str]
429
The source URL for the thumbnail. Pass None to remove.
430
"""
431
...
432
433
# Field methods
434
def add_field(
435
self,
436
*,
437
name: str,
438
value: str,
439
inline: bool = True
440
) -> Self:
441
"""Adds a field to the embed object.
442
443
Parameters
444
----------
445
name: str
446
The name of the field.
447
value: str
448
The value of the field.
449
inline: bool
450
Whether the field should be displayed inline.
451
"""
452
...
453
454
def insert_field_at(
455
self,
456
index: int,
457
*,
458
name: str,
459
value: str,
460
inline: bool = True
461
) -> Self:
462
"""Inserts a field at a specified index.
463
464
Parameters
465
----------
466
index: int
467
The index of where to insert the field.
468
name: str
469
The name of the field.
470
value: str
471
The value of the field.
472
inline: bool
473
Whether the field should be displayed inline.
474
"""
475
...
476
477
def set_field_at(
478
self,
479
index: int,
480
*,
481
name: str,
482
value: str,
483
inline: bool = True
484
) -> Self:
485
"""Modifies a field at the specified index.
486
487
Parameters
488
----------
489
index: int
490
The index of the field to modify.
491
name: str
492
The name of the field.
493
value: str
494
The value of the field.
495
inline: bool
496
Whether the field should be displayed inline.
497
"""
498
...
499
500
def remove_field(self, index: int) -> Self:
501
"""Removes a field at a specified index.
502
503
Parameters
504
----------
505
index: int
506
The index of the field to remove.
507
"""
508
...
509
510
def clear_fields(self) -> Self:
511
"""Removes all fields from this embed."""
512
...
513
514
# Properties
515
@property
516
def fields(self) -> List[EmbedFieldProxy]:
517
"""List[EmbedFieldProxy]: Returns a list of EmbedProxy denoting the field contents."""
518
...
519
520
@property
521
def footer(self) -> EmbedFooterProxy:
522
"""EmbedFooterProxy: Returns an EmbedProxy denoting the footer contents."""
523
...
524
525
@property
526
def image(self) -> EmbedMediaProxy:
527
"""EmbedMediaProxy: Returns an EmbedProxy denoting the image contents."""
528
...
529
530
@property
531
def thumbnail(self) -> EmbedMediaProxy:
532
"""EmbedMediaProxy: Returns an EmbedProxy denoting the thumbnail contents."""
533
...
534
535
@property
536
def author(self) -> EmbedAuthorProxy:
537
"""EmbedAuthorProxy: Returns an EmbedProxy denoting the author contents."""
538
...
539
540
# Utility methods
541
def copy(self) -> Self:
542
"""Returns a shallow copy of the embed."""
543
...
544
545
def to_dict(self) -> EmbedData:
546
"""Converts this embed object into a dict."""
547
...
548
549
@classmethod
550
def from_dict(cls, data: Mapping[str, Any]) -> Self:
551
"""Converts a dict to an Embed."""
552
...
553
554
# Usage Examples
555
def create_basic_embed():
556
"""Create a basic embed."""
557
embed = nextcord.Embed(
558
title="My Embed Title",
559
description="This is the embed description.",
560
color=0x00ff00 # Green color
561
)
562
return embed
563
564
def create_rich_embed():
565
"""Create a rich embed with multiple elements."""
566
embed = nextcord.Embed(
567
title="Rich Embed",
568
description="A comprehensive embed example.",
569
color=nextcord.Colour.blue(),
570
timestamp=datetime.utcnow()
571
)
572
573
embed.set_author(
574
name="Author Name",
575
url="https://example.com",
576
icon_url="https://example.com/icon.png"
577
)
578
579
embed.set_thumbnail(url="https://example.com/thumbnail.png")
580
embed.set_image(url="https://example.com/image.png")
581
582
embed.add_field(name="Field 1", value="Value 1", inline=True)
583
embed.add_field(name="Field 2", value="Value 2", inline=True)
584
embed.add_field(name="Long Field", value="This field spans the full width", inline=False)
585
586
embed.set_footer(
587
text="Footer text",
588
icon_url="https://example.com/footer_icon.png"
589
)
590
591
return embed
592
```
593
594
## Attachments
595
596
File handling and attachment management.
597
598
```python { .api }
599
from nextcord import Attachment, File
600
from typing import Optional, Union
601
import io
602
from os import PathLike
603
604
class Attachment:
605
"""Represents an attachment from Discord.
606
607
Attributes
608
----------
609
id: int
610
The attachment ID.
611
size: int
612
The attachment size in bytes.
613
height: Optional[int]
614
The attachment's height, in pixels (images/videos only).
615
width: Optional[int]
616
The attachment's width, in pixels (images/videos only).
617
filename: str
618
The attachment's filename.
619
url: str
620
The attachment URL.
621
proxy_url: str
622
The proxy URL (cached version).
623
content_type: Optional[str]
624
The attachment's media type.
625
description: Optional[str]
626
The attachment's description.
627
"""
628
629
def is_spoiler(self) -> bool:
630
"""bool: Whether this attachment contains a spoiler."""
631
...
632
633
async def save(
634
self,
635
fp: Union[io.BufferedIOBase, PathLike, str],
636
*,
637
seek_begin: bool = True,
638
use_cached: bool = False,
639
) -> int:
640
"""Saves this attachment into a file-like object.
641
642
Parameters
643
----------
644
fp: Union[io.BufferedIOBase, PathLike, str]
645
The file-like object to save to or filename.
646
seek_begin: bool
647
Whether to seek to the beginning after saving.
648
use_cached: bool
649
Whether to use proxy_url rather than url.
650
651
Returns
652
-------
653
int
654
The number of bytes written.
655
"""
656
...
657
658
async def read(self, *, use_cached: bool = False) -> bytes:
659
"""Retrieves the content of this attachment as bytes.
660
661
Parameters
662
----------
663
use_cached: bool
664
Whether to use proxy_url rather than url.
665
666
Returns
667
-------
668
bytes
669
The contents of the attachment.
670
"""
671
...
672
673
async def to_file(
674
self,
675
*,
676
filename: Optional[str] = None,
677
description: Optional[str] = None,
678
use_cached: bool = False,
679
spoiler: bool = False,
680
force_close: bool = True,
681
) -> File:
682
"""Converts the attachment into a File suitable for sending.
683
684
Parameters
685
----------
686
filename: Optional[str]
687
The filename to use. If not specified, uses attachment filename.
688
description: Optional[str]
689
The description to use. If not specified, uses attachment description.
690
use_cached: bool
691
Whether to use proxy_url rather than url.
692
spoiler: bool
693
Whether the file is a spoiler.
694
force_close: bool
695
Whether to forcibly close the bytes when .close() is called.
696
697
Returns
698
-------
699
File
700
The attachment as a file suitable for sending.
701
"""
702
...
703
704
class File:
705
"""A parameter object used for sending file objects.
706
707
Attributes
708
----------
709
fp: Union[io.BufferedReader, io.BufferedIOBase]
710
A file-like object opened in binary mode and read mode.
711
filename: Optional[str]
712
The filename to display when uploading to Discord.
713
description: Optional[str]
714
The description for the file.
715
spoiler: bool
716
Whether the attachment is a spoiler.
717
force_close: bool
718
Whether to forcibly close the bytes when .close() is called.
719
"""
720
721
def __init__(
722
self,
723
fp: Union[str, bytes, PathLike, io.BufferedIOBase],
724
filename: Optional[str] = None,
725
*,
726
description: Optional[str] = None,
727
spoiler: bool = False,
728
force_close: Optional[bool] = None,
729
):
730
"""Creates a File object.
731
732
Parameters
733
----------
734
fp: Union[str, bytes, PathLike, io.BufferedIOBase]
735
A file-like object opened in binary mode or a filename.
736
filename: Optional[str]
737
The filename to display when uploading to Discord.
738
description: Optional[str]
739
The description for the file.
740
spoiler: bool
741
Whether the attachment is a spoiler.
742
force_close: Optional[bool]
743
Whether to forcibly close the bytes when .close() is called.
744
"""
745
...
746
747
def reset(self, *, seek: Union[int, bool] = True) -> None:
748
"""Reset the file position."""
749
...
750
751
def close(self) -> None:
752
"""Close the file."""
753
...
754
755
# Usage Examples
756
async def download_attachment(attachment):
757
"""Download an attachment to local file."""
758
await attachment.save(f"./downloads/{attachment.filename}")
759
760
async def read_attachment_content(attachment):
761
"""Read attachment content into memory."""
762
content = await attachment.read()
763
return content
764
765
async def resend_attachment(attachment, channel):
766
"""Convert attachment to file and resend."""
767
file = await attachment.to_file()
768
await channel.send("Reposting this file:", file=file)
769
770
def create_file_from_path():
771
"""Create a File from a local path."""
772
return nextcord.File("./image.png", description="My image")
773
774
def create_file_from_bytes():
775
"""Create a File from bytes in memory."""
776
data = b"Hello, world!"
777
return nextcord.File(io.BytesIO(data), filename="hello.txt")
778
```
779
780
## Reactions
781
782
Adding, removing, and managing message reactions.
783
784
```python { .api }
785
from nextcord import Reaction, Emoji, PartialEmoji
786
from nextcord.abc import Snowflake
787
from typing import Union, Optional
788
789
EmojiInputType = Union[Emoji, PartialEmoji, str]
790
791
class Message:
792
async def add_reaction(self, emoji: EmojiInputType) -> None:
793
"""Add a reaction to the message.
794
795
Parameters
796
----------
797
emoji: Union[Emoji, Reaction, PartialEmoji, str]
798
The emoji to react with.
799
"""
800
...
801
802
async def remove_reaction(
803
self,
804
emoji: Union[EmojiInputType, Reaction],
805
member: Snowflake
806
) -> None:
807
"""Remove a reaction by the member from the message.
808
809
Parameters
810
----------
811
emoji: Union[Emoji, Reaction, PartialEmoji, str]
812
The emoji to remove.
813
member: Snowflake
814
The member for which to remove the reaction.
815
"""
816
...
817
818
async def clear_reaction(self, emoji: Union[EmojiInputType, Reaction]) -> None:
819
"""Clears a specific reaction from the message.
820
821
Parameters
822
----------
823
emoji: Union[Emoji, Reaction, PartialEmoji, str]
824
The emoji to clear.
825
"""
826
...
827
828
async def clear_reactions(self) -> None:
829
"""Removes all the reactions from the message."""
830
...
831
832
class Reaction:
833
"""Represents a reaction to a message.
834
835
Attributes
836
----------
837
emoji: Union[Emoji, PartialEmoji, str]
838
The reaction emoji. May be a custom emoji, or a unicode emoji.
839
count: int
840
Number of times this reaction was made.
841
me: bool
842
If the user sent this reaction.
843
message: Message
844
Message this reaction is for.
845
"""
846
847
def is_custom_emoji(self) -> bool:
848
"""bool: If this is a custom emoji."""
849
...
850
851
async def remove(self, user: Snowflake) -> None:
852
"""Remove the reaction by the provided User from the message.
853
854
Parameters
855
----------
856
user: Snowflake
857
The user from which to remove the reaction.
858
"""
859
...
860
861
async def clear(self) -> None:
862
"""Clears this reaction from the message."""
863
...
864
865
def users(
866
self,
867
*,
868
limit: Optional[int] = None,
869
after: Optional[Snowflake] = None
870
) -> ReactionIterator:
871
"""Returns an AsyncIterator representing the users that have reacted.
872
873
Parameters
874
----------
875
limit: Optional[int]
876
The maximum number of results to return.
877
after: Optional[Snowflake]
878
For pagination, reactions are sorted by member.
879
880
Yields
881
------
882
Union[User, Member]
883
The users that have reacted to this message.
884
"""
885
...
886
887
# Usage Examples
888
async def add_reactions(message):
889
"""Add multiple reactions to a message."""
890
await message.add_reaction("š")
891
await message.add_reaction("š")
892
await message.add_reaction("ā¤ļø")
893
894
async def remove_user_reaction(message, user):
895
"""Remove a specific user's reaction."""
896
await message.remove_reaction("š", user)
897
898
async def clear_specific_reaction(message):
899
"""Clear all instances of a specific reaction."""
900
await message.clear_reaction("š")
901
902
async def clear_all_reactions(message):
903
"""Remove all reactions from a message."""
904
await message.clear_reactions()
905
906
async def get_reaction_users(message):
907
"""Get users who reacted with thumbs up."""
908
for reaction in message.reactions:
909
if str(reaction.emoji) == "š":
910
async for user in reaction.users():
911
print(f"{user.name} reacted with š")
912
```
913
914
## Message References
915
916
Replies, message references, and threading.
917
918
```python { .api }
919
from nextcord import MessageReference, Message, PartialMessage
920
from typing import Optional, Union
921
922
class MessageReference:
923
"""Represents a reference to a Message.
924
925
Attributes
926
----------
927
message_id: Optional[int]
928
The id of the message referenced.
929
channel_id: int
930
The channel id of the message referenced.
931
guild_id: Optional[int]
932
The guild id of the message referenced.
933
fail_if_not_exists: bool
934
Whether replying should raise HTTPException if message no longer exists.
935
resolved: Optional[Union[Message, DeletedReferencedMessage]]
936
The message that this reference resolved to.
937
"""
938
939
def __init__(
940
self,
941
*,
942
message_id: int,
943
channel_id: int,
944
guild_id: Optional[int] = None,
945
fail_if_not_exists: bool = True,
946
):
947
"""Creates a MessageReference.
948
949
Parameters
950
----------
951
message_id: int
952
The id of the message to reference.
953
channel_id: int
954
The channel id of the message to reference.
955
guild_id: Optional[int]
956
The guild id of the message to reference.
957
fail_if_not_exists: bool
958
Whether to raise an exception if the message doesn't exist.
959
"""
960
...
961
962
@classmethod
963
def from_message(
964
cls,
965
message: Message,
966
*,
967
fail_if_not_exists: bool = True
968
) -> MessageReference:
969
"""Creates a MessageReference from an existing Message.
970
971
Parameters
972
----------
973
message: Message
974
The message to be converted into a reference.
975
fail_if_not_exists: bool
976
Whether replying should raise HTTPException if message no longer exists.
977
978
Returns
979
-------
980
MessageReference
981
A reference to the message.
982
"""
983
...
984
985
@property
986
def cached_message(self) -> Optional[Message]:
987
"""Optional[Message]: The cached message, if found in the internal message cache."""
988
...
989
990
@property
991
def jump_url(self) -> str:
992
"""str: Returns a URL that allows the client to jump to the referenced message."""
993
...
994
995
class Message:
996
async def reply(
997
self,
998
content: Optional[str] = None,
999
**kwargs
1000
) -> Message:
1001
"""A shortcut method to reply to the Message.
1002
1003
This is equivalent to:
1004
1005
await message.channel.send(content, reference=message, **kwargs)
1006
1007
Parameters
1008
----------
1009
content: Optional[str]
1010
The content of the message to send.
1011
**kwargs
1012
Keyword arguments to pass to send().
1013
1014
Returns
1015
-------
1016
Message
1017
The message that was sent.
1018
"""
1019
...
1020
1021
def to_reference(self, *, fail_if_not_exists: bool = True) -> MessageReference:
1022
"""Creates a MessageReference from the current message.
1023
1024
Parameters
1025
----------
1026
fail_if_not_exists: bool
1027
Whether replying using the message reference should raise HTTPException.
1028
1029
Returns
1030
-------
1031
MessageReference
1032
The reference to this message.
1033
"""
1034
...
1035
1036
# Usage Examples
1037
async def reply_to_message(message):
1038
"""Reply to a message."""
1039
await message.reply("This is a reply to your message!")
1040
1041
async def reply_without_mention(message):
1042
"""Reply without mentioning the author."""
1043
await message.reply("This won't mention you!", mention_author=False)
1044
1045
async def create_manual_reference(channel, message_id):
1046
"""Create a manual message reference."""
1047
reference = nextcord.MessageReference(
1048
message_id=message_id,
1049
channel_id=channel.id,
1050
guild_id=channel.guild.id if channel.guild else None
1051
)
1052
await channel.send("Replying to an older message", reference=reference)
1053
1054
async def reply_with_embed(message):
1055
"""Reply with an embed."""
1056
embed = nextcord.Embed(title="Reply", description="This is a reply with an embed!")
1057
await message.reply(embed=embed)
1058
```
1059
1060
## File Uploads
1061
1062
Uploading files and images to Discord.
1063
1064
```python { .api }
1065
from nextcord import File
1066
import io
1067
from typing import Optional, List, Union
1068
from os import PathLike
1069
1070
# File Creation Methods
1071
def create_file_from_path(path: str, *, spoiler: bool = False) -> File:
1072
"""Create a File from a local file path."""
1073
return File(path, spoiler=spoiler)
1074
1075
def create_file_from_bytes(
1076
data: bytes,
1077
filename: str,
1078
*,
1079
spoiler: bool = False
1080
) -> File:
1081
"""Create a File from bytes in memory."""
1082
return File(io.BytesIO(data), filename=filename, spoiler=spoiler)
1083
1084
def create_spoiler_file(path: str) -> File:
1085
"""Create a spoiler file (prefixes filename with SPOILER_)."""
1086
return File(path, spoiler=True)
1087
1088
# Sending Files
1089
async def send_single_file(channel):
1090
"""Send a single file."""
1091
file = nextcord.File("./image.png", description="An example image")
1092
await channel.send("Here's an image:", file=file)
1093
1094
async def send_multiple_files(channel):
1095
"""Send multiple files at once."""
1096
files = [
1097
nextcord.File("./image1.png"),
1098
nextcord.File("./image2.png"),
1099
nextcord.File("./document.pdf")
1100
]
1101
await channel.send("Multiple files:", files=files)
1102
1103
async def send_file_with_embed(channel):
1104
"""Send a file along with an embed."""
1105
file = nextcord.File("./data.json")
1106
embed = nextcord.Embed(title="Data File", description="JSON data export")
1107
await channel.send(embed=embed, file=file)
1108
1109
# Dynamic File Creation
1110
async def send_text_file(channel, content: str, filename: str):
1111
"""Create and send a text file from string content."""
1112
file_data = content.encode('utf-8')
1113
file = nextcord.File(io.BytesIO(file_data), filename=filename)
1114
await channel.send("Generated file:", file=file)
1115
1116
async def send_json_data(channel, data: dict):
1117
"""Send JSON data as a file."""
1118
import json
1119
json_str = json.dumps(data, indent=2)
1120
json_bytes = json_str.encode('utf-8')
1121
file = nextcord.File(io.BytesIO(json_bytes), filename="data.json")
1122
await channel.send("JSON data export:", file=file)
1123
1124
# File Context Manager Usage
1125
async def send_with_context_manager(channel):
1126
"""Use File as a context manager for automatic cleanup."""
1127
with nextcord.File("./large_file.zip") as file:
1128
await channel.send("Large file upload:", file=file)
1129
# File is automatically closed after sending
1130
```
1131
1132
## Message Components
1133
1134
Buttons and select menus within messages.
1135
1136
```python { .api }
1137
from nextcord import ButtonStyle, ComponentType
1138
from nextcord.ui import Button, Select, View
1139
from typing import List, Optional
1140
1141
class Button:
1142
"""Represents a button component.
1143
1144
Attributes
1145
----------
1146
style: ButtonStyle
1147
The style of the button.
1148
custom_id: Optional[str]
1149
The ID of the button that gets received during an interaction.
1150
url: Optional[str]
1151
The URL this button sends you to.
1152
disabled: bool
1153
Whether the button is disabled or not.
1154
label: Optional[str]
1155
The label of the button, if any.
1156
emoji: Optional[PartialEmoji]
1157
The emoji of the button, if available.
1158
"""
1159
pass
1160
1161
class StringSelectMenu:
1162
"""Represents a string select menu component.
1163
1164
Attributes
1165
----------
1166
custom_id: str
1167
The ID of the select menu.
1168
placeholder: Optional[str]
1169
The placeholder text that is shown if nothing is selected.
1170
min_values: int
1171
The minimum number of items that must be chosen.
1172
max_values: int
1173
The maximum number of items that must be chosen.
1174
options: List[SelectOption]
1175
A list of options that can be selected.
1176
disabled: bool
1177
Whether the select is disabled or not.
1178
"""
1179
pass
1180
1181
class SelectOption:
1182
"""Represents an option in a select menu.
1183
1184
Attributes
1185
----------
1186
label: str
1187
The user-facing name of the option.
1188
value: str
1189
The dev-defined value of the option.
1190
description: Optional[str]
1191
An additional description of the option.
1192
emoji: Optional[PartialEmoji]
1193
An emoji that appears on the option.
1194
default: bool
1195
Whether this option is selected by default.
1196
"""
1197
pass
1198
1199
# Usage with Views
1200
from nextcord.ui import View, Button, Select
1201
1202
class MyView(View):
1203
def __init__(self):
1204
super().__init__()
1205
1206
@nextcord.ui.button(label='Click me!', style=nextcord.ButtonStyle.primary)
1207
async def button_callback(self, button: Button, interaction: nextcord.Interaction):
1208
await interaction.response.send_message('Button was clicked!', ephemeral=True)
1209
1210
@nextcord.ui.select(
1211
placeholder='Choose an option...',
1212
options=[
1213
nextcord.SelectOption(label='Option 1', value='1'),
1214
nextcord.SelectOption(label='Option 2', value='2'),
1215
nextcord.SelectOption(label='Option 3', value='3'),
1216
]
1217
)
1218
async def select_callback(self, select: Select, interaction: nextcord.Interaction):
1219
await interaction.response.send_message(f'You chose {select.values[0]}!', ephemeral=True)
1220
1221
# Sending Messages with Components
1222
async def send_message_with_components(channel):
1223
"""Send a message with interactive components."""
1224
view = MyView()
1225
await channel.send("This message has components:", view=view)
1226
1227
async def send_button_message(channel):
1228
"""Send a message with just buttons."""
1229
class ButtonView(View):
1230
@nextcord.ui.button(label='Primary', style=nextcord.ButtonStyle.primary)
1231
async def primary_button(self, button: Button, interaction: nextcord.Interaction):
1232
await interaction.response.send_message('Primary button clicked!', ephemeral=True)
1233
1234
@nextcord.ui.button(label='Secondary', style=nextcord.ButtonStyle.secondary)
1235
async def secondary_button(self, button: Button, interaction: nextcord.Interaction):
1236
await interaction.response.send_message('Secondary button clicked!', ephemeral=True)
1237
1238
@nextcord.ui.button(label='Danger', style=nextcord.ButtonStyle.danger)
1239
async def danger_button(self, button: Button, interaction: nextcord.Interaction):
1240
await interaction.response.send_message('Danger button clicked!', ephemeral=True)
1241
1242
view = ButtonView()
1243
await channel.send("Choose an action:", view=view)
1244
1245
async def send_select_message(channel):
1246
"""Send a message with a select menu."""
1247
class SelectView(View):
1248
@nextcord.ui.select(
1249
placeholder='Pick your favorite color...',
1250
options=[
1251
nextcord.SelectOption(label='Red', value='red', emoji='š“'),
1252
nextcord.SelectOption(label='Blue', value='blue', emoji='šµ'),
1253
nextcord.SelectOption(label='Green', value='green', emoji='š¢'),
1254
]
1255
)
1256
async def color_select(self, select: Select, interaction: nextcord.Interaction):
1257
color = select.values[0]
1258
await interaction.response.send_message(f'You picked {color}!', ephemeral=True)
1259
1260
view = SelectView()
1261
await channel.send("What's your favorite color?", view=view)
1262
```
1263
1264
## Message Flags
1265
1266
Message properties and metadata.
1267
1268
```python { .api }
1269
from nextcord.flags import MessageFlags
1270
1271
class MessageFlags:
1272
"""Wraps up a Discord Message flag value.
1273
1274
Attributes
1275
----------
1276
value: int
1277
The raw value. This is a bit array field representing available flags.
1278
"""
1279
1280
@property
1281
def crossposted(self) -> bool:
1282
"""bool: Returns True if the message is the original crossposted message."""
1283
...
1284
1285
@property
1286
def is_crossposted(self) -> bool:
1287
"""bool: Returns True if the message was crossposted from another channel."""
1288
...
1289
1290
@property
1291
def suppress_embeds(self) -> bool:
1292
"""bool: Returns True if the message's embeds have been suppressed."""
1293
...
1294
1295
@property
1296
def source_message_deleted(self) -> bool:
1297
"""bool: Returns True if the source message for this crosspost has been deleted."""
1298
...
1299
1300
@property
1301
def urgent(self) -> bool:
1302
"""bool: Returns True if the message is an urgent message."""
1303
...
1304
1305
@property
1306
def has_thread(self) -> bool:
1307
"""bool: Returns True if the message has an associated thread."""
1308
...
1309
1310
@property
1311
def ephemeral(self) -> bool:
1312
"""bool: Returns True if the message is ephemeral."""
1313
...
1314
1315
@property
1316
def loading(self) -> bool:
1317
"""bool: Returns True if the message is a loading state."""
1318
...
1319
1320
@property
1321
def failed_to_mention_some_roles_in_thread(self) -> bool:
1322
"""bool: Returns True if the message failed to mention some roles in thread."""
1323
...
1324
1325
# Usage Examples
1326
def check_message_flags(message):
1327
"""Check various message flags."""
1328
if message.flags.crossposted:
1329
print("This message was crossposted from another channel")
1330
1331
if message.flags.suppress_embeds:
1332
print("This message has suppressed embeds")
1333
1334
if message.flags.has_thread:
1335
print("This message has a thread")
1336
1337
if message.flags.ephemeral:
1338
print("This message is ephemeral")
1339
1340
async def suppress_message_embeds(message):
1341
"""Suppress embeds in a message by editing it."""
1342
await message.edit(suppress=True)
1343
1344
async def send_message_with_flags(channel):
1345
"""Send a message with specific flags."""
1346
flags = nextcord.MessageFlags()
1347
flags.suppress_embeds = True
1348
await channel.send("This message will have suppressed embeds", flags=flags)
1349
1350
# Working with announcement channels
1351
async def publish_announcement(message):
1352
"""Publish a message in an announcement channel."""
1353
if message.channel.type == nextcord.ChannelType.news:
1354
await message.publish()
1355
print("Message published to followers")
1356
```
1357
1358
## Complete Usage Examples
1359
1360
Comprehensive examples combining multiple message features.
1361
1362
```python { .api }
1363
import nextcord
1364
from nextcord.ext import commands
1365
from datetime import datetime
1366
import io
1367
1368
class MessageExamples:
1369
"""Complete examples of message functionality."""
1370
1371
@staticmethod
1372
async def comprehensive_message_example(channel):
1373
"""Send a comprehensive message with multiple features."""
1374
1375
# Create a rich embed
1376
embed = nextcord.Embed(
1377
title="š Status Report",
1378
description="Daily server statistics and information.",
1379
color=nextcord.Colour.blue(),
1380
timestamp=datetime.utcnow()
1381
)
1382
1383
embed.set_author(
1384
name="Server Bot",
1385
icon_url="https://example.com/bot_avatar.png"
1386
)
1387
1388
embed.add_field(name="š„ Members", value="1,234", inline=True)
1389
embed.add_field(name="š± Online", value="456", inline=True)
1390
embed.add_field(name="šÆ Active", value="89", inline=True)
1391
1392
embed.add_field(
1393
name="š Today's Activity",
1394
value="⢠50 messages sent\n⢠12 new members\n⢠5 events created",
1395
inline=False
1396
)
1397
1398
embed.set_thumbnail(url="https://example.com/server_icon.png")
1399
embed.set_footer(text="Last updated", icon_url="https://example.com/clock.png")
1400
1401
# Create a file attachment
1402
report_data = {
1403
"date": datetime.utcnow().isoformat(),
1404
"members": 1234,
1405
"messages": 50,
1406
"events": 5
1407
}
1408
1409
import json
1410
json_data = json.dumps(report_data, indent=2).encode('utf-8')
1411
file = nextcord.File(io.BytesIO(json_data), filename="daily_report.json")
1412
1413
# Create interactive components
1414
class ReportView(nextcord.ui.View):
1415
@nextcord.ui.button(label="š Detailed Stats", style=nextcord.ButtonStyle.primary)
1416
async def detailed_stats(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
1417
await interaction.response.send_message("Fetching detailed statistics...", ephemeral=True)
1418
1419
@nextcord.ui.button(label="š Refresh", style=nextcord.ButtonStyle.secondary)
1420
async def refresh(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
1421
await interaction.response.send_message("Report refreshed!", ephemeral=True)
1422
1423
@nextcord.ui.select(
1424
placeholder="Choose a time period...",
1425
options=[
1426
nextcord.SelectOption(label="Last 24 hours", value="24h", emoji="š"),
1427
nextcord.SelectOption(label="Last 7 days", value="7d", emoji="š "),
1428
nextcord.SelectOption(label="Last 30 days", value="30d", emoji="š"),
1429
]
1430
)
1431
async def time_period(self, select: nextcord.ui.Select, interaction: nextcord.Interaction):
1432
period = select.values[0]
1433
await interaction.response.send_message(f"Showing data for: {period}", ephemeral=True)
1434
1435
# Send the comprehensive message
1436
view = ReportView()
1437
message = await channel.send(
1438
content="**š Daily Server Report**\nHere's your server's daily activity summary:",
1439
embed=embed,
1440
file=file,
1441
view=view
1442
)
1443
1444
# Add some reactions
1445
await message.add_reaction("š")
1446
await message.add_reaction("š")
1447
await message.add_reaction("š")
1448
1449
return message
1450
1451
@staticmethod
1452
async def conversation_flow_example(channel):
1453
"""Example of a conversation flow with replies and references."""
1454
1455
# Initial message
1456
initial_message = await channel.send(
1457
"š® **Game Night Planning**\n"
1458
"Who's interested in game night this Friday? React below!"
1459
)
1460
1461
await initial_message.add_reaction("ā ") # Yes
1462
await initial_message.add_reaction("ā") # No
1463
await initial_message.add_reaction("š¤") # Maybe
1464
1465
# Follow-up with embed
1466
embed = nextcord.Embed(
1467
title="šÆ Game Options",
1468
description="Vote for which games you'd like to play!",
1469
color=nextcord.Colour.green()
1470
)
1471
1472
embed.add_field(name="š² Board Games", value="Monopoly, Risk, Settlers", inline=False)
1473
embed.add_field(name="š® Video Games", value="Among Us, Jackbox, Fall Guys", inline=False)
1474
embed.add_field(name="š Card Games", value="Uno, Poker, Cards Against Humanity", inline=False)
1475
1476
games_message = await initial_message.reply(
1477
embed=embed,
1478
mention_author=False # Don't ping everyone
1479
)
1480
1481
# Create a poll with reactions
1482
game_emojis = ["š²", "š®", "š"]
1483
for emoji in game_emojis:
1484
await games_message.add_reaction(emoji)
1485
1486
return initial_message, games_message
1487
1488
@staticmethod
1489
async def file_sharing_example(channel):
1490
"""Example of various file sharing scenarios."""
1491
1492
# Text file from string
1493
content = """
1494
# Meeting Notes - 2024-01-15
1495
1496
## Attendees
1497
- Alice
1498
- Bob
1499
- Charlie
1500
1501
## Topics Discussed
1502
1. Project timeline
1503
2. Budget allocation
1504
3. Next steps
1505
1506
## Action Items
1507
- [ ] Alice: Update project plan
1508
- [ ] Bob: Review budget
1509
- [ ] Charlie: Schedule follow-up
1510
"""
1511
1512
notes_file = nextcord.File(
1513
io.BytesIO(content.encode('utf-8')),
1514
filename="meeting_notes.md",
1515
description="Meeting notes from today's discussion"
1516
)
1517
1518
# Image with spoiler
1519
# Assuming we have an image file
1520
spoiler_image = nextcord.File("./spoiler_image.png", spoiler=True)
1521
1522
# Multiple files
1523
files = [notes_file, spoiler_image]
1524
1525
embed = nextcord.Embed(
1526
title="š File Share",
1527
description="Meeting notes and images from today's session",
1528
color=nextcord.Colour.purple()
1529
)
1530
1531
await channel.send(
1532
"š **Files from today's meeting:**",
1533
embed=embed,
1534
files=files
1535
)
1536
1537
@staticmethod
1538
async def error_handling_example(channel):
1539
"""Example with proper error handling for message operations."""
1540
1541
try:
1542
# Attempt to send a message with potential issues
1543
embed = nextcord.Embed(title="Test Embed")
1544
message = await channel.send(embed=embed)
1545
1546
# Try to edit the message
1547
await message.edit(content="Updated content")
1548
1549
# Try to add reactions
1550
await message.add_reaction("ā ")
1551
1552
# Try to reply
1553
reply = await message.reply("Operation successful!")
1554
1555
# Schedule deletion
1556
await reply.delete(delay=10.0)
1557
1558
except nextcord.Forbidden:
1559
print("Missing permissions for this operation")
1560
except nextcord.HTTPException as e:
1561
print(f"HTTP error occurred: {e}")
1562
except nextcord.NotFound:
1563
print("Message or channel not found")
1564
except Exception as e:
1565
print(f"Unexpected error: {e}")
1566
1567
# Bot command examples using nextcord.ext.commands
1568
class MessageCommands(commands.Cog):
1569
"""Command examples for message functionality."""
1570
1571
@commands.command()
1572
async def embed_info(self, ctx, *, title: str):
1573
"""Create an embed with user input."""
1574
embed = nextcord.Embed(
1575
title=title,
1576
description=f"Created by {ctx.author.mention}",
1577
color=nextcord.Colour.random(),
1578
timestamp=datetime.utcnow()
1579
)
1580
embed.set_footer(text=f"Requested by {ctx.author}", icon_url=ctx.author.avatar.url)
1581
await ctx.send(embed=embed)
1582
1583
@commands.command()
1584
async def quote(self, ctx, message_id: int):
1585
"""Quote a message by ID."""
1586
try:
1587
message = await ctx.fetch_message(message_id)
1588
1589
embed = nextcord.Embed(
1590
description=message.content,
1591
timestamp=message.created_at,
1592
color=nextcord.Colour.blue()
1593
)
1594
embed.set_author(
1595
name=message.author.display_name,
1596
icon_url=message.author.avatar.url
1597
)
1598
embed.set_footer(text=f"Originally sent in #{message.channel.name}")
1599
1600
await ctx.send(f"š¬ **Quote from {message.author.mention}:**", embed=embed)
1601
1602
except nextcord.NotFound:
1603
await ctx.send("ā Message not found!")
1604
except nextcord.Forbidden:
1605
await ctx.send("ā I don't have permission to read that message!")
1606
1607
@commands.command()
1608
async def poll(self, ctx, question: str, *options):
1609
"""Create a poll with reactions."""
1610
if len(options) < 2:
1611
await ctx.send("ā Please provide at least 2 options!")
1612
return
1613
1614
if len(options) > 10:
1615
await ctx.send("ā Maximum 10 options allowed!")
1616
return
1617
1618
embed = nextcord.Embed(
1619
title="š Poll",
1620
description=question,
1621
color=nextcord.Colour.blue()
1622
)
1623
1624
reactions = ["1ļøā£", "2ļøā£", "3ļøā£", "4ļøā£", "5ļøā£", "6ļøā£", "7ļøā£", "8ļøā£", "9ļøā£", "š"]
1625
1626
for i, option in enumerate(options):
1627
embed.add_field(
1628
name=f"{reactions[i]} Option {i+1}",
1629
value=option,
1630
inline=False
1631
)
1632
1633
message = await ctx.send(embed=embed)
1634
1635
for i in range(len(options)):
1636
await message.add_reaction(reactions[i])
1637
```
1638
1639
This comprehensive documentation covers all the major aspects of nextcord's message and communication capabilities, including practical examples and proper error handling. The documentation follows the Knowledge Tile format with API blocks and complete type definitions, making it a valuable reference for developers working with nextcord.