Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

discord - Python shedule does not perform a function

My shedule script does not perform a function. I do everything as it should be, and the function does not call, so do not unmute and not print lol. When I put it instead of the print function, it was executed. I don't know what I'm doing wrong.

def unmutetempmute(ctx, member: discord.Member):
    print('lol')
    role = discord.utils.get(ctx.guild.roles, name='Wyciszony/a')
    if role in member.roles:
        unmuteembed = discord.Embed(
            title='Odciszono {}!'.format(member.name),
            color=28159,
            description='Czas wyciszenia si? skończy?.')

        ctx.channel.send(embed=unmuteembed)
        member.send(embed=unmuteembed)
        member.remove_roles(role)
        return schedule.CancelJob

@client.command()
@commands.has_permissions(kick_members=True)
async def tempmute(ctx,
                   member: discord.Member,
                   time: int,
                   *,
                   reason='Nie podano powodu'):
    role = discord.utils.get(ctx.guild.roles, name='Wyciszony/a')

    if not role in member.roles:
        muteembed = discord.Embed(
            title='Wyciszono {}!'.format(member.name), color=28159)

        muteembed.add_field(name='Powód:', value=reason, inline=False)
        muteembed.add_field(
            name='Czas:', value='{}m'.format(time), inline=False)
        muteembed.add_field(
            name='Administrator:', value=ctx.author.mention, inline=False)

        await ctx.channel.send(embed=muteembed)
        await member.send(embed=muteembed)

        await member.add_roles(role)
        await ctx.message.delete()

        await schedule.every(time).seconds.do(
            unmutetempmute, ctx=ctx, member=member)
        return

    errorembed = discord.Embed(
        title='B??d!',
        color=16711686,
        description='U?ytkownik ju? jest wyciszony!')

    await ctx.channel.send(embed=errorembed)
    await ctx.message.delete()

question from:https://stackoverflow.com/questions/65887940/python-shedule-does-not-perform-a-function

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You probably don't want to use schedule here, as it's not built with asyncio in mind, whereas discord.py is built on it. You could force it to work like in this question, but those solutions are pretty cumbersome since they try to work around the fact that schedule wasn't designed to be used with asyncio.

Instead, since this is a one-off delayed task, you can simply leverage basic asyncio:

import asyncio


async def delayed_coro(seconds: int, coro):
    # Delays execution of the given coroutine by `seconds`
    try:
        await asyncio.sleep(seconds)
        await coro
    except asyncio.CancelledError:
        coro.close()


# FIXED: This needs to be a coroutine!
async def unmutetempmute(ctx, member: discord.Member):
    print('lol')
    role = discord.utils.get(ctx.guild.roles, name='Wyciszony/a')
    if role in member.roles:
        unmuteembed = discord.Embed(
            title='Odciszono {}!'.format(member.name),
            color=28159,
            description='Czas wyciszenia si? skończy?.')

        await ctx.channel.send(embed=unmuteembed)
        await member.send(embed=unmuteembed)
        await member.remove_roles(role)


@client.command()
@commands.has_permissions(kick_members=True)
async def tempmute(ctx,
                   member: discord.Member,
                   time: int,
                   *,
                   reason='Nie podano powodu'):
    role = discord.utils.get(ctx.guild.roles, name='Wyciszony/a')
    if not role in member.roles:
        # create and send your embed
        # add muted role to user, etc.
        
        # You can also save the task returned by `create_task` if you want.
        await ctx.bot.loop.create_task(
            delay_coro(time, unmutetempmute(ctx, member)))
        return

    # errorembed stuff

Step by Step

First, we create a small wrapper coroutine delay_coro that takes a number of seconds to wait before awaiting the given coroutine coro:

async def delayed_coro(seconds: int, coro):
    # Delays execution of the given coroutine by `seconds`
    try:
        await asyncio.sleep(seconds)
        await coro
    except asyncio.CancelledError:
        coro.close()

Then, in tempmute, instead of using schedule.every(time).seconds, we create a new task on the bot's event loop with ctx.bot.loop.create_task, passing in unmutetempmute wrapped within delay_coro:

await ctx.bot.loop.create_task(
    delay_coro(time, unmutetempmute(ctx, member)))

Lastly, you forgot to make your unmutetempmute a coroutine and await the appropriate discord library calls, so I fixed that in the full example. Be sure to include those changes or it will not run.


A Little Extra

If at some point you find that you need to schedule something to run more than once, I recommend the tasks extension that comes with discord.py; it provides helpers specifically for scheduling tasks in a loop when using discord.py.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...