Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to loop a task in discord.py

I am experimenting with making my own little discord bot that can get information from Twitch, but I'm stumped on how to make the bot loop and check for a condition.

I want the bot to loop a section of code every few seconds that checks if the specified twitch channel is live.


Code

import discord
from discord.ext import commands, tasks
from twitch import TwitchClient
from pprint import pformat


client = TwitchClient(client_id='<twitch token>')

bot = commands.Bot(command_prefix='$')

@bot.event
async def on_ready():
    print('We have logged in as {0.user}'.format(bot))

@bot.command()
async def info(ctx, username):
    response = await ctx.send("Querying twitch database...")
    try:
        users = client.users.translate_usernames_to_ids(username)
        for user in users:
            print(user.id)
            userid = user.id
        twitchinfo = client.users.get_by_id(userid)
        status = client.streams.get_stream_by_user(userid)
        if status == None:
            print("Not live")
            livestat = twitchinfo.display_name + "is not live"
        else:
            livestat = twitchinfo.display_name + " is " + status.stream_type
        responsemsg = pformat(twitchinfo) + "\n" + livestat
        await response.edit(content=responsemsg)
    except:
        await response.edit(content="Invalid username")

bot.run("<discord token>")

I want the bot to run the following code every 10 seconds, for example:

status = client.streams.get_stream_by_user(<channel id>)
if status == None:
     print("Not live")
     livestat = twitchinfo.display_name + "is not live"
else:
     livestat = twitchinfo.display_name + " is " + status.stream_type

I've tried using @tasks.loop(seconds=10) to try and make a custom async def repeat every 10 seconds but it didn't seem to work.

Any ideas?

like image 626
sharp312 Avatar asked May 20 '20 18:05

sharp312


People also ask

How do you make commands for discord BOT py?

Commands are defined by attaching it to a regular Python function. The command is then invoked by the user using a similar signature to the Python function. You must have access to the message_content intent for the commands extension to function. This must be set both in the developer portal and within your code.

How do you stop a loop in discord?

1 Answer. Show activity on this post. Use clearInterval() to stop a running interval. Please keep in mind that sending a message to a channel every second is every abusive to Discord's API.

What is asyncio task helpers in discord?

discord.ext.tasks – asyncio.Task helpers ¶ New in version 1.1.0. One of the most common operations when making a bot is having a loop run in the background at a specified interval. This pattern is very common but has a lot of things you need to look out for:

What is the goal of this discord extension?

The goal of this discord.py extension is to abstract all these worries away from you. A simple background task in a Cog: Adding an exception to handle during reconnect: Looping a certain amount of times before exiting: Waiting until the bot is ready before the loop starts:

What does LOOP () DO in Python?

Looping a certain amount of times before exiting: Waiting until the bot is ready before the loop starts: Doing something during cancellation: A background task helper that abstracts the loop and reconnection logic for you. The main interface to create this is through loop ().

Is there an example of playground in discord?

playground is a channel in my Discord server, and other examples work just fine. Just not this example. I can create a new issue if preferred, but commented here since it's around background task.


3 Answers

The newer version of discord.py doesn't support client.command()

To achieve the same I used the following snippet

import discord
from discord.ext import tasks
client = discord.Client()
@tasks.loop(seconds = 10) # repeat after every 10 seconds
async def myLoop():
    # work


myLoop.start()

client.run('<your token>')
like image 79
Lovesh Dongre Avatar answered Oct 24 '22 03:10

Lovesh Dongre


This can be done like so:

async def my_task(ctx, username):
    while True:
        # do something
        await asyncio.sleep(10)

@client.command()
async def info(ctx, username):
    client.loop.create_task(my_task(ctx, username))

References:

  • asyncio.create_task()
  • asyncio.sleep()
like image 6
Diggy. Avatar answered Oct 24 '22 05:10

Diggy.


This is the most proper way to implement background tasks.

from discord.ext import commands, tasks

bot = commands.Bot(...)

@bot.listen()
async def on_ready():
    task_loop.start() # important to start the loop

@tasks.loop(seconds=10)
async def task_loop():
    ... # this code will be executed every 10 seconds after the bot is ready

Check this for more info

like image 2
Exenifix Avatar answered Oct 24 '22 05:10

Exenifix