#๐ Question
86 messages ยท Page 1 of 1 (latest)
@quasi shuttle
Remember to:
- Ask your Python question, not if you can ask or if there's an expert who can help.
- Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
- Explain what you expect to happen and what actually happens.
:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.
-# Sorry i fell asleep yesterday and couldn't answer in time
Also i think i'm not doing anything that's against Disocrd's ToS right? If so please let me know๐
Show your code snippet, I'd like to see your approach
Okay, one second
I'm only a beginner btw so it might not be as good
do you want the full code or
You can just share the particular function only, if you shared whole code, it'll be good as well.
okay, i'm js going to share the full code
Make sure to hide your Auth token
Great
if message.author.bot:
return
snipes[message.channel.id] = {
"content": message.content,
"author": message.author,
"time": message.created_at
}```
- This is the event
```@guild_only()
async def snipe(ctx, count: int = 1):
if not await check_permission(ctx):
return
bucket = snipe_cooldown.get_bucket(ctx.message)
retry_after = bucket.update_rate_limit()
if retry_after:
timestamp = int(time.time() + retry_after)
msg = await ctx.send(f"This command is on cooldown. Try again <t:{timestamp}:R>.")
await asyncio.sleep(retry_after)
try: await msg.delete()
except discord.NotFound: pass
return
if ctx.channel.id not in snipes:
msg = await ctx.send("No recently deleted messages in this channel.")
await msg.delete(delay=3)
return
if count > 5:
msg = await ctx.send("You can't snipe more than 5 messages.")
await msg.delete(delay=3)
return
if count < 1:
msg = await ctx.send("Enter a valid number of messages.")
await msg.delete(delay=3)
return
snipe_data = snipes[ctx.channel.id]
embed = discord.Embed(
color=discord.Color.orange(),
timestamp=snipe_data["time"]
)
embed.add_field(name=f"Content", value=snipe_data["content"], inline=False)
embed.set_author(
name=f"Message sent by {snipe_data["author"]}",
icon_url=snipe_data["author"].display_avatar.url
)
embed.set_footer(text=f"Sniped by {ctx.author}")
await ctx.send(embed=embed)```
- This is the command
Hey @quasi shuttle!
Add a py after the three backticks.
```py
print('Hello, world!')
```
This will result in the following:
print('Hello, world!')```
This is the problem
The event
You are assigning message to dictionary, which overwrites the old message
You should append here
you would have to store the deleted messages in a queue per channel
if there should be a limit on 5 messages per channel the queue per channel should never get any bigger then 5 elements, so that it doesn't grow unbounded
from collections import defaultdict, deque
snipes = defaultdict(lambda: deque(maxlen=5))
async def on_message_delete(message):
if message.author.bot:
return
snipes[message.channel.id].appendleft({
"content": message.content,
"author": message.author,
"time": message.created_at
})
This can be a snippet
This is exactly what i tried but i was getting some kind of an error for some reason
Should i only change the event or?
you probably want to adjust how you retrieve the snipes in your command as well
Okay, lemme test out the deque thing first tho
RuntimeWarning: coroutine 'Command.call' was never awaited
snipe_data_list = list(snipes[ctx.channel.id])[:count]
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Unhandled error: Command raised an exception: TypeError: 'coroutine' object is not subscriptable
here, the same exact error i was getting like 2 days ago
i tried fixing it by doing (await list(snipes[ctx.channel.id]))[:count]
but then i got another error i think
I guess its because of missing decorator
you're calling @guild_only(), there should also be @commands.command()
yea ik
oh
no wait
yea yea ik, im doing that
i just didnt include it in the code my bad
i tried fixing it by typing snipe_data_list = (await list(snipes[ctx.channel.id]))[:count]
but then i get this error:
Command raised an exception: AttributeError: 'collections.deque' object has no attribute 'guild'
Click here to see this code in our pastebin.
@quasi shuttle This will work
okay, i'm going to test it
btw i'm not using cogs yet so should i include it
in the code
i plan on adding Cogs when the bot is completely done
you could do:
for i, snipe_data in enumerate(snipe_data_list, start=1):
```so that the `+ 1` isn't necessary later in the code after the `i`
Oh Yes, that would be cleaner and avoid any potential errors
please open your own help thread or check in #cybersecurity
Depends on you, I like to structure everything since beginning
don't write in other peoples help threads unless you are there to help the OP of that help thread or have a comment or question on the topic that is discuses their that could also benefit OP of that same help thread
!rule money
I am new on discord..
@teal crystal this as well, it applies to this whole server ๐
it doesn't exempt you from reading our #rules and #code-of-conduct first before starting to post on this server
and again, stop writing in this help thread unless you are here to help OP that owns this thread
OK!
This was my whole code, including testcase... Take reference if you face any further problems.
Click here to see this code in our pastebin.
def __init__(self, bot):
self.bot = bot
# Event: Save deleted messages
@commands.Cog.listener()
async def on_message_delete(self, message):
if message.author.bot:
return
# Skip if message has no content (embeds, images, etc.)
if not message.content:
return
# Append to deque instead of overwriting
snipes[message.channel.id].appendleft({
"content": message.content,
"author": message.author,
"time": message.created_at
})
@client.command()
@guild_only()
async def snipe(self, ctx, count: int = 1):
if not await check_permission(ctx):
return
# Cooldown handling
bucket = snipe_cooldown.get_bucket(ctx.message)
retry_after = bucket.update_rate_limit()
if retry_after:
timestamp = int(time.time() + retry_after)
msg = await ctx.send(f"This command is on cooldown. Try again <t:{timestamp}:R>.")
await asyncio.sleep(retry_after)
try:
await msg.delete()
except discord.NotFound:
pass
return
# No deleted messages
if ctx.channel.id not in snipes or not snipes[ctx.channel.id]:
msg = await ctx.send("No recently deleted messages in this channel.")
await msg.delete(delay=3)
return
```
Hey @quasi shuttle!
Add a py after the three backticks.
```py
print('Hello, world!')
```
This will result in the following:
print('Hello, world!')```
if count > 5:
msg = await ctx.send("You can't snipe more than 5 messages.")
await msg.delete(delay=3)
return
if count < 1:
msg = await ctx.send("Enter a valid number of messages.")
await msg.delete(delay=3)
return
# Grab last `count` deleted messages
snipe_data_list = list(snipes[ctx.channel.id])[:count]
if not snipe_data_list:
msg = await ctx.send("No recently deleted messages in this channel.")
await msg.delete(delay=3)
return
for i, snipe_data in enumerate(snipe_data_list):
embed = discord.Embed(
color=discord.Color.orange(),
timestamp=snipe_data["time"]
)
# Truncate long messages
content = snipe_data["content"]
if len(content) > 1024:
content = content[:1021] + "..."
embed.add_field(
name="Content",
value=content or "*No text*",
inline=False
)
embed.set_author(
name=f"Message sent by {snipe_data['author']}",
icon_url=snipe_data["author"].display_avatar.url
)
embed.set_footer(text=f"Sniped by {ctx.author} โข Message {i+1}/{len(snipe_data_list)}")
await ctx.send(embed=embed)```
is this going to work (I cut it in 2 parts cuz discord didnt let me send it)
Test it, I already shared my whole code, You can take reference from that as well... If you Get any error then show us here
Command raised an exception: AttributeError: 'int' object has no attribute 'guild'
i am getting this with the code i shared
and with your code i am getting another error that's part of the on_command_error event
Have you pasted it correctly? It ran smoothly on my system, compare with my whole code that I shared
yep
i am getting this error ```in on_command_error
if ctx.command.name == "add":
^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'name'
i'm getting this cuz i have another command
called "add"
but idk why that's popping up rn
i removed that statement and now i'm not getting any errors but nothing's happening
could it be cuz i don't have Cogs
i can also try to implement Cogs to the bot rn, instead of waiting until everything's finished
This help channel has been closed. Feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.