0
# Event Handling
1
2
Comprehensive event system for responding to Discord activities including messages, reactions, member changes, guild updates, and voice state changes. Discord.py provides both high-level events and raw gateway events for detailed control over bot behavior.
3
4
## Capabilities
5
6
### Core Events
7
8
Essential events for bot functionality and user interactions.
9
10
```python { .api }
11
@client.event
12
async def on_ready():
13
"""
14
Called when the client has successfully connected to Discord.
15
Bot is fully ready to process events and commands.
16
"""
17
pass
18
19
@client.event
20
async def on_resumed():
21
"""
22
Called when the client has resumed a session.
23
"""
24
pass
25
26
@client.event
27
async def on_connect():
28
"""
29
Called when the client has connected to Discord's gateway.
30
This may be called multiple times during reconnections.
31
"""
32
pass
33
34
@client.event
35
async def on_disconnect():
36
"""
37
Called when the client has disconnected from Discord's gateway.
38
"""
39
pass
40
41
@client.event
42
async def on_shard_connect(shard_id: int):
43
"""
44
Called when a shard connects to Discord.
45
46
Parameters:
47
- shard_id: ID of the connected shard
48
"""
49
pass
50
51
@client.event
52
async def on_shard_disconnect(shard_id: int):
53
"""
54
Called when a shard disconnects from Discord.
55
56
Parameters:
57
- shard_id: ID of the disconnected shard
58
"""
59
pass
60
61
@client.event
62
async def on_shard_ready(shard_id: int):
63
"""
64
Called when a shard becomes ready.
65
66
Parameters:
67
- shard_id: ID of the ready shard
68
"""
69
pass
70
71
@client.event
72
async def on_shard_resumed(shard_id: int):
73
"""
74
Called when a shard resumes a session.
75
76
Parameters:
77
- shard_id: ID of the resumed shard
78
"""
79
pass
80
```
81
82
### Message Events
83
84
Events for message creation, editing, deletion, and reactions.
85
86
```python { .api }
87
@client.event
88
async def on_message(message: Message):
89
"""
90
Called when a message is created.
91
92
Parameters:
93
- message: The message that was created
94
"""
95
pass
96
97
@client.event
98
async def on_message_edit(before: Message, after: Message):
99
"""
100
Called when a message is edited.
101
102
Parameters:
103
- before: Message before editing
104
- after: Message after editing
105
"""
106
pass
107
108
@client.event
109
async def on_message_delete(message: Message):
110
"""
111
Called when a message is deleted.
112
113
Parameters:
114
- message: The deleted message (may be partial)
115
"""
116
pass
117
118
@client.event
119
async def on_bulk_message_delete(messages: List[Message]):
120
"""
121
Called when multiple messages are deleted at once.
122
123
Parameters:
124
- messages: List of deleted messages
125
"""
126
pass
127
128
@client.event
129
async def on_reaction_add(reaction: Reaction, user: Union[User, Member]):
130
"""
131
Called when a reaction is added to a message.
132
133
Parameters:
134
- reaction: The reaction that was added
135
- user: User who added the reaction
136
"""
137
pass
138
139
@client.event
140
async def on_reaction_remove(reaction: Reaction, user: Union[User, Member]):
141
"""
142
Called when a reaction is removed from a message.
143
144
Parameters:
145
- reaction: The reaction that was removed
146
- user: User who removed the reaction
147
"""
148
pass
149
150
@client.event
151
async def on_reaction_clear(message: Message, reactions: List[Reaction]):
152
"""
153
Called when all reactions are cleared from a message.
154
155
Parameters:
156
- message: Message that had reactions cleared
157
- reactions: List of reactions that were cleared
158
"""
159
pass
160
161
@client.event
162
async def on_reaction_clear_emoji(reaction: Reaction):
163
"""
164
Called when all reactions of a specific emoji are cleared.
165
166
Parameters:
167
- reaction: The reaction that was cleared
168
"""
169
pass
170
171
@client.event
172
async def on_typing(channel: Messageable, user: Union[User, Member], when: datetime):
173
"""
174
Called when someone starts typing.
175
176
Parameters:
177
- channel: Channel where typing started
178
- user: User who started typing
179
- when: When typing started
180
"""
181
pass
182
```
183
184
### Guild Events
185
186
Events for guild (server) management and changes.
187
188
```python { .api }
189
@client.event
190
async def on_guild_join(guild: Guild):
191
"""
192
Called when the bot joins a guild.
193
194
Parameters:
195
- guild: Guild that was joined
196
"""
197
pass
198
199
@client.event
200
async def on_guild_remove(guild: Guild):
201
"""
202
Called when the bot is removed from a guild.
203
204
Parameters:
205
- guild: Guild that was left
206
"""
207
pass
208
209
@client.event
210
async def on_guild_update(before: Guild, after: Guild):
211
"""
212
Called when a guild is updated.
213
214
Parameters:
215
- before: Guild before update
216
- after: Guild after update
217
"""
218
pass
219
220
@client.event
221
async def on_guild_available(guild: Guild):
222
"""
223
Called when a guild becomes available.
224
225
Parameters:
226
- guild: Guild that became available
227
"""
228
pass
229
230
@client.event
231
async def on_guild_unavailable(guild: Guild):
232
"""
233
Called when a guild becomes unavailable.
234
235
Parameters:
236
- guild: Guild that became unavailable
237
"""
238
pass
239
240
@client.event
241
async def on_guild_channel_create(channel: GuildChannel):
242
"""
243
Called when a guild channel is created.
244
245
Parameters:
246
- channel: Channel that was created
247
"""
248
pass
249
250
@client.event
251
async def on_guild_channel_delete(channel: GuildChannel):
252
"""
253
Called when a guild channel is deleted.
254
255
Parameters:
256
- channel: Channel that was deleted
257
"""
258
pass
259
260
@client.event
261
async def on_guild_channel_update(before: GuildChannel, after: GuildChannel):
262
"""
263
Called when a guild channel is updated.
264
265
Parameters:
266
- before: Channel before update
267
- after: Channel after update
268
"""
269
pass
270
271
@client.event
272
async def on_guild_channel_pins_update(channel: Union[TextChannel, DMChannel, GroupChannel], last_pin: Optional[datetime]):
273
"""
274
Called when channel pins are updated.
275
276
Parameters:
277
- channel: Channel with pin update
278
- last_pin: Timestamp of most recent pin
279
"""
280
pass
281
282
@client.event
283
async def on_guild_integrations_update(guild: Guild):
284
"""
285
Called when guild integrations are updated.
286
287
Parameters:
288
- guild: Guild with integration update
289
"""
290
pass
291
292
@client.event
293
async def on_webhooks_update(channel: TextChannel):
294
"""
295
Called when channel webhooks are updated.
296
297
Parameters:
298
- channel: Channel with webhook update
299
"""
300
pass
301
302
@client.event
303
async def on_guild_role_create(role: Role):
304
"""
305
Called when a guild role is created.
306
307
Parameters:
308
- role: Role that was created
309
"""
310
pass
311
312
@client.event
313
async def on_guild_role_delete(role: Role):
314
"""
315
Called when a guild role is deleted.
316
317
Parameters:
318
- role: Role that was deleted
319
"""
320
pass
321
322
@client.event
323
async def on_guild_role_update(before: Role, after: Role):
324
"""
325
Called when a guild role is updated.
326
327
Parameters:
328
- before: Role before update
329
- after: Role after update
330
"""
331
pass
332
333
@client.event
334
async def on_guild_emojis_update(guild: Guild, before: List[Emoji], after: List[Emoji]):
335
"""
336
Called when guild emojis are updated.
337
338
Parameters:
339
- guild: Guild with emoji update
340
- before: Emojis before update
341
- after: Emojis after update
342
"""
343
pass
344
345
@client.event
346
async def on_guild_stickers_update(guild: Guild, before: List[GuildSticker], after: List[GuildSticker]):
347
"""
348
Called when guild stickers are updated.
349
350
Parameters:
351
- guild: Guild with sticker update
352
- before: Stickers before update
353
- after: Stickers after update
354
"""
355
pass
356
```
357
358
### Member Events
359
360
Events for member management, joins, leaves, and updates.
361
362
```python { .api }
363
@client.event
364
async def on_member_join(member: Member):
365
"""
366
Called when a member joins a guild.
367
368
Parameters:
369
- member: Member who joined
370
"""
371
pass
372
373
@client.event
374
async def on_member_remove(member: Member):
375
"""
376
Called when a member leaves a guild.
377
378
Parameters:
379
- member: Member who left
380
"""
381
pass
382
383
@client.event
384
async def on_member_update(before: Member, after: Member):
385
"""
386
Called when a member is updated.
387
388
Parameters:
389
- before: Member before update
390
- after: Member after update
391
"""
392
pass
393
394
@client.event
395
async def on_user_update(before: User, after: User):
396
"""
397
Called when a user updates their profile.
398
399
Parameters:
400
- before: User before update
401
- after: User after update
402
"""
403
pass
404
405
@client.event
406
async def on_member_ban(guild: Guild, user: Union[User, Member]):
407
"""
408
Called when a member is banned from a guild.
409
410
Parameters:
411
- guild: Guild where ban occurred
412
- user: User who was banned
413
"""
414
pass
415
416
@client.event
417
async def on_member_unban(guild: Guild, user: User):
418
"""
419
Called when a member is unbanned from a guild.
420
421
Parameters:
422
- guild: Guild where unban occurred
423
- user: User who was unbanned
424
"""
425
pass
426
427
@client.event
428
async def on_presence_update(before: Member, after: Member):
429
"""
430
Called when a member's presence is updated.
431
Requires PRESENCE_UPDATE intent.
432
433
Parameters:
434
- before: Member before presence update
435
- after: Member after presence update
436
"""
437
pass
438
```
439
440
### Voice Events
441
442
Events for voice channel activity and state changes.
443
444
```python { .api }
445
@client.event
446
async def on_voice_state_update(member: Member, before: VoiceState, after: VoiceState):
447
"""
448
Called when a member's voice state changes.
449
450
Parameters:
451
- member: Member whose voice state changed
452
- before: Voice state before change
453
- after: Voice state after change
454
"""
455
pass
456
457
@client.event
458
async def on_stage_instance_create(stage_instance: StageInstance):
459
"""
460
Called when a stage instance is created.
461
462
Parameters:
463
- stage_instance: Stage instance that was created
464
"""
465
pass
466
467
@client.event
468
async def on_stage_instance_delete(stage_instance: StageInstance):
469
"""
470
Called when a stage instance is deleted.
471
472
Parameters:
473
- stage_instance: Stage instance that was deleted
474
"""
475
pass
476
477
@client.event
478
async def on_stage_instance_update(before: StageInstance, after: StageInstance):
479
"""
480
Called when a stage instance is updated.
481
482
Parameters:
483
- before: Stage instance before update
484
- after: Stage instance after update
485
"""
486
pass
487
```
488
489
### Interaction Events
490
491
Events for slash commands, buttons, select menus, and other interactions.
492
493
```python { .api }
494
@client.event
495
async def on_interaction(interaction: Interaction):
496
"""
497
Called when an interaction is received.
498
499
Parameters:
500
- interaction: The interaction that was received
501
"""
502
pass
503
504
@client.event
505
async def on_application_command_error(interaction: Interaction, error: AppCommandError):
506
"""
507
Called when an application command raises an error.
508
509
Parameters:
510
- interaction: Interaction that caused the error
511
- error: Error that was raised
512
"""
513
pass
514
515
@client.event
516
async def on_app_command_completion(interaction: Interaction, command: Union[Command, ContextMenu]):
517
"""
518
Called when an application command completes successfully.
519
520
Parameters:
521
- interaction: Interaction that completed
522
- command: Command that was executed
523
"""
524
pass
525
```
526
527
### Thread Events
528
529
Events for thread creation, deletion, and management.
530
531
```python { .api }
532
@client.event
533
async def on_thread_create(thread: Thread):
534
"""
535
Called when a thread is created.
536
537
Parameters:
538
- thread: Thread that was created
539
"""
540
pass
541
542
@client.event
543
async def on_thread_delete(thread: Thread):
544
"""
545
Called when a thread is deleted.
546
547
Parameters:
548
- thread: Thread that was deleted
549
"""
550
pass
551
552
@client.event
553
async def on_thread_update(before: Thread, after: Thread):
554
"""
555
Called when a thread is updated.
556
557
Parameters:
558
- before: Thread before update
559
- after: Thread after update
560
"""
561
pass
562
563
@client.event
564
async def on_thread_member_join(member: ThreadMember):
565
"""
566
Called when a member joins a thread.
567
568
Parameters:
569
- member: Thread member who joined
570
"""
571
pass
572
573
@client.event
574
async def on_thread_member_remove(member: ThreadMember):
575
"""
576
Called when a member leaves a thread.
577
578
Parameters:
579
- member: Thread member who left
580
"""
581
pass
582
583
@client.event
584
async def on_thread_join(thread: Thread):
585
"""
586
Called when the bot joins a thread.
587
588
Parameters:
589
- thread: Thread that was joined
590
"""
591
pass
592
593
@client.event
594
async def on_thread_remove(thread: Thread):
595
"""
596
Called when the bot is removed from a thread.
597
598
Parameters:
599
- thread: Thread that was left
600
"""
601
pass
602
```
603
604
### Scheduled Event Events
605
606
Events for guild scheduled events.
607
608
```python { .api }
609
@client.event
610
async def on_scheduled_event_create(event: ScheduledEvent):
611
"""
612
Called when a scheduled event is created.
613
614
Parameters:
615
- event: Scheduled event that was created
616
"""
617
pass
618
619
@client.event
620
async def on_scheduled_event_delete(event: ScheduledEvent):
621
"""
622
Called when a scheduled event is deleted.
623
624
Parameters:
625
- event: Scheduled event that was deleted
626
"""
627
pass
628
629
@client.event
630
async def on_scheduled_event_update(before: ScheduledEvent, after: ScheduledEvent):
631
"""
632
Called when a scheduled event is updated.
633
634
Parameters:
635
- before: Event before update
636
- after: Event after update
637
"""
638
pass
639
640
@client.event
641
async def on_scheduled_event_user_add(event: ScheduledEvent, user: User):
642
"""
643
Called when a user subscribes to a scheduled event.
644
645
Parameters:
646
- event: Scheduled event
647
- user: User who subscribed
648
"""
649
pass
650
651
@client.event
652
async def on_scheduled_event_user_remove(event: ScheduledEvent, user: User):
653
"""
654
Called when a user unsubscribes from a scheduled event.
655
656
Parameters:
657
- event: Scheduled event
658
- user: User who unsubscribed
659
"""
660
pass
661
```
662
663
### Auto Moderation Events
664
665
Events for Discord's auto-moderation system.
666
667
```python { .api }
668
@client.event
669
async def on_automod_rule_create(rule: AutoModRule):
670
"""
671
Called when an auto-moderation rule is created.
672
673
Parameters:
674
- rule: Auto-moderation rule that was created
675
"""
676
pass
677
678
@client.event
679
async def on_automod_rule_delete(rule: AutoModRule):
680
"""
681
Called when an auto-moderation rule is deleted.
682
683
Parameters:
684
- rule: Auto-moderation rule that was deleted
685
"""
686
pass
687
688
@client.event
689
async def on_automod_rule_update(before: AutoModRule, after: AutoModRule):
690
"""
691
Called when an auto-moderation rule is updated.
692
693
Parameters:
694
- before: Rule before update
695
- after: Rule after update
696
"""
697
pass
698
699
@client.event
700
async def on_automod_action(execution: AutoModAction):
701
"""
702
Called when an auto-moderation action is executed.
703
704
Parameters:
705
- execution: Auto-moderation action execution
706
"""
707
pass
708
```
709
710
### Raw Events
711
712
Low-level events providing raw Discord gateway data.
713
714
```python { .api }
715
@client.event
716
async def on_raw_message_edit(payload: RawMessageUpdateEvent):
717
"""
718
Called when a message is edited (raw event).
719
720
Parameters:
721
- payload: Raw message update data
722
"""
723
pass
724
725
@client.event
726
async def on_raw_message_delete(payload: RawMessageDeleteEvent):
727
"""
728
Called when a message is deleted (raw event).
729
730
Parameters:
731
- payload: Raw message delete data
732
"""
733
pass
734
735
@client.event
736
async def on_raw_bulk_message_delete(payload: RawBulkMessageDeleteEvent):
737
"""
738
Called when messages are bulk deleted (raw event).
739
740
Parameters:
741
- payload: Raw bulk delete data
742
"""
743
pass
744
745
@client.event
746
async def on_raw_reaction_add(payload: RawReactionActionEvent):
747
"""
748
Called when a reaction is added (raw event).
749
750
Parameters:
751
- payload: Raw reaction data
752
"""
753
pass
754
755
@client.event
756
async def on_raw_reaction_remove(payload: RawReactionActionEvent):
757
"""
758
Called when a reaction is removed (raw event).
759
760
Parameters:
761
- payload: Raw reaction data
762
"""
763
pass
764
765
@client.event
766
async def on_raw_reaction_clear(payload: RawReactionClearEvent):
767
"""
768
Called when reactions are cleared (raw event).
769
770
Parameters:
771
- payload: Raw reaction clear data
772
"""
773
pass
774
775
@client.event
776
async def on_raw_reaction_clear_emoji(payload: RawReactionClearEmojiEvent):
777
"""
778
Called when emoji reactions are cleared (raw event).
779
780
Parameters:
781
- payload: Raw emoji clear data
782
"""
783
pass
784
785
@client.event
786
async def on_raw_typing(payload: RawTypingEvent):
787
"""
788
Called when typing starts (raw event).
789
790
Parameters:
791
- payload: Raw typing data
792
"""
793
pass
794
795
@client.event
796
async def on_raw_member_remove(payload: RawMemberRemoveEvent):
797
"""
798
Called when a member leaves (raw event).
799
800
Parameters:
801
- payload: Raw member remove data
802
"""
803
pass
804
805
@client.event
806
async def on_raw_thread_update(payload: RawThreadUpdateEvent):
807
"""
808
Called when a thread is updated (raw event).
809
810
Parameters:
811
- payload: Raw thread update data
812
"""
813
pass
814
815
@client.event
816
async def on_raw_thread_delete(payload: RawThreadDeleteEvent):
817
"""
818
Called when a thread is deleted (raw event).
819
820
Parameters:
821
- payload: Raw thread delete data
822
"""
823
pass
824
825
@client.event
826
async def on_raw_app_command_permissions_update(payload: RawAppCommandPermissionsUpdateEvent):
827
"""
828
Called when app command permissions are updated (raw event).
829
830
Parameters:
831
- payload: Raw permissions update data
832
"""
833
pass
834
```
835
836
### Error Events
837
838
Events for handling errors and exceptions.
839
840
```python { .api }
841
@client.event
842
async def on_error(event: str, *args, **kwargs):
843
"""
844
Called when an event handler raises an uncaught exception.
845
846
Parameters:
847
- event: Name of the event that raised the exception
848
- args: Positional arguments passed to the event
849
- kwargs: Keyword arguments passed to the event
850
"""
851
pass
852
853
@client.event
854
async def on_command_error(ctx: Context, error: CommandError):
855
"""
856
Called when a command raises an error.
857
Only available when using the commands extension.
858
859
Parameters:
860
- ctx: Command context
861
- error: Error that was raised
862
"""
863
pass
864
```
865
866
## Raw Event Payloads
867
868
Raw event payload classes for low-level event handling:
869
870
```python { .api }
871
class RawMessageUpdateEvent:
872
"""Raw message update event payload."""
873
message_id: int # Message ID
874
channel_id: int # Channel ID
875
guild_id: Optional[int] # Guild ID
876
data: Dict[str, Any] # Message data
877
cached_message: Optional[Message] # Cached message if available
878
879
class RawMessageDeleteEvent:
880
"""Raw message delete event payload."""
881
message_id: int # Deleted message ID
882
channel_id: int # Channel ID
883
guild_id: Optional[int] # Guild ID
884
cached_message: Optional[Message] # Cached message if available
885
886
class RawBulkMessageDeleteEvent:
887
"""Raw bulk message delete event payload."""
888
message_ids: Set[int] # Deleted message IDs
889
channel_id: int # Channel ID
890
guild_id: Optional[int] # Guild ID
891
cached_messages: List[Message] # Cached messages if available
892
893
class RawReactionActionEvent:
894
"""Raw reaction add/remove event payload."""
895
message_id: int # Message ID
896
user_id: int # User ID
897
channel_id: int # Channel ID
898
guild_id: Optional[int] # Guild ID
899
emoji: PartialEmoji # Reaction emoji
900
member: Optional[Member] # Member who reacted (if available)
901
event_type: str # 'REACTION_ADD' or 'REACTION_REMOVE'
902
903
class RawReactionClearEvent:
904
"""Raw reaction clear event payload."""
905
message_id: int # Message ID
906
channel_id: int # Channel ID
907
guild_id: Optional[int] # Guild ID
908
909
class RawReactionClearEmojiEvent:
910
"""Raw emoji reaction clear event payload."""
911
message_id: int # Message ID
912
channel_id: int # Channel ID
913
guild_id: Optional[int] # Guild ID
914
emoji: PartialEmoji # Cleared emoji
915
916
class RawTypingEvent:
917
"""Raw typing event payload."""
918
channel_id: int # Channel ID
919
user_id: int # User ID
920
timestamp: datetime # When typing started
921
guild_id: Optional[int] # Guild ID
922
member: Optional[Member] # Member who is typing
923
924
class RawMemberRemoveEvent:
925
"""Raw member remove event payload."""
926
user: User # User who left
927
guild_id: int # Guild ID
928
929
class RawThreadUpdateEvent:
930
"""Raw thread update event payload."""
931
thread_id: int # Thread ID
932
guild_id: int # Guild ID
933
data: Dict[str, Any] # Thread data
934
thread: Optional[Thread] # Thread object if cached
935
936
class RawThreadDeleteEvent:
937
"""Raw thread delete event payload."""
938
thread_id: int # Thread ID
939
guild_id: int # Guild ID
940
parent_id: int # Parent channel ID
941
thread_type: ChannelType # Thread type
942
thread: Optional[Thread] # Thread object if cached
943
944
class RawAppCommandPermissionsUpdateEvent:
945
"""Raw app command permissions update event payload."""
946
id: int # Command ID
947
application_id: int # Application ID
948
guild_id: int # Guild ID
949
permissions: List[AppCommandPermissions] # Updated permissions
950
```
951
952
## Usage Examples
953
954
### Basic Event Handling
955
956
```python
957
import discord
958
from discord.ext import commands
959
960
bot = commands.Bot(command_prefix='!', intents=discord.Intents.all())
961
962
@bot.event
963
async def on_ready():
964
print(f'{bot.user} has connected to Discord!')
965
print(f'Connected to {len(bot.guilds)} guilds')
966
967
@bot.event
968
async def on_member_join(member):
969
# Send welcome message
970
channel = discord.utils.get(member.guild.text_channels, name='welcome')
971
if channel:
972
embed = discord.Embed(
973
title=f'Welcome {member.display_name}!',
974
description=f'Welcome to {member.guild.name}!',
975
color=0x00ff00
976
)
977
embed.set_thumbnail(url=member.display_avatar.url)
978
embed.add_field(name='Member Count', value=len(member.guild.members))
979
await channel.send(embed=embed)
980
981
@bot.event
982
async def on_member_remove(member):
983
# Log member leave
984
channel = discord.utils.get(member.guild.text_channels, name='mod-log')
985
if channel:
986
embed = discord.Embed(
987
title='Member Left',
988
description=f'{member} left the server',
989
color=0xff0000,
990
timestamp=discord.utils.utcnow()
991
)
992
await channel.send(embed=embed)
993
994
@bot.event
995
async def on_message(message):
996
# Ignore bot messages
997
if message.author.bot:
998
return
999
1000
# Auto-react to messages containing "discord.py"
1001
if 'discord.py' in message.content.lower():
1002
await message.add_reaction('๐')
1003
1004
# Process commands
1005
await bot.process_commands(message)
1006
1007
bot.run('YOUR_TOKEN')
1008
```
1009
1010
### Reaction Role System
1011
1012
```python
1013
@bot.event
1014
async def on_raw_reaction_add(payload):
1015
"""Handle reaction role assignment."""
1016
# Configuration: message_id -> {emoji: role_id}
1017
REACTION_ROLES = {
1018
123456789012345678: { # Replace with actual message ID
1019
'๐ฎ': 987654321098765432, # Gaming role ID
1020
'๐ต': 876543210987654321, # Music role ID
1021
'๐': 765432109876543210, # Study role ID
1022
}
1023
}
1024
1025
if payload.message_id not in REACTION_ROLES:
1026
return
1027
1028
if payload.user_id == bot.user.id:
1029
return # Ignore bot reactions
1030
1031
guild = bot.get_guild(payload.guild_id)
1032
if not guild:
1033
return
1034
1035
member = guild.get_member(payload.user_id)
1036
if not member:
1037
return
1038
1039
emoji_str = str(payload.emoji)
1040
role_id = REACTION_ROLES[payload.message_id].get(emoji_str)
1041
1042
if role_id:
1043
role = guild.get_role(role_id)
1044
if role and role not in member.roles:
1045
try:
1046
await member.add_roles(role, reason="Reaction role")
1047
print(f"Added {role.name} to {member}")
1048
except discord.HTTPException as e:
1049
print(f"Failed to add role: {e}")
1050
1051
@bot.event
1052
async def on_raw_reaction_remove(payload):
1053
"""Handle reaction role removal."""
1054
# Same configuration as above
1055
REACTION_ROLES = {
1056
123456789012345678: {
1057
'๐ฎ': 987654321098765432,
1058
'๐ต': 876543210987654321,
1059
'๐': 765432109876543210,
1060
}
1061
}
1062
1063
if payload.message_id not in REACTION_ROLES:
1064
return
1065
1066
if payload.user_id == bot.user.id:
1067
return
1068
1069
guild = bot.get_guild(payload.guild_id)
1070
if not guild:
1071
return
1072
1073
member = guild.get_member(payload.user_id)
1074
if not member:
1075
return
1076
1077
emoji_str = str(payload.emoji)
1078
role_id = REACTION_ROLES[payload.message_id].get(emoji_str)
1079
1080
if role_id:
1081
role = guild.get_role(role_id)
1082
if role and role in member.roles:
1083
try:
1084
await member.remove_roles(role, reason="Reaction role removed")
1085
print(f"Removed {role.name} from {member}")
1086
except discord.HTTPException as e:
1087
print(f"Failed to remove role: {e}")
1088
```
1089
1090
### Advanced Message Monitoring
1091
1092
```python
1093
@bot.event
1094
async def on_message_edit(before, after):
1095
"""Log message edits."""
1096
if before.author.bot:
1097
return
1098
1099
if before.content == after.content:
1100
return # No content change
1101
1102
# Log to mod channel
1103
mod_channel = discord.utils.get(before.guild.text_channels, name='mod-log')
1104
if mod_channel:
1105
embed = discord.Embed(
1106
title='Message Edited',
1107
color=0xffaa00,
1108
timestamp=after.edited_at
1109
)
1110
embed.add_field(name='Author', value=before.author.mention, inline=True)
1111
embed.add_field(name='Channel', value=before.channel.mention, inline=True)
1112
embed.add_field(name='Message ID', value=before.id, inline=True)
1113
embed.add_field(name='Before', value=before.content[:1024], inline=False)
1114
embed.add_field(name='After', value=after.content[:1024], inline=False)
1115
embed.add_field(name='Jump to Message', value=f'[Click here]({after.jump_url})', inline=False)
1116
1117
await mod_channel.send(embed=embed)
1118
1119
@bot.event
1120
async def on_message_delete(message):
1121
"""Log message deletions."""
1122
if message.author.bot:
1123
return
1124
1125
mod_channel = discord.utils.get(message.guild.text_channels, name='mod-log')
1126
if mod_channel:
1127
embed = discord.Embed(
1128
title='Message Deleted',
1129
color=0xff0000,
1130
timestamp=discord.utils.utcnow()
1131
)
1132
embed.add_field(name='Author', value=message.author.mention, inline=True)
1133
embed.add_field(name='Channel', value=message.channel.mention, inline=True)
1134
embed.add_field(name='Message ID', value=message.id, inline=True)
1135
embed.add_field(name='Content', value=message.content[:1024] or '*No content*', inline=False)
1136
1137
if message.attachments:
1138
attachments = '\n'.join([att.filename for att in message.attachments])
1139
embed.add_field(name='Attachments', value=attachments, inline=False)
1140
1141
await mod_channel.send(embed=embed)
1142
```
1143
1144
### Voice Activity Monitoring
1145
1146
```python
1147
@bot.event
1148
async def on_voice_state_update(member, before, after):
1149
"""Monitor voice activity."""
1150
1151
# Member joined voice
1152
if before.channel is None and after.channel is not None:
1153
print(f"{member} joined {after.channel}")
1154
1155
# Create temporary voice channel if joining "Create Channel" channel
1156
if after.channel.name == "โ Create Channel":
1157
category = after.channel.category
1158
temp_channel = await after.channel.guild.create_voice_channel(
1159
name=f"{member.display_name}'s Channel",
1160
category=category,
1161
user_limit=10
1162
)
1163
await member.move_to(temp_channel)
1164
1165
# Set permissions for channel owner
1166
await temp_channel.set_permissions(member, manage_channels=True, manage_permissions=True)
1167
1168
# Member left voice
1169
elif before.channel is not None and after.channel is None:
1170
print(f"{member} left {before.channel}")
1171
1172
# Delete temporary channels when empty
1173
if before.channel.name.endswith("'s Channel") and len(before.channel.members) == 0:
1174
await before.channel.delete(reason="Temporary channel cleanup")
1175
1176
# Member moved channels
1177
elif before.channel != after.channel and before.channel is not None and after.channel is not None:
1178
print(f"{member} moved from {before.channel} to {after.channel}")
1179
1180
# Voice state changes
1181
if before.self_mute != after.self_mute:
1182
status = "muted" if after.self_mute else "unmuted"
1183
print(f"{member} {status} themselves")
1184
1185
if before.self_deaf != after.self_deaf:
1186
status = "deafened" if after.self_deaf else "undeafened"
1187
print(f"{member} {status} themselves")
1188
```
1189
1190
### Error Handling
1191
1192
```python
1193
@bot.event
1194
async def on_error(event, *args, **kwargs):
1195
"""Handle errors in event handlers."""
1196
import traceback
1197
import sys
1198
1199
print(f'Ignoring exception in {event}:', file=sys.stderr)
1200
traceback.print_exc()
1201
1202
# Log to error channel
1203
error_channel = bot.get_channel(ERROR_CHANNEL_ID)
1204
if error_channel:
1205
embed = discord.Embed(
1206
title='Event Error',
1207
description=f'Error in event: `{event}`',
1208
color=0xff0000,
1209
timestamp=discord.utils.utcnow()
1210
)
1211
embed.add_field(name='Traceback', value=f'```py\n{traceback.format_exc()[:1900]}\n```', inline=False)
1212
await error_channel.send(embed=embed)
1213
1214
@bot.event
1215
async def on_command_error(ctx, error):
1216
"""Handle command errors."""
1217
if isinstance(error, commands.CommandNotFound):
1218
return # Ignore unknown commands
1219
1220
elif isinstance(error, commands.MissingRequiredArgument):
1221
await ctx.send(f'Missing required argument: `{error.param.name}`')
1222
1223
elif isinstance(error, commands.BadArgument):
1224
await ctx.send(f'Invalid argument: {error}')
1225
1226
elif isinstance(error, commands.MissingPermissions):
1227
perms = ', '.join(error.missing_permissions)
1228
await ctx.send(f'You need the following permissions: {perms}')
1229
1230
elif isinstance(error, commands.BotMissingPermissions):
1231
perms = ', '.join(error.missing_permissions)
1232
await ctx.send(f'I need the following permissions: {perms}')
1233
1234
elif isinstance(error, commands.CommandOnCooldown):
1235
await ctx.send(f'Command is on cooldown. Try again in {error.retry_after:.2f} seconds.')
1236
1237
else:
1238
# Log unexpected errors
1239
import traceback
1240
traceback.print_exception(type(error), error, error.__traceback__)
1241
await ctx.send('An unexpected error occurred.')
1242
```