circuit

How to Update Discord bot status with Discord.py

Personalizing your bot's displayed activity for your discord server with Python




Looking at the latest iteration of our Discord bot, it isn't very exciting. It sits online and watches. Let's update our bot's status when it comes online to make it a bit more lively. If you missed the last post on how to use dotenv to hide your token, see the link below. Using dotenv to Hide Sensitive Information in Python Hide your passwords and API tokens to make your code more securetowardsdatascience.com

The client object for the bot has a method change_presence. This method is used to change the bot's status. There are a couple helper functions that we can use to build statuses.

There are so many options for what a bot can do!There are so many options for what a bot can do!

  • Playing: Use discord.Game() to display the bot as playing a game. Provide the name of the game to the name argument

  • Streaming: Use discord.Streaming() to display the bot as streaming with an optional url argument

  • Listening: Use discord.Activity() with the type argument set to discord.ActivityType.listenting to show the bot as listening to something

  • Watching: Use discord.Activity() with the type argument set to discord.ActivityType.watching to show the bot as watching something

Examples

Setting the bot's status when it first comes online will add a bit of polish while it is hanging out in the server. In order to keep things simple, we'll append the examples to the on_ready event.

Let's start with one of the most common statuses seen on Discord, playing a game. This is particularly relevant to the bot I originally set out to build. The bot was going to be in a server dedicated to Sea of Thieves. Naturally, I wanted the bot to be playing Sea of Thieves around the clock.

Adding the following code in the on_ready function sets the bot's status to “Playing Sea of Thieves”.

# Startup Information
@client.event
async def on_ready():
    await client.change_presence(activity=discord.Game('Sea of Thieves'))

    print('Connected to bot: {}'.format(client.user.name))
    print('Bot ID: {}'.format(client.user.id))

The bot is sailing the seas!The bot is sailing the seas!

Streaming Status

People love to share their gameplay, and with the current pandemic conditions, it isn't as safe to hangout and play together in person. In the spirit of playing games together, let's change the bot status to “Streaming Sea of Thieves” with a link to a Twitch stream.

Note: Discord only supports streaming links for YouTube and Twitch

With the streaming status, there are 2 arguments: name and url. The name argument is the game the bot will be “streaming.” The url argument will become a clickable link to watch the stream.

Note: the url argument must be formatted as an actual URL. http://www.twitch.tv will work while www.twitch.tv will not. It won't change the bot status at all

# Startup Information
@client.event
async def on_ready():
    await client.change_presence(activity=discord.Streaming(name='Sea of Thieves', url='https://www.twitch.tv/your_channel_here'))

    print('Connected to bot: {}'.format(client.user.name))
    print('Bot ID: {}'.format(client.user.id))

Watching Status

After a long day of managing servers, maybe the bot just wants to unwind with the latest episode of *The Boys* on Amazon Prime. To get the watching status, we have to switch the code up a little bit. Playing and streaming are so common that they get their own simple methods. Watching requires that we use discord.Activity and define the activity with the type argument set to discord.ActivityType.watching.

# Startup Information
@client.event
async def on_ready():
    await client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name='The Boys'))

    print('Connected to bot: {}'.format(client.user.name))
    print('Bot ID: {}'.format(client.user.id))

Listening Status

Listening functions the same way as watching, but this time set type to discord.ActivityType.listening. Now it can listen to some custom beats!

# Startup Information
@client.event
async def on_ready():
    await client.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name='Some Custom Beats'))

    print('Connected to bot: {}'.format(client.user.name))
    print('Bot ID: {}'.format(client.user.id))

Changing Status for Long Running Actions

Sometimes commands run long and you may want to update the status for while the bot is doing a calculation and return to the previous status when it has completed. Let's break down the problem into steps:

  1. Capture the bot's current activity

  2. Change the bot's activity to something new

  3. Simulate a long running task

  4. Change the bot's activity back to the original activity

Let's start by capturing the bot's current activity. Our bot is named client in the code, so we can use that to save the current activity to a variable.

previous_status = client.guilds[0].get_member(client.user.id).activity

We are accessing the first guild the bot is a member of, then using the get_member method with the bot ID to retrieve its activity attribute.

Next, let's change the bot activity to the new activity. Since the bot is executing a command, let's use the listening activity.

await client.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name='to Your Commands!'))

Now that the status has been updated, let's do the long running part of the code. We'll simulate it here using the time module. Import time at the top of your bot script.

import time

Now in our command, we can add a 5 second pause to the code to simulate the script doing some long running calculations.

time.sleep(5)

Finally, let's return the status of the bot to whatever it was previously. To do this we simply pass the original status to the change_presence method. Since the activity is saved as the correct object type, there is no extra work to perform. The bot is now back to its original activity.

await client.change_presence(activity=previous_status)

Altogether this would look something like the longcommand command defined below.

[@client](http://twitter.com/client).command()
async def longcommand(ctx):
 # Get previous activity
    previous_status = client.guilds[0].get_member(client.user.id).activity

    # Change activity for the task
    await client.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name='to Your Commands!'))

    # Long Running Task
    time.sleep(5)
    await ctx.send('Task Complete!')

    # Reset the status
    await client.change_presence(activity=previous_status)

Adding Dynamic Information to a Status

You may have seen bots in other servers that list information like how many different servers they are a part of. client.guilds is a list of the servers a bot has been added to (guild is the developer name for servers). The length of this list is equal to the number of servers the bot is a part of. We can create a string based off this information.

activity_string = 'on {} servers.'.format(len(client.guilds))

I like to think my bot is always listening, so let's use the listening command to display. This will be just like our earlier use of it, but now the name argument will be set to activity_string.

# Startup Information
@client.event
async def on_ready():
    await client.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name=activity_string))

    print('Connected to bot: {}'.format(client.user.name))
    print('Bot ID: {}'.format(client.user.id))

Now when the bot starts up it will automatically show how many servers it is a part of. This only updates when the bot starts, so for now it won't update in real time as the bot is added to more servers.

Caveats

One major issue with frequently changing the bot status is that Discord only supports a single status per server. In other words, if the bot is in many servers, its status will change in every server anytime a status change is triggered. For this reason many bots don't change their status based on commands.

Another limitation of the Discord API is that it does not at this time support custom statuses. This means that you can't create a “Dreaming” activity for your bot to dream of electric sheep.

Join Medium with my referral link - Drew Seewald

Send an Embed with a Discord Bot in Python

Python Discord Bots: Formatting Text




Continue Learning