Code:
import discord
class MyClient(discord.Client):
async def on_ready(self):
print('Logged in as')
print(self.user.name)
print(self.user.id)
print('------')
async def on_message(self, message):
words = [] # List of words to look for
if message.author.id == self.user.id:
return
for i in words:
if i in message.content.lower():
await message.channel.send(f"Hey <#{message.author.id}>, i have noticed that in your message is a word on a list")
break
await message.add_reaction("✅")
await client.wait_for("reaction_add")
await message.delete()
client = MyClient()
client.run("TOKEN")
How Could i make the bot add reaction to its own message and if the user uses it delete its own message
i did look for the answer but god is discord.py messy, i have seen 6 answers that did not work and all of them seemed like they use different modules
i apologize if the answer was easy to find, but i just couldnt
First of all, you should always try to find your answer in the documentation (discord.py documentation). (Off-topic: it's not discord.py that's messy; it's likely the method you are using to find answers which is messy.)
The TextChannel.send() method returns the message which was sent. So, you could just assign that return value to a variable.
For the other issue, there is an event listener which detects message deletions, on_message_delete()
import discord
class MyClient(discord.Client):
async def on_ready(self):
...
async def on_message(self, message):
words = []
if message.author.id == self.user.id:
return
for i in words:
if i in message.content.lower():
sent_message = await message.channel.send(
f"Hey {message.author.mention}, I have noticed that in your message is a word on a list"
)
break
await sent_message.add_reaction("reaction")
await message.add_reaction("✅")
await client.wait_for("reaction_add")
await message.delete()
async def on_message_delete(self, message):
# Do stuff here
client = MyClient()
client.run("TOKEN")
(On a side note, you can use Member.mention to mention/ping a member, instead of "<#{message.author.id}>".)
In my opinion, it is preferable to use the #client.event method decorator above your event methods instead of putting them in their own class. You would declare the client object as client=discord.Client() at the top, then put #client.event above your event handling methods. The on_reaction_add method can have reaction and message parameters to respond.
Related
Good afternoon! I am new to Python , and I am working on a discord bot. I keep suffering from this error: AttributeError: 'Client' object has no attribute 'command'. I tried everything to repair this, but I did not know. Any help would be fine. Please help me!
Here is the code:
import discord
import random
from discord.ext import commands
class MyClient(discord.Client):
client = commands.Bot(command_prefix = '?')
# Start
async def on_ready(self):
print('Logged on as', self.user)
# Latency
client = discord.Client()
#client.command()
async def ping(ctx):
await ctx.send(f'Pong! {round(client.latency * 1000)}ms')
# 8ball
#client.command(aliases=['8ball'])
async def _8ball(ctx, *, question):
responses = ['Biztosan.',
'Nagyon kétséges.']
await ctx.send(f'Kérdés: {question}\nVálasz: {random.choice(responses)}')
# Clear
#client.command()
async def clear(ctx, amount=5):
await ctx.channel.purge(limit=amount)
await ctx.send(f'Kész!')
async def on_message(self, message):
word_list = ['fasz', 'kurva', 'anyad', 'anyád', 'f a s z', 'seggfej', 'buzi', 'f.a.s.z', 'fa sz', 'k U.rv# any#dat']
if message.author == self.user:
return
messageContent = message.content
if len(messageContent) > 0:
for word in word_list:
if word in messageContent:
await message.delete()
await message.channel.send('Ne használd ezt a szót!')
messageattachments = message.attachments
if len(messageattachments) > 0:
for attachment in messageattachments:
if attachment.filename.endswith(".dll"):
await message.delete()
await message.channel.send("Ne küldj DLL fájlokat!")
elif attachment.filename.endswith('.exe'):
await message.delete()
await message.channel.send("Ne csak parancsikont küldj!")
else:
break
client = MyClient()
client.run(token)
There are a multitude of ways to make your bot, and it seems you tried to mash 2 ways of making it together.
Option 1: using the pre-made commands bot class
client = commands.Bot(command_prefix = '?')
client.command()
async def command_name(ctx, argument):
#command function
client.run(token)
Option 2: making you own subclass of client
class MyClient(discord.Client):
async def on_message(self, message):
if message.content.startswith('command_name'):
#command functionality
client = MyClient()
client.run()
You can use either of the two options, but not both at the same time (you could actually do that, but not in the way you did)
Also I would advice staying away from discord.py to learn python as asyncio is pretty complex
Why don't you simply define client like this?
client = commands.Bot(...)
Also you have defined it a couple of times in the code, delete them all and define it only ONCE at the top of the code after the imports. This is a really bad question, you should learn a lot more python before diving deeper into discord.py.
I am coding a discord bot and i think there has got to be a much easier/ simpler way to detect messages using the prefix for commands (and easy to expand in future), my code at the moment just scans each message to see if it contains the exact command, maybe a class will help?
#client.event
async def on_message(message):
# print message content
print(message.content)
# if the message came from the bot ignore it
if message.author == client.user:
return
# if the message starts with "!repeat" then say the message in chat
if message.content.startswith("!repeat"):
sentmessage = message.content.replace("!repeat", "")
await message.channel.send(sentmessage)
if "hello" in message.content.lower():
await message.channel.send("Hello!")
if message.content.startswith("!cleanup"):
if not message.author.guild_permissions.administrator:
await message.channel.send("You do not have permission to run this command!")
else:
num2c = 0
num2c = int(message.content.replace("!cleanup", ""))+1
print(num2c)
await message.channel.purge(limit=num2c)
num2c = num2c-1
cleanmessage = str("Cleared "+str(num2c)+" Messages.")
await message.channel.send(cleanmessage, delete_after=5)
You can use commands.Bot, it has a built-in command system, here's an example:
import discord
from discord.ext import commands
# enabling intents
intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)
#bot.command()
async def foo(ctx, *args):
await ctx.send('whatever')
# You also have all the functionality that `discord.Client` has
#bot.event
async def on_message(message):
# ...
# you always need to add this when using `commands.Bot`
await bot.process_commands(message)
bot.run('token')
Take a look at the introduction
The Problem
I am running a bot event on a cog and I want to delete a message if it is not in the right channel. However, on_message only seems to take the messages argument so I cannot delete the message sent in context:
#commands.Cog.listener()
async def on_message(self, message):
musicchannel = self.bot.get_channel(705116959804489898)
if message.content.startswith('-p'):
if message.channel.id == musicchannel.id:
pass
else:
await message.channel.send("```ini\n[Music commands only in the appropriate channel]```", delete_aft$
await asyncio.sleep(4)
message.delete()
Usually you would have the ctx argument so it's as simple as ctx.message.delete() but that will not work in this case.
What I've tried
I have attempted to fetch the message with self.bot.fetch_message(message.id) but bot does not take the attribute fetch_message().
Solution
Somehow I didn't notice it straight away but all you need is await as .delete() is a co-routine.
All you're missing is await. As delete() is a co-routine, you just need to modify the event so that:
#commands.Cog.listener()
async def on_message(self, message):
musicchannel = self.bot.get_channel(705116959804489898)
if message.content.startswith('-p'):
if message.channel.id == musicchannel.id:
pass
else:
#code
await message.delete()
References:
Message.delete()
I'm trying to make a bot for a discord server that simply listens for specific messages, deletes them and then refers the user to a different text channel (in a clickable link by mentioning it)
Here's what I have now:
import Discord
import asyncio
client = discord.Client()
#client.event
async def on_message(message):
msg = '{0.author.mention}\nWrong text channel\nUse '.format(message)
if message.content.startswith('!p'):
await client.delete_message(message)
await client.send_message(message.channel, msg)
return
client.run('')
Ideally, I'd also want to search through a list with startswith() instead of just ('!p') & to ignore all messages from a specific text channel as well but I'm not sure how to do those either
Don't know if your problem is solved or not, but for all future developers looking on this thread. A super simple way to get a bot to mention a channel is like this...
<#channelID>
were the channel ID is the discord ID of the specific channel you wish to mention.
and in an example
await message.channel.send("Please go to <#channelID>")
I'm honestly a bit confused that no one on this thread has already mentioned this, so I feel like I'm missing something that y'all already know lol.
Sure, just add text_channel = client.get_channel('1234567890') and reference its mention with text_channel.mention (where 1234567890 is the id of the channel you want to link to)
So the code would end up looking something like this
#client.event
async def on_message(message):
text_channel = client.get_channel('1234567890')
msg = '{0.author.mention}\nWrong text channel\nUse {1.mention}'.format(message,text_channel)
if message.content.startswith('!p'):
await client.delete_message(message)
await client.send_message(message.channel, msg)
return
Regarding your second question, you could do something like this
arr = ['!p','!a','!b']
for a in arr:
if message.content.startswith(a):
break
else:
return
and remove the if message.content.startswith('!p'): altogether
To ignore a specific channel just do if message.channel.id == "9876543210": at the top of the function (9876543210 is the id of the channel you want to ignore commands from)
With those changes the code looks like this
#client.event
async def on_message(message):
if message.channel.id == "9876543210":
return
arr = ['!p','!a','!b']
for a in arr:
if message.content.startswith(a):
break
else:
return
text_channel = client.get_channel('1234567890')
msg = '{0.author.mention}\nWrong text channel\nUse {1.mention}'.format(message,text_channel)
await client.delete_message(message)
await client.send_message(message.channel, msg)
return
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()
async def mention(ctx):
ch = await client.fetch_channel(enter channel id)
await ctx.send(f"Mention your channel -> {ch}")
client.run("token")
I have searched around a lot for this answer, and I haven't found it. I want to use a suggestion command, that whenever someone uses it to suggest an idea, it DMs me, and me only.
You'll have to use the send_message method. Prior to that, you have to find which User correspond to yourself.
#client.event
async def on_message(message):
# we do not want the bot to reply to itself
if message.author == client.user:
return
# can be cached...
me = await client.get_user_info('MY_SNOWFLAKE_ID')
await client.send_message(me, "Hello!")
#client.event
async def on_message(message):
if message.content.startswith("#whatever you want it to be")
await client.send_message(message.author, "#The message")
Replace the hashtagged things with the words that you want it to be. eg.: #whatever you want it to be could be "!help". #The message could be "The commands are...".
discord.py v1.0.0+
Since v1.0.0 it's no longer client.send_message to send a message, instead you use send() of abc.Messageable which implements the following:
discord.TextChannel
discord.DMChannel
discord.GroupChannel
discord.User
discord.Member
commands.Context
Example
With bot.command() (recommended):
from discord.ext import commands
bot = commands.Bot(command_prefix="!")
#bot.command()
async def suggest(ctx, *, text: str):
me = bot.get_user(YOUR_ID)
await me.send(text) # or whatever you want to send here
With on_message:
from discord.ext import commands
bot = commands.Bot()
#bot.event
async def on_message(message: discord.Message):
if message.content.startswith("!suggest"):
text = message.content.replace("!suggest", "")
me = bot.get_user(YOUR_ID)
await me.send(text) # or whatever you want to send here