Problems with a discord.py bot - discord

I have been trying to code a Discord bot for my own server.
However, it seems like, whenever I add more commands to the code, the ban, and kick functions no longer work correctly.
I've tried rewriting the code multiple times, but it did not work.
I've tried rearranging the codes, and that did not work as well.
client = commands.Bot(command_prefix = '!')
#client.command()
async def kick(ctx, member : discord.Member, *, reason = None):
await member.kick(reason = reason)
#client.command()
async def ban(ctx, member : discord.Member, *, reason = None):
await member.ban(reason = reason)
curseWord = ['die', 'kys', 'are you dumb', 'stfu', 'fuck you', 'nobody cares', 'do i care', 'bro shut up']
def get_quote():
response = requests.get("https://zenquotes.io/api/random")
json_data = json.loads(response.text)
quote = json_data[0]['q'] + " -" + json_data[0]['a']
return(quote)
#ready
#client.event
async def on_ready():
print('LOGGED IN as mr MF {0.user}'.format(client))
#client.event
#detect self messages
async def on_message(message):
if message.author == client.user:
return
#greeting
if message.content.startswith('hello'):
await message.channel.send('ay whatup ma gamer')
#help
if message.content.startswith('!therapy'):
quote = get_quote()
await message.channel.send(quote)
#toxicity begone
msg_content = message.content.lower()
if any(word in msg_content for word in curseWord):
await message.delete()
#environment token
token = os.environ['token']
client.run(token)

