Respond to user and continue to run async functions - aiohttp

I want to respond to user as soon as I received the request, then continue to save data to database
async def index(request):
data = await request.post()
response.write("done")
async with request.app.mysqlpool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute("INSERT INTO ...")
If I try to wrap the part after request.write to separate function and than call it with run_in_executor - it doesn't allow awaitable functions inside (TypeError: coroutines cannot be used with run_in_executor())
Is there a way to do it in aiohttp?

Push await response.drain() just after response.write(...) call.
It doesn't exactly guarantee that data are sent through the wire but it's the closest solution.

Related

I want to send a list of users who reacted to my message but the list always shows empty

I searched it up and saw someone do it like this but it always returns an empty list
#bot.command()
async def spinthewheel(ctx,msg:discord.Message=None):
guild=ctx.guild
if msg==None:
em=discord.Embed(title="SPIN THE WHEEL!!", description="React to this message with ⚡ to enter!",color=discord.Color.from_str('#ff00ff'))
msg=await ctx.send(embed=em)
await msg.add_reaction('⚡')
else:
await msg.add_reaction('⚡')
await ctx.send("Reaction has been added",delete_after=10)
await asyncio.sleep(5)
users = list()
for reaction in msg.reactions:
if reaction.emoji == '⚡':
async for user in reaction.users():
if user != bot.user:
users.append(user.name)
user_list="\n".join(user.name for user in users)
await ctx.send(f"users: {user_list}")
I tried using this one too but same results
users = [user async for user in reaction.users()]
Can you pls tell me how to fix this? Thanks <3
The issue is that msg.reactions is empty - this is because it's the message representation at the time it was created and hasn't been updated since with the reaction information. This is easily fixable with a:
msg = await msg.fetch()
This will fetch the message anew from the channel. Just put it after your asyncio.sleep and before you loop over the reactions.

How I can edit followUp message (discord.py)?

I have this code, however I don't understand how it is possible to edit the followup message. Thanks!
#bot.command()
async def button(ctx):
view=View()
button_create = Button(label="CREATE", style=discord.ButtonStyle.green)
view.add_item(button_create)
await ctx.send(view=view)
async def button_callback(interaction):
await interaction.response.defer()
await asyncio.sleep(delay=1)
await interaction.followup.send("Hi", ephemeral=True) # How can i edit this message? -_-
button_create.callback = button_callback
I tried to use "interaction.followup.edit_message("Something")", but i got error:
discord.errors.HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body
In message_id: Value "Something" is not snowflake.
followup.send() returns the WebhookMessage object that it sent if you set the wait kwarg to True, so you can store it in a variable and call .edit() on it.
From the send docs:
wait (bool) – Whether the server should wait before sending a response. This essentially means that the return type of this function changes from None to a WebhookMessage if set to True.

Toggling a server limited command

#f spam
async def on_message(message):
if message.author.bot:
return
elif message.content.lower() == 'f':
await message.channel.send('f')
await bot.process_commands(message)
this is my current code for an f spam or sends an f each time a user does.
I was wanting to make this command toggleable and also server/guild limited if possible.
for example someone says !fspam and it gets toggled and switched off and when done the same again it gets turned on. OR it could be !fspam on/ !fspam off
You can use Command.enable, where you can use command.update to. This will raise the DisabledCommand error.
Also please dont just copy and paste the code, try understanding what I did.This will disable it for all the guilds to. If you want it per server then you will need to use a database.
For example:
#client.command()
async def enable(ctx,*,command):
command = client.get_command(command)
command.update(enabled=True)
await ctx.send(f"{command} enabled!")
#client.command()
async def disable(ctx,*,command):
command = client.get_command(command)
command.update(enabled=False)
await ctx.send(f"{command} disabled!")

how to add reaction to a specifc user?

I've been working on this piece of code:
#client.event
async def lol(message,ctx):
if ctx.author.id == <user_id>:
await message.add_reaction('❤️')
else:
return
I am pretty sure that it is developed correctly, yet I am not getting the desired results.
I am pretty sure that if you check the console, an HTTP error would have been encountered. That's because you directly pasted the emoji in the function parameter. You have to add its unicode value. In your case:
await message.add_reaction(u'\u2764')
You are using an event decorator rather than a command, unless you were trying to detect if the user reacted, but its still completely off. What it looks like, the command that is called will send a message and the bot will react to it.
#client.command()
async def lol(ctx):
message = await ctx.send(f"{ctx.author.mention}, lol")
await message.add_reaction('😂')
If you then want to detect if the user had reacted to the emoji, you can use a event, but an on_reaction_add:
#client.event
async def on_reaction_add(reaction, user):
if reaction.emoji == '😂':
await user.send("Lol")

Wait for Message on_member_join using checks (discord.py) | SOLVED

I want to wait for a private message that was sent only by the member. I am trying to use the check parameter for the client.wait_for() method but I can not seem to get it. I tried putting the check as the response.author but will not work since I just assigned response. Also I am executing this when a member joins using on_member_join which takes in a member argument (like this async def on_member_join(member). Anyone know how to properly do this? Any answers would be greatly appreciated!
Here is the code for this:
await member.send('What is your student number? ')
response = await client.wait_for('message')
student_number = response.content
When adding a check function to wait_for, that check function will get the received message as an argument. This means that it will check every single message the bot gets, pass all of them to your check function, and wait until one of them makes the check return True.
#client.event()
async def on_member_join(member):
def check(message):
return message.author.id == member.id and message.guild is None
await member.send('What is your student number?')
response = await client.wait_for('message', check=check)
student_number = response.content
Note how my example also makes sure the guild is None, as you explicitly mentioned waiting for a private message.

Resources