Discord Bot Python Deleting Author's Message - python

I made a small discord bot for some fun:
I want the author's messages to be deleted when Author run this command. But this does not work.
if message.content.startswith('Delete me.'):
async for msg in client.logs_from(message.channel, message.author):
await client.delete_message(msg)

Looking at their docs, logs_from takes a channel, along with additional arguments allowing you to
filter which messages to retrieve.
So if you just wanted to delete all messages, you can do something like
async def on_message(message):
NONSENSE_LIMIT = 999999999999
if message.content.startswith('!delete'):
async for log in client.logs_from(message.channel, limit=NONSENSE_LIMIT):
if log.author == message.author:
await client.delete_message(log)
Which will delete all messages for a user that types in that command. Your bot must have the manage messages permission for that channel.
Note that the number of messages returned is limited, and here I just write down some arbitrary nonsense limit. If you want to be accurate, you would have to figure out how many messages there are in the channel somehow, and then use that as the limit.
I just looked up discord API in the last 5 minutes so I don't know if there's a more efficient way to do it.

Your problem is in the client.logs_from(message.channel, message.author)statement. logs_from accepts the following arguments: logs_from(channel, limit=100, *, before=None, after=None, around=None, reverse=False). See the API reference. So you have two channel arguments where logs_from only accepts 1. Perhaps you intended client.logs_from(message.author) instead?

Related

Discord.py bot command to search channel for keywords and copy message to another channel

Edit for follow up Question -
Using the previous suggestion I got it to work. Then I decided I needed variables with all of the channel ids rather than everyone having to know the IDs. Is it possible to have the user input be a variable, to where the bot will then use the ID stored in that variable? I believe it'll work by using a converter.
I've got some code I've pieced together from various sources on here. My goal is to have a bot command that will search the given channel for a keyword. Upon finding a message with the keyword in the channel, it will copy that message into another channel then delete the original message.
I'm also trying to do this with user given arguments, so I don't have to change the code for every keyword.
This is what I have so far.
#bot.command()
async def move_information(ctx,Keyword: discord.Message,ChannelFrom: int,ChannelTo: int):
for message in ChannelFrom:
msg = await ctx.fetch_mesage(Keyword)
await ChannelTo.send(msg)
discord.message is an object, if you are searching for messages in a specific textchannel then it would be something like this
#bot.command()
async def move_information(ctx,Keyword: str, ChannelFrom: discord.TextChannel, ChannelTo: discord.TextChannel):
async for message in ChannelFrom.history:
if Keyword in message.content:
await ChannelTo.send(Keyword)

Is there kind of a limit for asyncio in discord.py?

So I‘ve got a python discord bot. The idea is, there is a channel for funny quotes. In order to keep the channel organized, people can as well discuss in it, but after 24h their message should be deleted, if there‘s no %q before it. I‘ve got the following code:
#bot.event
async def on_message(ctx):
await bot.process_commands(ctx)
channel = bot.get_channel(ID_OF_CHANNEL)
if ctx.channel == channel:
if not ctx.content.lower().startswith("%q"):
await asyncio.sleep(86400)
await ctx.delete()
The problem is, it just doesn‘t work. The bot responds to other commands, but doesn‘t delete every single message after 24h. In fact, it doesn‘t delete any messages. I‘ve tried it with only 3h as well, but it didn‘t work too. Passing in only 30 seconds works…
I‘m sorry if my question may be stupid, but I‘m just clueless and I hope anybody can help me :)
May there be a limit of messages the bot can view or a limit of time it can do so?
Btw: I‘m pretty sure the bot was running all the time, so it was not interrupted.
EDIT: Just to make that clear: The idea is to start something like a timer on every single message, which works for 30 seconds, but strangely not for 3h.
Try using tasks instead of asyncio. It is made for such repetetive operations and it is easier and nicer because it is made by discord and is included in discord.ext. The way I would do it is something like this:
from discord.ext import tasks
#bot.command()
async def start(ctx):
deletingLoop.start() #here you start the loop
#tasks.loop(hours=24)
async def deletingLoop():
guild = self.bot.get_guild(guildID) #get the guild
channel = guild.get_channel(channelID) #and the channel
channel.purge(limit=1000) #clear the channel
and if you are afraid that this channel may have more than 1000 messages you can add on_message() event that would count the messages on this channel.
You have to take ctx.message as you want to delete the message of the context. This can take the parameter delay which deletes the selected message after that amount of time.
Code:
#bot.event
async def on_message(ctx):
await bot.process_commands(ctx)
channel = bot.get_channel(ID_OF_CHANNEL)
if ctx.channel == channel:
if not ctx.content.lower().startswith("%q"):
await ctx.message.delete(delay=24h_in_seconds)

My purge command keeps getting rate limited

