Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Discord.py Snipe command

Im trying to make a command where the bot "snipes" the last deleted message. this is my current code:


snipe_message_content = None
snipe_message_author = None

@client.event
async def on_message_delete(message):
    snipe_message_author.remove(None)
    snipe_message_content.remove(None)
    snipe_message_content.append(message.content) 
    snipe_message_author.append(message.author.id) 
    await asyncio.sleep(str(60))
    snipe_message_author.remove(message.author.id)
    snipe_message_content.remove(message.content)
    

@client.command()
async def snipe(message):
    if snipe_message_content==None:
        await message.channel.send("Theres nothing to snipe.")
    else:
        embed = discord.Embed(description=f"{snipe_message_content}")
        embed.set_footer(text=f"Asked by {message.author.name}#{message.author.discriminator}", icon_url=message.author.avatar_url)
        embed.set_author(name= f"<@{snipe_message_author}>")
        await message.channel.send(embed=embed)
        return

the await message.channel.send("Theres nothing to snipe.") part works perfectly fine, but the rest wont work. Can anyone help?

like image 936
Willwell Avatar asked Jan 25 '23 16:01

Willwell


2 Answers

Well your on_message_delete() function is just not working.

I'll shorten your variables as smc (snipe_message_content) and sma (snipe_message_author).

First of all, your variables sma and smc are of the type None, but the methods remove and append are part of the type list, so you'd have to declare lists

smc = []
sma = []

in order for them to work.

Still, you wouldn't have to do this anyway. Just give your current variables a new value:

snipe_message_content = None
snipe_message_author = None

@client.event
async def on_message_delete(message):

    global snipe_message_content
    global snipe_message_author
    # Variables outside a function have to be declared as global in order to be changed

    snipe_message_content = message.content
    snipe_message_author = message.author.id
    await asyncio.sleep(60)
    snipe_message_author = None
    snipe_message_content = None

Also, you should not convert 60 to a string. time.sleep and asyncio.sleep both need an integer in order to work. (And by the way, if you wanted 60 to be a string, just write "60" with quotation marks.

Also, be careful of the following case: If a message gets deleted, but 50 seconds after a new message gets deleted, sma and smc would be assigned to the new message. But 10 seconds later, the function executed by the message before would set he value of sma and smc to None.

Therefore, after await asyncio.sleep(60) check wether your message is still the same as before:

snipe_message_content = None
snipe_message_author = None
snipe_message_id = None

@client.event
async def on_message_delete(message):

    global snipe_message_content
    global snipe_message_author
    global snipe_message_id

    snipe_message_content = message.content
    snipe_message_author = message.author.id
    snipe_message_id = message.id
    await asyncio.sleep(60)

    if message.id == snipe_message_id:
        snipe_message_author = None
        snipe_message_content = None
        snipe_message_id = None
like image 164
Thörni Avatar answered Feb 09 '23 02:02

Thörni


Your command works now probably, but there's a problem. If I delete a message in my server, and you run the command in your server, you'll probably see the message.

What you should do is make the snipe_message_author and snipe_message_content variables dictionaries.

This is how the event should be:

snipe_message_author = {}
snipe_message_content = {}

@client.event
async def on_message_delete(message):
     snipe_message_author[message.channel.id] = message.author
     snipe_message_content[message.channel.id] = message.content
     await sleep(60)
     del snipe_message_author[message.channel.id]
     del snipe_message_content[message.channel.id]

@client.command(name = 'snipe')
async def snipe(ctx):
    channel = ctx.channel
    try: #This piece of code is run if the bot finds anything in the dictionary
        em = discord.Embed(name = f"Last deleted message in #{channel.name}", description = snipe_message_content[channel.id])
        em.set_footer(text = f"This message was sent by {snipe_message_author[channel.id]}")
        await ctx.send(embed = em)
    except KeyError: #This piece of code is run if the bot doesn't find anything in the dictionary
        await ctx.send(f"There are no recently deleted messages in #{channel.name}")


#If the bot sends the embed, but it's empty, it simply means that the deleted message was either a media file or another embed.


To summarize it, here's what this fixes for you:

  • Doesn't show deleted messages from other servers
  • Doesn't show deleted messages from other channels
  • Deleted message in one server won't replace the deleted message in another server

Hope this helped :)

like image 21
StatTrakDiamondSword Avatar answered Feb 09 '23 01:02

StatTrakDiamondSword