my discord bot made with python is not working - discord.py

here is my code:
import discord
import asyncio
from discord.ext import commands
TOKEN="secret"
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="?", intents = intents)
#bot.event
async def on_ready():
print(f'{bot.user} successfully logged in!')
#bot.event
async def on_message(message):
if message.author == bot.user:
return
await bot.process_commands(message)
#bot.command()
async def spam(ctx, message, *, amount:int):
await ctx.send("Starting Spam...")
new_amount = amount+1
for i in range(1, new_amount):
await ctx.send(message)
await asyncio.sleep(0.5)
await ctx.send("Spam Completed!")
try:
bot.run(TOKEN, bot = False)
except discord.HTTPException as e:
if e.status == 429:
print("The Discord servers denied the connection for making too many requests")
else:
raise e
my bot does go online, however, when I use the spam command, it doesn't work.
the code doesn't give any errors. so i am wondering what the problem is.
any help will be appreciated.

You don't have the message_content intent set to True. First page of docs shows you to need to enable the message_content intent. This allows your bot to read message content; and therefore actually be able to respond to commands.
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="?", intents=intents)
You will also need to enable the message content intent in the Discord Developer Portal as well. Under your application, go to "Bot", and then scroll down to "Privileged Gateway Intents" and then enable the message content one.

According to discord.py docs:
"With the API change requiring bot authors to specify intents, some intents were restricted further and require more manual steps. These intents are called privileged intents."
So basically what you need to do is go to the "Bot" section within your application in the discord developers portal and under the heading Privileged Gateway Intents you need to enable message content intents etc. based on what your needs are. Also this needs to be done through code as well.
In your case:
intents = discord.Intents.default()
needs to be replaced with
intents = discord.Intents(messages=True,message_content=True)
or simply
intents = discord.Intents.all()
Feel free to comment down any queries regarding this solution.

Related

How do I make it so that ctx is not of type 'interaction' (nextcord slash commands)?

I'm trying to create a music bot using nextcord slash commands and interactions. The command isn't fully finished yet, as I am having trouble getting it to even join the voice channel. I don't exactly know how interactions work yet but I'm assuming it's a similar concept as ctx. Below is my music.py cog:
import nextcord
from nextcord.ext import commands
from nextcord import Interaction
class Music(commands.Cog):
def __init__(self, client):
self.client = client
guild_ids = ["Guild Ids Go Here"]
#slash commands go under here
#nextcord.slash_command(name="play", description="plays music in vc", guild_ids = guild_ids)
async def play(self, interaction : Interaction, query: str):
channel = interaction.author.voice.channel #ERROR IS HERE
try:
await channel.connect()
await interaction.response.send_message("The bot has joined vc.")
except:
await interaction.response.send_message("Failed to find voice channel.")
def setup(client):
client.add_cog(Music(client))
I'm getting an error that says "'Interaction' object has no attribute 'author'. It occurs on line 15 in 'play' when it says 'channel = interaction.author.voice.channel'. I think this means that this isn't the right way to go about getting the author's voice channel. If this is the case, is there a better, working method?
In nextcord interaction, message author is interaction.user,
channel is interaction.channel.
You also can send interaction message by interaction.send instead
of interaction.response.send_message. It's much shorter and easier
to read.
If you want to send a normal message without using interaction, try
interaction.channel.send. It's similar to ctx.channel.send in application command

discord.py - on_message spam - jump_url

I'm working on a logging bot. To do this I'm using on_message with jump_url to detect links, however the bot just spams it, I'm guessing this is because it reads its own message.
I have tried to stop it by checking if the message author is the user, however that didn't fix it. Whenever I type anything it logs it and has the link even though I didn't put in any link.
This is in a cog.
#commands.Cog.listener()
async def on_message(self, message):
embed=discord.Embed(title="Message from {} contains a link ".format(message.author.name), description="", color=0x607d8b)
embed.set_thumbnail(url="https://cdn.discordapp.com/avatars/9005083965732483134/14fcc0c2d369d9f4d742d9e8471d8536.webp?size=1024")
embed.add_field(name="Message:" ,value=message.jump_url, inline=True)
The code works; it's just that the bot spams the link. There is some code missing like channel.send as I'm connected to a database to log the channels people picked to log stuff.
There are a few ways you can combat this, I will show you two possible methods to avoid your problem.
Method 1 involves checking if the author of the message, message.author, is a bot through its attributes. This method ensures that if the user is a bot, then your bot will ignore the message.
Method 2 will only ignore your own bot. You can do this using self.bot, which you may have defined in your __init__. With this, you can compare if the message.author is your bot, and if it's True you may ignore it.
Do view the methods below as explained above.
#commands.Cog.listener()
async def on_message(self, message):
# Method 1
if message.author.bot:
return
# Method 2
if message.author == self.bot:
return
# Please note: You do not need to use both methods!

Combining commands and events