You have overwritten the on_message event, which by default processes commands (those marked with the #client.command() decorator). You need to explicitly tell the library to process commands when you overwrite it. As noted in the discord.py documentation, you should add this line at the end of the on_message event:
await client.process_commands(message)

Related

get more input from one command (discord.py)

I'm trying to make an embed system that asks multiple questions and then put them together and send the embed with all the info given, but I can't figure out how to get multiple inputs in one command.
Based on what I understand from your question, you're only checking for one possible input with m.content == "hello". You can either remove it or add an in statement. Do view the revised code below.
#commands.command()
async def greet(ctx):
await ctx.send("Say hello!")
def check(m):
return m.channel == channel # only check the channel
# alternatively,
# return m.content.lower() in ["hello", "hey", "hi"] and m.channel == channel
msg = await bot.wait_for("message", check=check)
await ctx.send(f"Hello {msg.author}!")
In the case of the newly edited question, you can access the discord.Message class from the msg variable. For example, you can access the message.content. Do view the code snippet below.
#commands.command()
async def test(ctx):
def check(m):
return m.channel == ctx.channel and m.author == ctx.author
# return message if sent in current channel and author is command author
em = discord.Embed()
await ctx.send("Title:")
msg = await bot.wait_for("message",check=check)
em.title = msg.content
# in this case, you can continue to use the same check function
await ctx.send("Description:")
msg = await bot.wait_for("message",check=check)
em.description = msg.content
await ctx.send(embed=em)

Is there a way could check if an embed is a specific colour or not?

This is what I have been able to come up with after a lot of head scratching and being annoyed but lo and behold, it doesn't work.
import discord
client = discord.Client()
#client.event
async def on_ready():
print("Bot is ready")
#client.event
async def on_message(message):
if (message.channel.id == "the-channel-id-here"):
embeds = message.embeds
if not embeds:
return
else:
embed = (message.embeds)[0]
if (embed.color == 4caf50 or e53935):
print('I got that')
else:
return
client.run(BOT_TOKEN)
discord.py always returns a Color object, rather than an integer, so what you're comparing right now is an instance of Color (as defined here by the way) and a number. The Color object has an attribute value that returns an integer representation of the colour though, so you can use that to compare it to a number instead.
This code snippet should work:
import discord
client = discord.Client()
#client.event
async def on_ready():
print("Bot is ready")
#client.event
async def on_message(message):
if (message.channel.id == "the-channel-id-here"):
embeds = message.embeds
if not embeds:
return
else:
embed = (message.embeds)[0]
if (embed.color.value == 4caf50 or embed.color.value == e53935):
print('I got that')
else:
return
client.run(BOT_TOKEN)
Do note that I modified your if expression slightly, your use of or was wrong, you DO have to repeat embed.color.value again for the comparison to work!

A discord damage calculator bot

Currently I am working on a discord bot for a Pokemon and I will be running, I have the encounter system down, but have been having trouble with the damage system. Currently this is what the whole code looks like.
import discord
import os
import random
import asyncio
client = discord.Client()
from discord.ext import commands
client = commands.Bot(command_prefix='!')
#client.event
async def on_ready():
print('aaaaand were scuffed'.format(client))
###Biome encounter list###
DesertList2 = ['charmander', 'charmeleon', 'charizard']
###commands###
#desert enc
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('!desert'):
mon = random.choice(DesertList2)
print(mon)
await message.channel.send(mon)
#client.event
async def damage(ctx, num1, num2, num3):
result = (num1+num2)/num3
await ctx.send(result)
await client.process_commands(message)
Note(s): I have client.run, just not shown for obvious reasons.
You'd have to create separate argument variables.
#client.command()
async def damage(ctx, num1 : int, num2 : int, num3 : int): # for your 1 2 4 example, 3 number arguments would be sufficient
result = (num1+num2)/num3
await ctx.send(result)
This would do (1+2)/4 and should give you 0.75.
Also, after looking at your imgur image, this is what your on_message function needs to look like:
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('!desert'):
mon = random.choice(DesertList2)
print(mon)
await message.channel.send(mon)
await client.process_commands(message)
#2P1XLS I took the liberty of making your desert command an actual command, since it was previously in the on_message event, and it seems to me that you're trying to use it as a command. However, you can still run it how you were running it previously: !desert. I've also added the await client.process_commands(message) in the on_message event, since that's where it belongs. Try this out:
import discord
import os
import random
import asyncio
client = discord.Client()
from discord.ext import commands
client = commands.Bot(command_prefix='!')
#client.event
async def on_ready():
print('aaaaand were scuffed'.format(client))
#client.event
async def on_message(message):
if message.author == client.user:
return
await client.process_commands(message)
###Biome encounter list###
DesertList2 = ['charmander', 'charmeleon', 'charizard']
###commands###
#desert command
#client.command()
async def desert(ctx):
mon = random.choice(DesertList2)
print(mon)
await ctx.send(mon)
#damage command
#client.command()
async def damage(ctx, num1 : int, num2 : int, num3 : int):
result = (num1 + num2) / num3
await ctx.send(result)
If you run !damage 1 2 4, then it would do (1+2)/4 and would return 0.75. I've tried this code out myself, so it should definitely work. Make sure to copy it exactly. Hope this helped you!
Here is a clean and simple effective way of a calculator command, you can give it endless arguments for it to calculate
By using *, you can pass multiple numbers and .join will join each of the arguments you pass. Here's a simple example,
#client.command()
async def calculate(ctx, operation, *nums):
if operation not in ['+', '-', '*', '/']:
await ctx.send('Please use a valid operation type')
return
var = f' {operation} '.join(nums)
await ctx.send(f'{var} = {eval(var)}')

Discord.py bot clear

Alright so guys i need some help. Basically i am making an discord bot. I'm having problems with clear(purge) command. So this is my code so far:
#client.command(aliases= ['purge','delete'])
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount : int):
if amount == None:
await ctx.channel.purge(limit=1000000)
else:
await ctx.channel.purge(limit=amount)
my problem here is this if amount == None .
Please help me!
Im getting an error that i have missing requied argument...
That's because you're not giving amount the default value None. This is how you should define the function:
#client.command(aliases= ['purge','delete'])
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount=None): # Set default value as None
if amount == None:
await ctx.channel.purge(limit=1000000)
else:
try:
int(amount)
except: # Error handler
await ctx.send('Please enter a valid integer as amount.')
else:
await ctx.channel.purge(limit=amount)
This one is working for me
#client.command()
#has_permissions(manage_messages = True)
async def clear(ctx , amount=5):
await ctx.channel.purge(limit=amount + 1)
I got it from a youtuber channel, you can put the number of the messages u want to clear after the clear command, EX:
-clear 10
Try this:
#client.command(aliases = ['purge', 'delete'])
#commands.has_permissions(manage_messages = True)
async def clear(ctx, amount: int = 1000000):
await ctx.channel.purge(limit = amount)
This should work, as I have a clear command that looks almost exactly like this. The amount param is being converted to an int and if the client doesn't give parameters, the amount will be set at 1000000.
This is the one I'm using atm.
#bot.command(name='clear', help='this command will clear msgs')
async def clear(ctx, amount = 50): # Change amount
if ctx.message.author.id == (YOUR USER ID HERE):
await ctx.channel.purge(limit=amount)
else:
await ctx.channel.send(f"{ctx.author.mention} you are not allowed")
I've just added an 'if' statement for being the only one who can use that command. You can also allow an specific role.
import discord
from discord.ext import commands
client = commands.Bot(command_prefix='>')
#client.event
async def on_ready():
print("Log : "+str(client.user))
#client.command()
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount: int):
await ctx.channel.purge(limit=amount+1)
await ctx.message.delete()
client.run("token")
you can do this:
#client.command(aliases= ['purge','delete'])
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount :int = -1):
if amount == -1:
await ctx.channel.purge(limit=1000000)
else:
await ctx.channel.purge(limit=amount)
I think it should work, if the client doesn't give parameters, the amount will be set at "-1"

