Events in discord.py 🐍
Tags: discord, discordpy, python, dpy
Published: 2021-03-05 15:58:18

discord.py has an extensive collection of features. Events are one of the most useful of these. Events are used for welcoming bots, reaction roles, and lots of other functions. This guide will teach you more about events, and how you can use them in your discord bot. In the end, we will have the bot print to the console when it is signed in, and give it a simple moderation and logging system.

> *If you haven't yet, I suggest reading the earlier post in this series, as this builds on the previous post.*

So far, we have the following code:
```py
import discord
from discord.ext import commands

bot = commands.Bot(command_prefix="!", case_insensitive=True)

@bot.command(name='hello', description="Greet the user!")
async def hello(ctx):
    await ctx.send(f"Hello {ctx.author.name}!") # f-string

bot.run('token')
```

But what if we want to delete a message when a user sends a link in the chat? They obviously wouldn't use a command.

---
We can use the `on_message` event to trigger a function whenever a message is sent.

We first want to use the `event` decorator to tell discord.py that this is an event.

```py
@bot.event
async def on_message(message):
   if 'https://' in message.content:
      await message.delete()
      await message.channel.send(f"{message.author.mention} Don't send links!")
   else:
      await bot.process_commands(message)
```
Now, if we send a link, the bot will warn us!
![Demo](https://mikey.has-no-bra.in/CawdwT.gif)

## Automoderation 🔧

But what if we want to create a profanity list?
```py
badwords = ['bad', 'words', 'here']

@bot.event
async def on_message(message):
   for i in badwords: # Go through the list of bad words;
      if i in message:
         await message.delete()
         await message.channel.send(f"{message.author.mention} Don't use that word here!")
         return # So that it doesn't try to delete the message again.
   await bot.process_commands(message)
```

## Logging 📜
Events are called by using the `dispatch` function. When a message is sent, the internals of discord.py uses `bot.dispatch('message', message_object)`. This triggers other parts of discord.py to find the function called `on_message` and run it. So, we could make our own event that logs profanity!

So let's adapt on the code so that it will use a logging system!
```py
badwords = ['bad', 'words', 'here']

@bot.event
async def on_message(message):
   for i in badwords: # Go through the list of bad words;
      if i in message.content:
         await message.delete()
         await message.channel.send(f"{message.author.mention} Don't use that word!")
         bot.dispatch('profanity', message, i)
         return # So that it doesn't try to delete the message again, which will cause an error.
   await bot.process_commands(message)
```

Our logging code:
> *Before beginning this section, you will need to know how to get channel IDs. You can follow [this guide](https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-) if you need to enable developer mode.*

You will need to get your log channel ID so that the bot can access the specific channel. Don't worry, IDs aren't private, so you don't have to worry about sharing them.

```py
@bot.event
async def on_profanity(message, word):
   channel = bot.get_channel(channel_id_here) # for me it's bot.get_channel(817421787289485322)
   embed = discord.Embed(title="Profanity Alert!",description=f"{message.author.name} just said ||{word}||", color=discord.Color.blurple()) # Let's make an embed!
   await channel.send(embed=embed)
```
![Demo](https://mikey.has-no-bra.in/nKy9xk.gif)

Congrats! You just:
- Created your own event
- Created a simple automoderation system
- Logged when the rules are broken
- Created an embed

Next, we'll be creating a Discord bot that moderates invite links!