Is it possible to send messages outside a function? - python

I'm writing a discord.py script and I wanted to make alerts for my original code but I'm not sure how to write it properly:
#client.event
async def on_ready():
print('Client is ready.')
channel = client.get_channel(00000000000000)
await channel.send(f'example')
this works fine but when I write this outside it doesn't want to work. Is there any way writing this section?
channel = client.get_channel(000000000000000)
await channel.send(f'message')

Everything has to be async so it has to be in a function
async def sendmsg():
channel = client.get_channel(000000000000000)
await channel.send(f'message')
Then you can do await sendmsg() in the on_ready or another async function.

The code outside the functions is getting called when you start the file. So as the bot isn't ready there, you can't say it to get a channel and send a message to it.
So you have to put the channel = ... await channel.send in another function, you call when a specific thing happens.
Also as FluxedScript said, you have to put it into an async function, because it has an await in it and then you have to call it with await FUNCTION_NAME.

Related

Discord.py: How to send a message without using async and await

How can I create a function (without async) that sends a message to a specific channel every time it (the function) gets executed somewhere in the code?
def sendMsg():
channel = client.getChannel(Channel id)
message.channel.send("example message")
#excecuting the function
sendMsg()
Doesn't do anything
async def on_message():
await message.channel.send("example message")
Only this one works
So my question is if I can modify the code on the top make it work?
If you need to send the message outside of an async context, you need to add the task into the event loop. Note that when you "call" a coroutine, you get the actual coroutine object. "Calling" it doesn't actually run the coroutine, you need to put it in the event loop for it to run.
asyncio.get_event_loop().create_task(<coro>)
# use it like this
asyncio.get_event_loop().create_task(ctx.send('test'))
asyncio.get_event_loop().create_task(message.channel.send("example message"))
Eric's answer is correct. Moreover, in order to get the loop event from discord.py, you can use client.loop to get discord.py's asyncio eventloop
that said, use asyncio.run_coroutine_threadsafe(def,loop) to safely submit task to event_loop
client = discord.Client()
async def send_message_to_specific_channel(message='abc',id=123):
channel = client.get_channel(id)
await channel.send(message)
asyncio.run_coroutine_threadsafe(send_message_to_specific_channel('abc',123),client.loop)
Async is really needed for synchronize the message
If your wanna make it as selfbot response message, do
# Import's here
from discord.ext import commands
bot = commands.Bot(command_prefix='!', help_command=None, self_bot=True)
#bot.event
async def on_message(message):
if message.content.startswith("Hello"):
await message.channel.send(f"Hi #{message.author}")
bot.run('token ofc', bot=False)
Anyways this for selfbot if you wanna do it with bots, delete self_bot=True and bot=False

Discord.py - await allowed only within async function python

With the next code:
intents = discord.Intents.all()
bot = commands.Bot(command_prefix='!!')
online=####
#tasks.loop(seconds=1)
async def thatloop():
def sendmsg():
channel = bot.get_channel(online)
await channel.send("Hi")
sendmsg()
#bot.event
async def on_ready():
print("Comienza el scrap.")
try:
thatloop.start()
except RuntimeError:
pass
bot.run('####')
I'm trying to message a discord channel from a function to understand how to fix a bigger issue.
What I'm really looking for is to send a embed from a predefined function INSIDE the loop function (The simplest simile is the code above).
The error is in the title.
I have read everything on this site, but maybe my poor understanding of English is working against me.
I tried to put the function outside the loop but the error persists.

how to make an event stop overlapping a command

I've had this problem for a while, trying to use both commands and events in one file.
I know that there's a function called process_commands(), but the bot doesn't seem to have this function. Is there anything I need to import though? (else than discord.ext and commands)
picture of code: https://i.stack.imgur.com/Gdvj8.png
you should add await client.process_commands(message) on top of the on_message event
#client.event
async def on_message(message):
await client.process_commands(message)
# do other stuff
also message.send('...') in your command doesnt work, it must be awaited since its a coroutine. (Docs)
#client.command()
async def test(ctx): # ctx instead of message
await ctx.send("test")

How to run async function as a thread in discord.py?

I have a counting functions that sends a number every second to a text channel (it's in a while-true loop), while this is happening I want the bot to do other things as well such as answering commands in a different channel but it is stuck in that while-true loop.
I've tried using a call-back function but that didn't let me send any messages..
This is my full code:
#bot.event
async def on_ready():
text_channel = bot.get_channel(xxxxxxxxxxx)
await count_in_server(text_channel)
#bot.command()
async def ping(ctx):
await ctx.send('pong')
#bot.event
async def count_in_server(chat):
count = 0
while True:
await chat.send(count)
await asyncio.sleep(1)
count += 1
My question more specfic is how do you run count_in_server() as a thread? (please provide code example)
EDIT:
Thanks to AKX I changed asyncio.sleep(1) to await asyncio.sleep(1) and now between each second it lets the other script run, but I'm looking for another way to do this.
await count_in_server(text_channel)
replace the line above with:
asyncio.create_task(count_in_server(text_channel))
And you should be ok.
Tasks are scheduled to run in parallel. "awaited" coroutines block the code where the "await" keyword is until the target resolves.

clear all messages in certain channel on_load

When I'm playing with my bot I do everything in a "bottesting" channel only I have access to, I'm trying to figure out how to get the bot on load to purge or delete all the messages currently in that certain channel
I've tried to make the bot.say(!clear) its own command to clear the channel but it won't recognize its output, I currently have to manually do the clear command I have set up for others to use
#bot.event
async def on_ready():
#bot announces to me when its online and posts in bottesting channel
await bot.send_message(discord.Object(id=bottesting), 'Im Back ' + myid)
print('<',datetime.datetime.now(),'>',NaMe," Launched")
This is what my current on_ready looks like and as of now it just posts that it is online and tags me in the post and the channel as well as outputs to cmd with print.
Here's one way you could turn clear into a seperate coroutine that can be called from both places:
#bot.command(pass_context=True)
#has_permissions(administrator=True, manage_messages=True, manage_roles=True)
async def clear(ctx, amount: int=1):
await _clear(ctx.message.channel, amount) # Technically you could apply the decorators directly
# to the _clear callback, but that's a little complicated
async def _clear(channel, amount=1):
messages = []
async for message in bot.logs_from(channel, limit=amount+1):
messages.append(message)
await bot.delete_messages(messages)
#bot.event
async def on_ready():
channel = bot.get_channel("123")
await _clear(channel, 100)

Categories

Resources