DiscordPy clear hybrid command - Only works properly with prefix, not as slash command - discord.py

Good day folks. I have the following clear command:
#clear command
#commands.hybrid_command(name = "clear", with_app_command = True, description = "Need to clear?",ephemeral = True)
#commands.has_permissions(manage_messages=True)
async def clear(self,ctx: commands.Context, limit:int = None):
if limit == None:
limit = 5
await ctx.channel.purge(limit=limit+1)
#await ctx.reply(f'Successfully cleared {limit} messages.')
The command works properly deleting messages. However when I call it as a slash command, it will clear the messages but return a "The application did not respond" message.
I've tried using ctx.reply and ctx.send on the commented line but none of them do the trick.
I also get a "In message_reference: Unknown message".
Any help is appreciated.

"The application did not respond" message.
For application commands, you have to respond within 3 seconds. As you are clearing messages beforehand (which is an API call that may take some time to complete) you're probably exceeding this deadline.
If what you're doing is slow, you must first defer and then followup afterwards. The library can handle this automatically for you in hybrid commands using Context.typing().

Related

Discord.py Bot Autodelete

Im new to python (i learned the basics at a school course),
and for the moment im trying to create simple bots for my discord server.
And for the moment, the bot i really want, is an autodelete bot so that i can say, (for example) delete every message in the ...Channel after 24h. because i really dont wanna do that manually.
I know there are a few good bots that do that,
but for example MEE6 wants me to buy Premium to use the funktion.The other reason why i dont want to use any finished bot is that i really want to understand and learn the code,
i watched many tutorials and tried to put the parts of the scripts that i understood together, but it did not work. I also didnt find a tutorial which explained it to me so that i understood, so now im here and hope that im going to understand it.
I hope there are some ppl to help me. :)
Thanks
-Yami.Code
#bot.event()
async def on_ready(ctx):
while requirement == 1:
await ctx.channel.purge
time.sleep(20)
#the Error is:
line 11, in <module>
#bot.event()
TypeError: event() missing 1 required positional argument: 'coro'
Process finished with exit code 1
You shouldn't call bot.event (remove the parenthesis),
time.sleep is a blocking call, use asyncio.sleep instead (What does "blocking" mean)
on_ready doens't take ctx as an argument, if you want to send a message to a channel you should get the channel object first, and then use the send method
You're missing a parenthesis in your channel.purge method...
import asyncio # if you haven't already
#bot.event
async def on_ready():
channel = bot.get_channel(channel_id) # replace `channel_id` with an actual channel ID
while requirement == 1:
await channel.purge(limit=x) # change `x` accordingly...
await asyncio.sleep(20)

discord.py save every message in specific channel (using channel id)

How can a python bot read every message that is sent in a certain channel or read every message that was sent in one using a command like $save 421345187663708161. Thanks in advance, havent been able to find the answer anywhere.
I made this in an on_message Function which scans the message content for "$save" on the beginning, then gets the channel per the given ID.
#client.event
async def on_message(message):
if message.content.startswith("$save"):
splittedcontent = message.content.split()
channel = client.get_channel(splittedcontent[1])
all_messages = channel.history()
What your job now is, is to understand this code, maybe inform about the things that are going on here (like channel.history) and implement this to your code (preferably also with some try/except cases).

How to keep browser opening by the end of the code running with playwright-python?