How do functions work in cogs (discord.py)?

An error occurs using this code it says bot is not defined. I don't understand cogs that much but I understand a bit of classes too. I wanted to know how functions work in a cog and how variables are assigned like guildstats = ... below.
This is my code: (I am trying to make a database using the discord bot in a guild. The code works without using cogs but I wanted it to be easier to debug any errors so I went for cogs.)
class Boot(commands.Cog):
def __init__(self, bot):
self.bot = bot
guildstats = pd.read_excel('DiscordStats.xlsx',sheet_name=0)
userstats = pd.read_excel('DiscordStats.xlsx',sheet_name=1)
def dataframe_to_excel(df1 = guildstats, df2 = userstats):
with pd.ExcelWriter('DiscordStats.xlsx', mode = 'w') as writer:
df1.to_excel(writer, index=False, sheet_name = 'GuildStats')
df2.to_excel(writer, index=False, sheet_name = 'UserStats')
def guildstats_writer():
guild_row_data = []
for guild in self.bot.guilds:
if '\''+str(guild.id) not in guildstats['GuildID'].to_list():
guild_row_data.append([guild.name,'\''+str(guild.id),'','',False])
else:
pass
guild_row = pd.DataFrame(guild_row_data,columns = guildstats.columns.to_list())
guildstats1 = guildstats.append(guild_row,ignore_index=True)
Boot.dataframe_to_excel(df1=guildstats1)
#commands.Cog.listener()
async def on_ready(self):
Boot.guildstats_writer(self)
await sbot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="for MeepMop ~help"))
print(f'{bot.user} is connected to the following guild:')
for guild in bot.guilds:
print(f'{guild.name} (id: {guild.id})')
def setup(bot):
bot.add_cog(Boot(bot))
You're trying to call the variable bot when you never defined it, your program has no idea what the variable "bot" is, try changing all the times you called bot to instead call self.bot instead
For example your on_ready function should look like this:
#commands.Cog.listener()
async def on_ready(self):
Boot.guildstats_writer(self)
await self.bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="for MeepMop ~help"))
print(f'{self.bot.user} is connected to the following guild:')
for guild in self.bot.guilds:
print(f'{guild.name} (id: {guild.id})')

Resources