This is my purge command and although it works fine it keeps getting rate limited after I purge 30 massages or more.
#commands.command()
async def purge(self, ctx, num):
'''
Clears messages.
'''
embed = discord.Embed(title="🧹**MESSAGES PURGED**🧹", description=" ", color=0x0059ff)
async for message in ctx.channel.history(limit=int(num) + 1):
await message.delete(delay=0.5)
await ctx.send(embed=embed)
Any help is appreciated
I looked at your code and I understood that you are using a difficult path to create a purge command. Discord.py library has a coroutine called purge whose job is just to delete messages. Rather than using a loop and various other methods, it would be better to use it.
I created a purge command first which has the following code:
#nucleobot.command()
#commands.has_permissions(manage_messages=True)
async def purge(ctx, limit: int):
await ctx.message.delete()
await asyncio.sleep(1)
await ctx.channel.purge(limit=limit)
purge_embed = discord.Embed(title='Purge [!purge]', description=f'Successfully purged {limit} messages. \n Command executed by {ctx.author}.', color=discord.Colour.random())
purge_embed.set_footer(text=str(datetime.datetime.now()))
await ctx.channel.send(embed=purge_embed, delete_after=True)
How does this code work?
The command usage is deleted, i.e., !purge 10 would be deleted when sent into the chat.
It would pause for 1 second due to await asyncio.sleep(1). You would need to import asyncio in order to use it. (You might know that already :D)
The number of messages your entered are cleared from the channel using await ctx.message.delete(limit=limit) (This is a discord.py coroutine)
purge_embed is the embed variable which is used to send the embed after the deletion. I have used datetime module to add the time of the command completion on the embed. (You need to import datetime as well, but only if you want to use it. If not then remove the footer code.)
This would make up your complete and working purge command. :D
Examples with images.
I created a new channel and added 10 messages with numbers from 1 to 10 as shown below:
Then I entered the command in the message box and it was like (I know it was not needed but never mind):
After I sent this message and the command was executed, the purge successful embed was posted by the bot:
I was glad I could help. Any doubts of confusions are appreciated. Ask me anytime. :D
Thank You! :)

How do I get a bot to mention someone?

I've been trying to make my bot mention someone for a command for a while, I was looking around Google and other websites and most of them where specific people like using <#(User ID)> but I want to make it mention whoever, like, when I use a command like "?hit" I would like it to say "(bot pings who used the command) punches (person pinged in command)
(Random message idk)"
I can't find a website or video of how to do it I need a little help.
Every Member object is mentionable (using the mention function), read up on the docs here. Using that, we can create a command which takes in a member to hit. Then, we can ping the ctx.author and member using the function mention. It would look something like:
#client.command()
async def hit(ctx, member: discord.Member):
await ctx.send(f"{ctx.author.mention} punches {member.mention}")
Output:
I don't mean to be rude but this question was easily answered by looking at the discord API docs, as it explains everything in the API and what it does. My solution is below. You didn't provide any code or problem you've had with code so this is all I can do.
#client.command() # here, we make the client command.
async def hit(ctx, member : discord.Member): # we are making the function that actually hits the person here.
await ctx.send(f'{ctx.message.author.mention} hits {member.mention}.') # here, we send the message that pings both the user who triggered the command, and the person who the you want to ping.
If you wanted to have it select from a list, for example, here's how that'd work.
#client.command()
async def hit(ctx, member : discord.Member):
# this is a list of random responses that could happen.
hit_responses = [f'{ctx.message.author.mention} hits {member.mention}.',
f'{ctx.message.author.mention} swings and hits {member.mention}.',
f'{ctx.message.author.mention} slaps {member.mention} across the face.']
hit_message = random.choice(hit_respones) # this chooses a random response.
await ctx.send(hit_message) # this sends the random response
An example output would be as follows:
#goose.mp4 slaps #user across the face.

How do I move a user to a specific channel on discord using the discord.py API

Okay, so I know the command to do this but my issue is I do not know what arguments to pass to the parameters. I want my code to take a user's message content and then move the user to a voice channel named "afk". Here is a snippet of my code:
All I want to do is move a user that types the words !move in any case to be moved to another voice channel.
I am sorry if my code is bad but I just need this down.
I know you might need to see my definitions but all it is:
def on_message(message):
if '!MOVE' in message.content.upper():
author = message.author
voice_channel = id('afk')
await client.move_member(author, voice_channel)
client.move_member takes two arguments: a Member and a Channel. We can use discord.utils.find to get the channel from the servers list of channels.
channel = discord.utils.find(lambda x: x.name == 'afk', message.server.channels)
await client.move_member(message.author, channel)
Some further notes:
The above is actually unnecessary for the afk channel, as servers have a Server.afk_channel attribute.
You should also be using the discord.ext.commands extension to implement your commands, to keep your on_message from getting cluttered.

Categories

Resources