I am building a discord bot that I want to be able to interact both with commands and emojis. Here is the code so far:
import os
import discord
from dotenv import load_dotenv
from discord.ext import commands
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD = os.getenv('DISCORD_GUILD')
bot = commands.Bot(command_prefix='$')
client = discord.Client()
#bot.command(name='repeat', help='help me to understand bots')
async def test(ctx, *args):
for arg in args:
await ctx.send(arg)
#client.event
async def on_raw_reaction_add(payload):
print("someone reacted to something")
print(payload)
bot.run(TOKEN)
client.run(TOKEN)
My intuition is that the last two lines are where this goes wrong, although I don't understand the run(TOKEN) feature to have a good understanding of why this happens, or how to fix it.
To further develop this you need to fully understand what you've done and have a plan for what you want to do. I will first direct you to the discord python documentation Where you can see everything discord.py has to offer. This should probably be your first stop when you have questions.
I see you have import discord and from discord.ext import commands... discord.py has two ways to approach a bot, which you have:
client = discord.Client() hails from import discord, and
bot = commands.Bot() hails from import discord.ext.
You need to choose whether to use discord.Client() or discord.Bot() because the use cases are entirely different. I suggest the latter, as it will allow your bot to do more, in a cleaner fashion.
Your next step would be to change any # decorators to whichever variable you choose and keep that consistent throughout your code. Then, you need to remove whichever .run(TOKEN) you won't use. So, if I were you, I would read the documentation which I linked to you so you understand more than a YouTube tutorial would teach.
As for a revision to your code, it would look like this:
import os
import discord
from dotenv import load_dotenv
from discord.ext import commands
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD = os.getenv('DISCORD_GUILD')
bot = commands.Bot(command_prefix='$')
#bot.command(name='repeat', help='help me to understand bots')
async def test(ctx, *args):
for arg in args:
await ctx.send(arg)
#bot.event
async def on_raw_reaction_add(payload):
print("someone reacted to something")
print(payload)
bot.run(TOKEN)

Bot wont properly print member_count

So I'm new to Python and I decided to take the plunge and make a Discord bot for personal use in my server. I like the idea of having full control over what features my bot will have so I'm slowly building the bot. Currently I want my bot to show the current number of members in the server when called with a command
import discord
from discord.ext import commands
#botbot.command()
async def server(ctx):
guild = discord.Guild.member_count
await ctx.send(guild)
I know I'm most likely way off with my code here.
While the bot is sending a message into the chat, its formatted as:
<property object at 0x046036C0>
While I would like to have it say something like "This server has {some number} members."
Any advice is really appreciated!
Thank you for your time.
Edit: botbot is the name for my bot, just so thats clear.
discord.Guild is the class. You want to get the guild the command is in from the invocation context:
#botbot.command()
async def server(ctx):
await ctx.send(f"This server has {ctx.guild.member_count} members.")
The method member_count is not really what you want in this occasion, the guild object has a list called members, so it's as easy as getting the length of that list like so:
#botbot.command()
async def server(ctx):
guild = len(discord.guild.members)
await ctx.send(guild)
EDIT: And indeed you have a typo with using "Guild" instead of "guild"

How to check if bot is connected to a channel? | discord.py

I've decided to try making my discord bot play music, but I've gotten stuck already. Mainly due to the fact I can't find any sources to help with the current version, I've been winging everything from the docs. However, I can't figure out how to check if the bot is connected to a voice channel.
I have tried if not Client.is_connected():, however that didn't work. If there are any updated sources to help me get the basics of discord.py's voice features, please give me a link :) Here is my code so far:
# ----- ATTEMPT AT VOICE COMMANDS ------
#discord.opus.load_opus() - what goes in bracket???
#client.command(name="join", pass_ctx=True)
async def join(ctx):
#if not is_connected(): - Client.is_connected() not working
user = ctx.message.author
vc = user.voice.channel
await vc.connect()
await ctx.send(f"Joined **{vc}**")
#else:
# await ctx.send("I'm already connected!")
#client.command(name="disconnect", pass_ctx=True)
async def disconnect(ctx):
# if not is_connected(): - once again can't work it out
vc = ctx.message.guild.voice_client # i don't even know how this worked :D
await vc.disconnect()
#else:
# await ctx.send("I'm not connected to any channels")
#client.command(name="play", pass_ctx=True)
async def play(ctx, songurl=None):
if not songurl: # this works at least
await ctx.send("Please specify a song")
return
if not is_connected(): # once again, how to check if bot is connected?
vc = ctx.message.author.voice.channel
if not vc: # i think this should work
await ctx.send("You're not in a voice channel!")
await vc.connect()
# haven't even worked out anything past this point and it's broken
ps: sorry for just dumping my whole vc section but i don't understand a lot
Really all that matters here is the play command, but I included the others just because (as you can see from my comments) I don't understand LOTS of what is going on. How should I go about this? Are there any good sources for the current version? Thanks in advance.
A bot can be connected to voice in multiple guilds at the same time, so you need to get the VoiceClient for the appropriate guild from Client.voice_clients and then check VoiceClient.is_connected:
def is_connected(ctx):
voice_client = get(ctx.bot.voice_clients, guild=ctx.guild)
return voice_client and voice_client.is_connected()
you could also do
client.command()
async def join(ctx):
user = ctx.message.author
vc = user.voice.channel
voice = discord.utils.get(client.voice_clients, guild=ctx.guild) # This allows for more functionality with voice channels
if voice == None: # None being the default value if the bot isnt in a channel (which is why the is_connected() is returning errors)
await vc.connect()
await ctx.send(f"Joined **{vc}**")
else:
await ctx.send("I'm already connected!")
After a bit of experimentation with my bot, I found that something similar to this may work for you. It's also pretty quick and easy.
if ctx.guild.voice_client in bot.voice_clients:
# Do something here
I used this with the on_message event, but it could likely work in your use case as well by doing:
if not ctx.guild.voice_client in bot.voice_clients:
# Do something else here

Resources