I am trying to set up a schedule to run a subroutine. I am trying to use the subroutine example to send a message to a discord channel when the schedule is triggered. At first I attempted to try and just send the message but got an error. I then tried looking into how to solve this and have tried different ways using asyncio all of which have not worked.
If anyone is able to give me any pointers on how I could do this then it would be much appreciated.
import discord
import asyncio
import time
import schedule # pip install schedule
client = discord.Client()
#client.event
async def on_ready():
print("Connected!")
async def example(message):
await client.get_channel(CHANNEL ID).send(message)
client.run(SECRET KEY)
def scheduledEvent():
loop = asyncio.get_event_loop()
loop.run_until_complete(example("Test Message"))
loop.close()
schedule.every().minute.do(scheduledEvent)
while True:
schedule.run_pending()
time.sleep(1)
You can't run your blocking schedule code in the same thread as your asynchronous event loop (your current code won't even try to schedule tasks until the bot has already disconnected). Instead, you should use the built in tasks extension which allows you to schedule tasks.
import discord
from discord.ext import tasks, commands
CHANNEL_ID = 1234
TOKEN = 'abc'
client = discord.Client()
#client.event
async def on_ready():
print("Connected!")
#tasks.loop(minutes=1)
async def example():
await client.get_channel(CHANNEL_ID).send("Test Message")
#example.before_loop
async def before_example():
await client.wait_until_ready()
example.start()
clinet.run(TOKEN)
Related
In my bot made with pyrogram, I wrote a code that asks the user to answer the messages after 60 seconds with asyncio sleep, but if too many people trigger this code, my bot does not receive any command until any of these waiting processes are over, how can I solve this problem?
My code:
from pyrogram import Client, filters
from pyrogram.types import Message
import asyncio
app = Client("my_account", bot_token="", api_id=0, api_hash="")
#app.on_message(filters.command("hello"))
async def hello(_, message: Message):
await message.reply_text("Hello!")
#app.on_message(filters.text)
async def answer(_, message: Message):
await asyncio.sleep(60)
await message.reply_text("Heyy!")
app.run()
I have a cog which is ment to handel events and loops. I am using aioschedule to run ping every minute as a test if the aioschedule works. But now the problem is that when I put it inside the class it asks for self but when i give self it gives an error.pls help with this
import discord
import os
import asyncio
import time
from discord.ext import commands,tasks
import aioschedule as schedule
class Events(commands.Cog):
def __init__(self, client):
self.client = client
async def bot_test_clear(self):
channel_bot_test = self.client.get_channel(os.getenv('bot-test-text'))
messages = await channel_bot_test.history(limit=100).flatten()
if not messages:
return
embed = discord.Embed(description='It has been 1 hour, clearing chats...', color=0xff0000)
await channel_bot_test.send(embed=embed)
await asyncio.sleep(10)
await channel_bot_test.purge(limit=None)
async def ping(self):
self.client.send("pong")
schedule.every(5).seconds.do(ping)
#commands.Cog.listener()
async def on_ready(self):
self.bot_text_clear.start()
print(f'{self.client.user} is now online')
def setup(client):
client.add_cog(Events(client))
loop = asyncio.get_event_loop()
while True:
loop.run_until_complete(schedule.run_pending())
time.sleep(0.1)
img of the error
So I answered your earlier question and suggested you use aioschedule so I will show you how I use it.
def _run_scheduler(self):
""" Create the scheduler task. """
async def _run_scheduler():
self._scheduler_running = True
print("Created 'Scheduler' task")
while self._scheduler_running:
await aioschedule.run_pending()
await asyncio.sleep(0.25)
if not self._scheduler_running:
asyncio.create_task(_run_scheduler())
The above method is attached to my bot, and is called once when the bot is created. The above code will process all the jobs you schedule. I use create_task so I can call the method from a non-async method.
#commands.Cog.listener()
async def on_startup(self):
aioschedule.every().monday.at("21:15").do(self.announce_winners)
aioschedule.every().day.at("21:30").do(self.start_quiz)
I add jobs, which are then processed in that event loop in the earlier code block. I use on_startup (a custom event) which is called after on_ready since on_ready can be called multiple times if the bot disconnects (stop duplicate jobs)
Your error (which should be text, not an image) is due to schedule.every(5).seconds.do(ping) being called and it is expecting self which you do not give it.
So this is part of my code, I can provide the entire thing if needed.
Previously my bot is all well when using this pretty standard status looping (the first bit). But since I tried the second version I started to receive
socket.send() raised exception.
And now running the bot makes all async commands unusable. Despite the commands are all correctly sent, nothing returns, and even the console doesn't show any errors for some reason... Does anyone understand why including client.change_presence(...) under on_ready() doesn't seem to work and why it conflicts with any other previously working commands?
status = cycle(['Vice-Captain of The Perkers', 'At your service...', 'AHIHIP Forever', 'Hey there!']) #Status update
#tasks.loop(seconds=7.5)
async def change_status():
await client.change_presence(activity=discord.Game(next(status)))
#client.event
async def on_ready():
change_status.start()
print("#G11 - The Perkers Vice-Captain Little Green reporting.")
time.sleep(0.75)
print("What can I help with, sir?")```
import discord
import time
import datetime
import random
import math
import pytz
import dns
import os
import pymongo
from pymongo import MongoClient
from discord.ext import commands,tasks
from itertools import cycle
from discord.utils import get
from typing import List
client = commands.Bot(command_prefix='lg')
#tasks.loop(seconds=5)
async def status_change():
while True:
await client.wait_until_ready()
await client.change_presence(status=discord.Status.idle, activity=discord.Game(name='Vice-Captain of The Perkers'))
time.sleep(10)
await client.change_presence(status=discord.Status.do_not_disturb, activity=discord.Game(name='At your service...'))
time.sleep(10)
await client.change_presence(status=discord.Status.online, activity=discord.Game(name='AHIHIP Forever!'))
time.sleep(10)
#client.event
async def on_ready():
print("#G11 - The Perkers Vice-Captain Little Green reporting.")
time.sleep(0.75)
print("What can I help with, sir?")
time.sleep(3)
client.loop.create_task(status_change())
#client.command()
async def hallo(ctx):
await ctx.send('Hi!')
client.run('Token')
Main goal:
Send a message to a channel every Wednesday at 08:00
This is my current code:
import schedule
import time
import discord
import asyncio
from discord.ext import commands, tasks
from discord.ext.tasks import loop
client = discord.Client()
# IMPORTANT
channel =
botToken = ""
async def sendloop():
while True:
schedule.run_pending()
await asyncio.sleep(1)
#client.event
async def on_ready():
general_channel = client.get_channel(channel)
print('ready')
schedule.every(2).seconds.do(lambda:loop.create_task(general_channel.send('TEST')))
client.run(botToken)
So far, there are no errors, just stuck on "ready". I am a beginner using VS Code.
I wouldn't recommend using scheduler, since discord the extension task which can do the same as what you are trying to implement in your code:
from discord.ext import commands, tasks
ch = id_channel
client = commands.Bot(command_prefix='.')
TOKEN = "Token"
#every week at this time, you can change this to seconds=2
#to replicate what you have been testing
#tasks.loop(hours=168)
async def every_wednesday():
message_channel = client.get_channel(ch)
await message_channel.send("Your message")
#every_wednesday.before_loop
async def before():
await client.wait_until_ready()
every_wednesday.start()
client.run(TOKEN)
If you were to run this code on the time you want it to be repeated, it will accomplish what you want. Another approach is checking on the before() function to check if it is the right time to run if you don't want to wait and run the code on the day you want this to run.
But if you really want to use the schedule module, this post my help you: Discord.py Time Schedule
I am writing my discord bot, which has a few commands. However, recently need appeared for every command to check a list before executing. So, naturally the right move is to synchronize the commands, with something like this:
import discord
from discord.ext import commands
from time import sleep
import subprocess
import logging
import asyncio
client = commands.Bot(command_prefix='>>', case_insensitive=True)
token = 'lul'
logging.basicConfig(level=logging.INFO)
lock = None
#client.event
async def on_ready():
lock = asyncio.Lock()
print(f'Logged in as {client.user}')
#client.command()
async def test(ctx, members : commands.Greedy[discord.Member]):
await ctx.send(len(members))
await ctx.send('approaching critical section')
with await lock:
await ctx.send('in critical section')
time.sleep(10)
await ctx.send('exited critical section')
So, if you were to invoke the command with >>test #abs #asda you would expect to receive the output:
2
approaching critical section
in critical section
exited critical section
But instead what we get is this:
2
approaching critical section
So, this means that the coroutine doesn't fall into the critical section. It could be that the coroutine crashes silently or times out for being unable to acquire a lock (if that's how it works actually).
Nevertheless help on solving this problem is much appreciated.
You should use an async with statement instead of with await. You should also create the lock in the global namespace, and use asyncio.sleep instead of time.sleep.
client = commands.Bot(command_prefix='>>', case_insensitive=True)
lock = asyncio.Lock() # Doesn't require event loop
#client.command()
async def test(ctx, members : commands.Greedy[discord.Member]):
await ctx.send(len(members))
await ctx.send('approaching critical section')
async with lock:
await ctx.send('in critical section')
await asyncio.sleep(10)
await ctx.send('exited critical section')