Trying to make my discord.py bot join voice channel; unsure about versions, discord.py rewrite, etc

Question:

I have recently started developing my own discord bot for use in my discord server. The bot works fine for the most part, but I am struggling to make it join a voice channel. Upon looking for advice on how to do it, and when looking up other issues, I see alot of varying info on the correct way to use discord.py. Here is my script; it says I am using discord.py 2.1.0 but my script is formatted much differently than other examples. Is what I’m doing different than the norm nowadays when making bots like this (does things like send images, join voice and play sounds, etc.)? What should I do to update it to be more modern? And should I look into upgrading to discord.py rewrite?

Thanks for your time.

import os

import discord
import nacl
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD = os.getenv('DISCORD_GUILD')

intents = discord.Intents.all()
client = discord.Client(intents=intents)
user = client.get_user(X)
voiceChannel = client.get_channel(X)
intents.message_content = True

# Sends info in the terminal on connection
@client.event
async def on_ready():
    for guild in client.guilds:
        if guild.name == GUILD:
            break

    print(
        f'{client.user} is connected to the following guild:n'
        f'{guild.name}(id: {guild.id})'
    )

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    # Sends a picture of a Tarkov map when a command is sent in chat
    if message.content.startswith('.customs'):
        await message.channel.send(file=discord.File('/home/container/Bot/tarkovmaps/customs.png'))
   
    
    # Sends a picture of Tarkov ammo stats when a command is sent in chat
    if message.content.startswith('.4.6x30'):
        await message.channel.send(file=discord.File('/home/container/Bot/tarkovammo/4.6x30.png'))
    if message.content.startswith('.5.7x28'):
        await message.channel.send(file=discord.File('/home/container/Bot/tarkovammo/5.7x28.png'))
    
    #There are more commands like the ones above and they all work 
    
    #Makes the bot join a voice channel and say stuff when a command is sent; doesn't work
    if message.content.startswith('.join'):
        #await client.join_voice_channel(voiceChannel)
        await voiceChannel.connect()
        print('Bot joined the channel.')
    #This format didn't work either    
    if message.contents.startswith('.leave'):
        await client.leave_voice_channel(voiceChannel)
        print('Bot left the channel.')

client.run(TOKEN)

Everything above the voice channel section works but I think my methods are a bit outdated. I am fairly new to python and new to discord.py in general; I feel like I’m using older functions to do this.

Asked By: Jordan Roark

||

Answers:

Yes, you should definitely modernise your code.

Manually parsing message content in on_message is one of the main things you should get rid of: the library now (well, for over 4 years) provides a built-in framework to handle commands for you, to avoid you having to do all this work yourself. The docs should contain enough info for you to refactor this, it’s not that much work.

The reason your voice-channel-joining doesn’t work is because the channel is always None:

client = discord.Client(intents=intents)
user = client.get_user(X)  # Bot isn't online yet
voiceChannel = client.get_channel(X)  # Bot isn't online yet

You’re getting a reference to the user and channel before your bot is even online, so it can’t find anything (the cache hasn’t been populated yet). As a result, this will always be None. You should fetch it either in something like setup_hook if you only want to do it once, or in your command (which currently doesn’t exist yet, but the first part of my answer should get you there) whenever it is invoked. get_channel is just a simple cache lookup so it doesn’t really matter performance-wise if you call it every single time the command is invoked.

Lastly,

intents = discord.Intents.all()
...
intents.message_content = True

This doesn’t really matter, but Intents.all() already includes every intent (as the name suggests, but the docs will also tell you) so enabling message_content again afterwards does nothing for you. It’s already enabled.

Answered By: stijndcl
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.