1

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()

MombotTv
  • 61
  • 1
  • 2

2 Answers2

0

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.

ZeroKnight
  • 518
  • 3
  • 17
-1

You need to let the schedule run as well.

#  await schedule.every(time)...
schedule.run_pending()
stijndcl
  • 5,294
  • 1
  • 9
  • 23