I'm fairly new at making a discord bot. I have created a method to get a list of all the members in the server the bot is connected to. This method works fine. However, I am also trying to get the bot to accept commands. I am having a lot of trouble with this and I keep seeing that I should use commands.Bot for this instead of Client. I can't figure out how to make my original method work with commands.Bot though. Any help would be appreciated!
import os
import discord
import csv
from collections import defaultdict
from discord.ext import commands
intents = discord.Intents.all()
client = discord.Client(intents=intents)
outP = open("giveawayList.txt", "w")
bot = commands.Bot(command_prefix='!')
#client.event
async def on_message(message):
if message == "!test":
await message.channel.send("you failed the test")
#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})'
)
count = 0
for guild in client.guilds:
for member in guild.members:
print(member)
if 'Bots' not in str(member.roles):
print(member.name, ' ')
outP.write(member.name)
outP.write("\n")
count += 1
print('Number of members: ' + str(count))
It is good to use commands.bot instead of Client because it is an extended version, as it inherits all the functionalities from Client.
I see you have tried to migrate from the use of Client to using commands.bot, but have a few things in mind:
You do not want to use both at the same time, so this is wrong:
client = discord.Client(intents=intents)
bot = commands.Bot(command_prefix='!')
You should keep only the bot one.
Apart from that, you gotta replace the client from the decorators and the calls inside the function. Your corrected code should look something like this:
import os
import discord
import csv
from collections import defaultdict
from discord.ext import commands
intents = discord.Intents.all()
outP = open("giveawayList.txt", "w")
bot = commands.Bot(command_prefix='!', intents=intents)
#bot.event
async def on_message(message):
if message == "!test":
await message.channel.send("you failed the test")
await bot.process_commands(message)
#bot.event
async def on_ready():
for guild in bot.guilds:
if guild.name == GUILD:
break
print(
f'{bot.user} is connected to the following guild: \n'
f'{guild.name} (id: {guild.id})'
)
count = 0
for guild in bot.guilds:
for member in guild.members:
print(member)
if 'Bots' not in str(member.roles):
print(member.name, ' ')
outP.write(member.name)
outP.write("\n")
count += 1
print('Number of members: ' + str(count))
So, regarding your questions, i am gonna answer them one by one :
1- client and bot are not diffrent at all, that means you shouldn't have any problem using the same functions on both(and neither are better than each other, meaning both will do the same stuff)
2- now to get your bot to receive/accept commands, you can use the await function, which basically waits for a command to be trigerred and will give out the output.
For example :
#Client.command()
async def botping(ctx):
await ctx.send(f"The bot's ping is {round(Client.latency*1000)} ms")
This command here (for example):
We are defining a command called "botping" and we are passing the ctx wich is the context the bot is writing, the you have the await wich will trigger the command when you type "prefix"botping in chat.
Hopefully this helped you a little bit about the concept of taking commands and that there is no diffrence between client and bot
For further information, i suggest that you check out the discord.py documentation:
https://discordpy.readthedocs.io/en/latest/index.html
Related
i have only started to look around and figure how things work with discord.py bot. Tried making a bot that welcomes people in a certain channel. But no matter what I do, it doesn't seem to be working. The code executes and the on_ready fires. But its not welcoming the user like its supposed to. Can someone help?
import discord
from discord.ext import commands
from discord.ext.commands import Bot
from discord import Color
import asyncio
import datetime
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
client=commands.Bot(command_prefix="-")
client.remove_command("help")
#client.event
async def on_ready():
print("Created by Goodboi")
print(client.user.name)
print("-----")
#client.event
async def on_member_join(member):
embed = discord.Embed(colour=0xe8744f,
description=f"Welcome to the discord server",)
embed.set_author(name=f"{member.mention}",icon_url=f"{member.avatar_url}")
embed.set_footer(text=f"{member.guild}",icon_url=f"{member.guild.icon_url}")
embed.timestamp = datetime.datetime.utcnow
channel = client.get_channel(id=) #usedid
await channel.send(embed=embed)
client.run('token') #usedtoken
Hi you have to get channel like this
#client.event
async def on_member_join(member):
embed = discord.Embed(colour=0xe8744f,
description=f"Welcome to the discord server",)
embed.set_author(name=f"{member.mention}",icon_url=f"{member.avatar_url}")
embed.set_footer(text=f"{member.guild}",icon_url=f"{member.guild.icon_url}")
embed.timestamp = datetime.datetime.utcnow()
channel = member.guild.get_channel(channel_id) #usedid
await channel.send(embed=embed)
The only thing you did wrong is passing no brackets to your datetime.datetime.utcnow "function" which gives out the following error:
TypeError: Expected datetime.datetime or Embed.Empty received builtin_function_or_method instead
If you put brackets behind the definition of your timestamp it should work:
#client.event
async def on_member_join(member):
embed = discord.Embed(colour=0xe8744f,
description=f"Welcome to the discord server", )
embed.set_author(name=f"{member.mention}", icon_url=f"{member.avatar_url}")
embed.set_footer(text=f"{member.guild}", icon_url=f"{member.guild.icon_url}")
embed.timestamp = datetime.datetime.utcnow() # Added brackets
channel = client.get_channel(ChannelID) # No "id=" needed
await channel.send(embed=embed)
You can also have a look at the docs: https://docs.python.org/3/library/datetime.html#datetime.datetime
This should work for you, though, can be improved in many ways, but if you asked for this, then here is it.
#client.event
async def on_member_join(member) :
channel = client.get_channel(CHANNEL ID) # First we need to get the channel we want to post our welcome message.
embed = discord.Embed(
colour=0xe8744f ,
description='Welcome to the discord server' ,
timestamp=datetime.utcnow()
)
embed.set_author(name=f'{member.mention}' , icon_url=f'{member.avatar_url}')
embed.set_footer(text=f'{member.guild}' , icon_url=f'{member.guild.icon_url}')
await channel.send(embed=embed) #Send the embed
I dont have access to some of these test servers my bot is in and I want the bot to leave them, my code is
#bot.command()
#commands.is_owner()
async def guilds(ctx):
await ctx.channel.purge(limit=1)
guild = ""
servers = bot.guilds
for a in servers:
guild += f"{a}\n"
if a == "Fleshy's server":
b = a.id()
await bot.leave(b)
await ctx.author.send(guild)
I dont get any error when i use this but it also doenst leave the Fleshy's servers
These are the servers he is in
my server The Judas Cradle 7 test server yosh’s rock Fleshy's server Retronized Cafe Fleshy's server Fleshy's server Able's Hub
If you want to leave a guild by knowing its name you can run the following command:
#bot.command()
async def leaveg(ctx, *, guild_name):
guild = discord.utils.get(bot.guilds, name=guild_name) # Get the guild by name
if guild is None:
print("No guild with that name found.") # No guild found
return
await guild.leave() # Guild found
await ctx.send(f"I left: {guild.name}!")
We use * in order to also allow names with a space in it
Import from discord.utils import get
If you know the ID of the server you can also run the following command:
#bot.command()
async def leave(ctx, guild_id):
await bot.get_guild(int(guild_id)).leave()
await ctx.send(f"I left: {guild_id}")
Import from discord.utils import get
Make sure to put in the ID: leave ServerID
You can also have a look at the docs.
I'm making a bot for a pokemon server, and I'm trying to make a command that will give the 'Gym Leader' role to another user. I try using the command, and using the test command, but there is no response in the server nor the shell.
import os
import discord
from dotenv import load_dotenv
from discord.ext import commands
from discord.utils import get
bot = commands.Bot(command_prefix='b!', case_insensitive=True)
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
client = discord.Client()
#client.event #works
async def on_ready():
print(f'{client.user.name} has connected to Discord!')
channel = client.get_channel(697500755766018098)
#client.event #works
async def on_member_join(member):
await member.create_dm()
await member.dm_channel.send(
f'Hi {member.name}, welcome to Pokémon Beast Ball!\n\nThis server utilizes Pokecord and Mewbot.\n\nSay \'pkhelp\' in the server to learn about Pokecord commands.\nSay \';help\' in the server to learn about Mewbot commands.'
)
#bot.command() #doesn't work
async def test(ctx):
print("test recieved")
await ctx.send(ctx)
#bot.command(pass_context=True) #this is the command that really needs help
async def newleader(ctx: discord.User=None):
print("command recieved")
if not user:
await ctx.send("Invalid")
print("1")
else:
role = discord.utils.get(ctx.guild.roles, name="Gym Leader")
role2 = discord.utils.get(ctx.guild.roles, name="Purple UniTurtle Man")
if role in ctx.author.roles or role2 in ctx.author.roles:
print("2")
await ctx.send(f'A new Gym Leader has been appointed')
await user.add_roles(role)
await bot.remove_roles(ctx.author, role)
else:
print("3")
await ctx.send("You do not have permission to use this command")
client.run(TOKEN)
You are mixing bot and client and your client = discord.Client() is stepping on your bot = commands.Bot(...) statement. Since you want to do commands and events you only use the commands.Bot(...) statement.
Remove the client = discord.Client() statement and change your #client.event decorators to #bot.event.
Also if you want to reference the command context in your test command update it with the ctx parameter async def test(ctx):.
That will get you started using your commands and entering b1test will now work.
Please note that the case_insensitive=True on the commands declaration refers to the command name and not the prefix.
Did you check :
bot connection → make a "on_connect" event (not exactly the same as "on_ready") to see if your bot successfully connect to your server (before receiving data from discord). If not, try to add your bot again to your server and check if all tokens are goods.
bot permissions (if your bot have the right to write in channel, read messages from channels, manage roles) → if your bot cannot read messages, he can't read commands !
role priority (you can't manage roles highers thant yours) → go to "server settings" > "roles" > put your bot role above the 'Gym Leader' role (or at the top of the list if you don't care).
The problem isn't actually what the selected answer suggests. There is probably no reason to use both commands.Bot and discord.Client but using both won't lead to that issue.
The issue is because you are only running the client, not the bot. You need to also run the bot instance if you want it to function.
If you are not trying to do something specific, then just using either bot or client will suffice anyway, so that part of the selected answer was helpful in avoiding the issue at least.
This is what I have:
#client.command(pass_context=True)
#client.event
async def on_member_join(ctx, member):
print(f'{member} has joined a server.')
await ctx.send(f"Hello {member}!")
await ctx.member.send(f"Welcome to the server!")
I need the bot to send a private message containing rules and commands list when he joins.
Please help!
The event on_member_join() only accepts member as a valid parameter (see doc). Thus what you try to do: on_member_join(ctx, member) ,wont work. You need to use this instead: on_member_join(member).
If you used the event as follows:
#client.event
async def on_member_join(member):
await member.send('Private message')
You can send messages directly to members who joined the server. Because you get an member object using this event.
I don't know what happened, from one day to the next the bot stopped sending welcome messages to new members. But I was finally able to solve it.
I just had to add these two lines of code. intents = discord.Intents() intents.members = True Read
import discord
from discord.ext import commands
#try add this
intents=discord.Intents.all()
#if the above don't work, try with this
#intents = discord.Intents()
#intents.members = True
TOKEN = 'your token'
bot=commands.Bot(command_prefix='!',intents=intents)
#Events
#bot.event
async def on_member_join(member):
await member.send('Private message')
#bot.event
async def on_ready():
print('My bot is ready')
bot.run(TOKEN)
I am looking for a way to allow a user to move him or her self and another user to a different voice channel. I already got the command to work for the author of the message, but I am having trouble finding out a way to move another user in the same message. The idea is that the user would be able to type "n!negotiate [Other User]" and it would move the author and the other user to the Negotiation channel.
I would love some help with how I might be able to do this. The code is provided below excluding the tokens and ids.
Code:
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import asyncio
import time
Client = discord.Client() #Initialise Client
client = commands.Bot(command_prefix = "n!") #Initialise client bot and prefix
#client.event
async def on_ready():
print("Logged in as:")
print(client.user.name)
print("ID:")
print(client.user.id)
print("Ready to use!")
#client.event
async def on_message(check): #Bot verification command.
if check.author == client.user:
return
elif check.content.startswith("n!check"):
await client.send_message(check.channel, "Nations Bot is online and well!")
async def on_message(negotiation): #Negotiate command. Allows users to move themselves and other users to the Negotiation voice channel.
if negotiation.author == client.user:
return
elif negotiation.content.startswith("n!negotiate"):
author = negotiation.author
voice_channel = client.get_channel('CHANNELID')
await client.move_member(author, voice_channel)
client.run("TOKEN")
You should use discord.ext.commands. You're importing it, but not actually using any of the features.
from discord.ext import commands
import discord
bot = commands.Bot(command_prefix = "n!") #Initialize bot with prefix
#bot.command(pass_context=True)
async def check(ctx):
await bot.say("Nations Bot is online and well!")
#bot.command(pass_context=True)
async def negotiate(ctx, member: discord.Member):
voice_channel = bot.get_channel('channel_id')
author = ctx.message.author
await bot.move_member(author, voice_channel)
await bot.move_member(member, voice_channel)
bot.run('TOKEN')
Here we use a converter to accept a Member as input. Then we resolve the author of the message from the invocation context and move both Members to the voice channel.