I want to use playwright-python to fill some forms automatically. And then double check the filling before submit. But it always close the browser by the end of the code running. Even if I used the handleSIGHUP=False, handleSIGINT=False, handleSIGTERM=False launch arguments, and didn't use any page.close() or browser.close() in my code, it still close the browser after the code finished.
Does anyone know how to do it?
The browser is started by the python script, so it will end, when the script ends.
So you need to keep the script alive.
For the async part it is a bit tricky.
I assume you have same kind of:
asyncio.get_event_loop().run_until_complete(main())
so in the async main routine you need to keep the async loop running:
e.g. waiting for the keyboard:
import asyncio
from playwright.async_api import async_playwright
from playwright.async_api import Page
async with async_playwright() as p:
async def main(run_forever: bool):
browser = await p.__getattribute__(C.BROWSER.browser).launch(headless=False, timeout=10000)
page = await browser.new_page()
if run_forever:
print('Press CTRL-D to stop')
reader = asyncio.StreamReader()
pipe = sys.stdin
loop = asyncio.get_event_loop()
await loop.connect_read_pipe(lambda: asyncio.StreamReaderProtocol(reader), pipe)
async for line in reader:
print(f'Got: {line.decode()!r}')
else:
browser.close()
get see worked link
Context:
Playwright Version: 1.16
Operating System: Windows
Node.js version: 14.18.1
Browser: All
Overview
There are multiple ways to turn on the Inspector, as explained in https://playwright.dev/docs/inspector
As per docs, when we set "PWDEBUG", it also disables the timeout, by setting it to 0. This is a good idea, as it allows the user to click around the inspector without a time limit.
However, this is not the case with page.pause(). This option also opens the inspector, but the timeout is not set to 0, thus the inspector will force exit after 30s with e.g.
Slow test: tests\my_test.test.js (30s)
The same behavior is mentioned in a Feature request here: #10132
And I believe it should be fixed to match the default behaviour of other options, at least for consistency reasons. For example, in Java binding, page.pause() does not require timeOut to be explicitly disabled.

Twisted reactor not calling functions from thread correctly

I am having problems with twisted.internet.reactor All my clients have completely identical environments, but only some experience this problem:
They correctly connectTCP to the server via ws and exchange first several messages. About one minute in, they should send a message to the server via
def execute(self, message, callback=None):
print(">>>", message, flush=True)
reactor.callFromThread(self._client_protocol_instance.send, message, callback)
self._client_protocol_instance.send method is defined as follows:
def send(self, command, callback):
print("send", command, callback, flush=True)
timestamp = int(time() * 1000000)
msg = (command.strip() + " --timestamp:" + str(timestamp))
if _self._debug:
_self._commands[str(timestamp)] = msg
if callback is not None:
_self._callbacks[str(timestamp)] = callback
payload = msg.encode()
_self._status_controller.set_state(payload)
self.sendMessage(payload)
First print shows up in stdout, but second one doesn't. I assume that send doesn't get executed. After reactor.run(), this is the only reference to the reactor in the entire program.
Killing client's process after this happens is immediately detected by the server, so the connection was still alive at that time.
What could be causing this?
I found the solution, the problem lied with the fact that the previous task wouldn't finish sometimes by the time it tried to send the message.
I solved it by moving all cpu-heavy response handling logic into threads to free up the reactor for other messages.

Delayed Job creating Airbrakes every time it raises an error

def perform
refund_log = {
success: refund_retry.success?,
amount: refund_amount,
action: "refund"
}
if refund_retry.success?
refund_log[:reference] = refund_retry.transaction.id
refund_log[:message] = refund_retry.transaction.status
else
refund_log[:message] = refund_retry.message
refund_log[:params] = {}
refund_retry.errors.each do |error|
refund_log[:params][error.code] = error.message
end
order_transaction.message = refund_log[:params].values.join('|')
raise "delayed RefundJob has failed"
end
end
When I raise "delayed RefundJob has failed" in the else statement, it creates an Airbrake. I want to run the job again if it ends up in the else section.
Is there any way to re-queue the job without raising an exception? And prevent creating an airbrake?
I am using delayed_job version 1.
The cleanest way would be to re-queue, i.e. create a new job and enqueue it, and then exit the method normally.
To elaborate on #Roman's response, you can create a new job, with a retry parameter in it, and enqueue it.
If you maintain the retry parameter (increment it each time you re-enqueue a job), you can track how many retries you made, and thus avoid an endless retry loop.
DelayedJob expects a job to raise an error to requeued, by definition.
From there you can either :
Ignore your execpetion on airbrake side, see https://github.com/airbrake/airbrake#filtering so it still gets queued again without filling your logs
Dive into DelayedJob code where you can see on https://github.com/tobi/delayed_job/blob/master/lib/delayed/job.rb#L65 that a method named reschedule is available and used by run_with_lock ( https://github.com/tobi/delayed_job/blob/master/lib/delayed/job.rb#L99 ). From there you can call reschedule it manually, instead of raising your exception.
About the later solution, I advise adding some mechanism that still fill an airbrake report on the third or later try, you can still detect that something is wrong without the hassle of having your logs filled by the attempts.

Resources