I don't know where to start like most things, but for example.
A user says "foo", the bot stores the message, and then says "bar". The closest I could get was this:
message = await channel.send('hmm…')
message_id = message.id
Though this stores the message sent by the bot, and not the user which triggered the function. It also doesn't store the message, just the ID. Please help.
Thanks in advance!
Edit: My goal is kinda like Sx4's suggest feature.
Hi :) not sure exactly what you want but seems like you are looking for the on message event? Here is an example. You should replace client with whatever you named your bot instance.
#client.event
async def on_message(message):
if message.author != client.user: # Avoids loops by checking that the message author is not the bot itself
# Code in here will run when a message is sent
await client.process_commands(message) # Runs all commands contained in the message
If you want to store every message, use something like this to set a variable that you can then do something with:
#client.event
async def on_message(message):
if message.author != client.user:
STORED_MESSAGE = message.content
# Do something with the variable here
await client.process_commands(message)
Or to respond to a message "foo" with "bar":
#client.event
async def on_message(message):
if message.author != client.user:
if message.content == "foo":
await message.channel.send("bar")
await client.process_commands(message)
Related
The title pretty much explains it self but I'll explain it again.
So basically when I have 2 #client.event or 1 #client.command and 1 #client.event line in the code, the whole thing breaks except for the last block of code.
Like in my code here, the first #client.event works fine. The second one doesn't, but the third one does, now if I switch the second one and the third ones place then the second ones works but the third doesn't.
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import asyncio
import time
import random
from discord import Game
Client = discord.client
client = commands.Bot(command_prefix = " ")
Clientdiscord = discord.Client()
#client.event
async def on_ready():
print('{0.user}'.format(client))
print('Is Online')
#client.command
async def cmds(ctx):
await ctx.send('Prefix: v!')
await client.process_commands(ctx)
#client.event
async def on_message(message):
if message.content == 'v!coin':
variable = [
'flip',
'stay',
]
await message.channel.send((random.choice)(variable))
await client.process_commands(message)
client.run("TOKEN")
If you're using the commands framework, you should add all your commands using the #client.commands decorator instead of having logic in your on_message event handler.
If you need to handle on_message events for another reason (examokeL autoresponse to non commands), you need to call await client.process_commands(message) at the end of your on_message event handler function. It should be outside any if statements but still inside the function. Only call process_commands once in your on_message, and never call it inside your commands unless you know exactly what you are doing. Your on_message function should look something like this:
#client.event
async def on_message(message):
# Do whatever here, but don't handle commands
# If you return early, any commands in the message will be skipped
await client.process_commands(message)
So instead of this:
#client.command
async def cmds(ctx):
await ctx.send('Prefix: v!')
await client.process_commands(ctx)
#client.event
async def on_message(message):
if message.content == 'v!coin':
variable = [
'flip',
'stay',
]
await message.channel.send((random.choice)(variable))
await client.process_commands(message)
You should have something like this:
#client.command()
async def cmds(ctx):
await ctx.send('Prefix: v!')
# Send a list of commands here or do whatever this command is supposed to do
# Don't call client.process_commands here
#client.command()
async def coin(ctx):
# Coinflip logic here
# I've added the original logic you had in your question
variable = [
'flip',
'stay',
]
await ctx.send((random.choice)(variable))
# no #client.event or def on_message unless you need to handle raw messages
Also, you don't need these lines of code:
Client = discord.client
client = commands.Bot(command_prefix = " ")
Clientdiscord = discord.Client()
You can just use this:
client = commands.Bot(command_prefix = "v!")
If you are using commands.Bot already, you don't need another discord.Client.
Instead of placing await client.process_commands(message) within your if statement, place it outside of it. Please review the revised code below.
#client.event
async def on_message(message):
if message.content == 'v!coin':
variable = [
'flip',
'stay',
]
await message.channel.send((random.choice)(variable))
await client.process_commands(message)
Please note that you do not need to include await client.process_commands(message) in a command, only in your on_message event.
I wanted to make a command that edits the bot's old message trought another command, example:
user: !cmds
bot: *commands list*
user: !next
bot: *edits old message into a new one*
I have tried many times to make it myself, but I failed all the times, can anyone help me?
How I tried to make it:
#client.command
async def test():
embed=discord.Embed(title="Page1")
await ctx.send(embed=embed)
#client.event
async def on_command(message):
embed2=discord.Embed(title="Page2")
await client.process_commands(message)
if message.content == '$next':
await message.edit(content=embed2)
The on_command event is called whenever a command is called, you didn't register a next command, that's one, second of all on_command doesn't take message argument, it takes the Context(ctx).
An idea to make what you're asking for is having a cog with an instance variable that references to the previous message, then edit it when the next command is called.
class SomeCog(commands.Cog):
def __init__(self, client):
self.client = client
self._previous_message = None
#commands.command()
async def test(self, ctx):
message = await ctx.send("I'll edit this message when you type `$next`")
self._previous_message = message
#commands.command()
async def next(self, ctx):
if self._previous_message is None: # Exiting if the `test` command wasn't called before, i.e the message is a NoneType
return await ctx.send("You need to invoke first `$test`")
await self._previous_message.edit(content="Edited the message")
client.add_cog(SomeCog(client))
I'm guessing you could do it with global or bot vars but this is the best way to do it, in my opinion.
So I want to be able to have my command only work in direct messages, can anyone help?
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('bb!help'):
await message.channel.send('Huge long commands list')
Use isinstance().
isinstance checks whether if an object has the specified type. For example, isinstance(3, int) checks if 3 is an integer (which it is and therefore returns True). In your case you could check if the message.channel is a DMChannel. The correct code would be:
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('bb!help') and isinstance(message.channel, discord.DMChannel):
await message.channel.send('Huge long commands list')
If you're using commands.Bot
#client.command()
#commands.dm_only()
async def command(ctx):
...
If you're using on_message
#client.event
async def on_message(message):
if isinstance(message.channel, discord.DMChannel):
# The message is sent in the dm's of the bot
I have a flip command that returns either heads or tails and it was working fine until I added the on_message function. I did some research on SO and read the documentation and here it says to include await bot.process_commands(message) in the on_message function but that did not solve the issue and the flip command still doesn't work. If I remove the on_message function everything works as expected.
bot.py
import discord
from discord.ext import commands
import random
# from app bot user
# click to reveal
TOKEN = 'token_here'
client = commands.Bot(command_prefix = '!')
#client.event
async def on_ready():
print('Bot ready')
#client.command()
async def flip():
flip = random.choice(['heads', 'tails'])
await client.say(flip)
#client.event
async def on_message(message):
if message.content.upper().startswith('N****'):
await client.send_message(message.channel, "Please do not use that word here.")
client.process_commands(message)
#client.event
async def on_member_join(member):
await client.change_presence(game=discord.Game(name='Hi %s' % (member)))
await client.send_message(member, "Hi %s, Welcome to Carson's Discord Server! This server is fairly NSFW at times; you've been warned! Enjoy your stay :)" % (member))
#client.event
async def on_member_remove(member):
await client.change_presence(game=discord.Game(name='Bye %s' % (member)))
client.run(TOKEN)
When I run the script, everything else works normally with no errors. It's just the commands that don't work. Any insight would be greatly appreciated.
You need to await the last line in on_message as process_commands is a coroutine.
await client.process_commands(message)
If you send !flip in discord, you should be able to receive the appropriate response (heads or tails).
So, I've been trying to make my bot respond to a specific keyword however when I do this the bot either doesn't respond or gives me a bunch of errors. I've tried a few methods of doing this but I didn't have much luck. If anybody can make it work would be glad here are one of the methods I tried using.
if message.content == "keyword":
await client.send_message(message.channel, "Response {0.author.mention}")
You can do this one of two ways, either with the commands extension, or within the on_message event.
Below is an example of how you can do this. With this example, when a user types "!ping" the bot will respond with "Pong". If a message contains the word "foo", then the bot will respond with "bar".
from discord.ext import commands
client = commands.Bot(command_prefix='!')
#client.event
async def on_ready():
print('client ready')
#client.command()
async def ping():
await client.say('Pong')
#client.event
async def on_message(message):
if client.user.id != message.author.id:
if 'foo' in message.content:
await client.send_message(message.channel, 'bar')
await client.process_commands(message)
client.run('TOKEN')