0

I'm trying to make a discord bot with a remind command. I would like the remind command to be able to do like ;remind 12.5m or ;remind 1h 12m 30s. but right now the remind command can only be used like ;remind 45m, ;remind 2h, ;remind 9m. basically the command only works if only one time is included. I'm not sure how to make the command work with multiple time included, can someone help me?

@client.command(case_insensitive=True, aliases=["reminder", "rm"])
async def remind(ctx, time, *, reminder="something"):
    user = ctx.author.mention
    channel = client.get_channel(12345678912345)
    seconds = 0
    log = discord.Embed(color=0xe9a9a9, timestamp=datetime.utcnow())
    embed = discord.Embed(color=0xe9a9a9)
    if time.lower().endswith("d"):
      seconds += int(time[:-1]) * 60 * 60 * 24
      counter = f"{seconds // 60 // 60 // 24} days"
    if time.lower().endswith("h"):
      seconds += int(time[:-1]) * 60 * 60
      counter = f"{seconds // 60 // 60} hours"
    if time.lower().endswith("m"):
      seconds += int(time[:-1]) * 60
      counter = f"{seconds // 60} minutes"
    if time.lower().endswith("s"):
      seconds += int(time[:-1])
      counter = f"{seconds} seconds"
    if seconds == 0 or seconds > 7776000:
      await ctx.send("Please specify a valid time.")
    if reminder is None:
      await ctx.send("Please tell me what to remind you.")
    else:
      log.set_author(name=f"{ctx.author.display_name}#{ctx.author.discriminator} - Remind", icon_url=ctx.author.avatar_url)
      log.set_footer(text=f"{counter} | {reminder}")
      embed.add_field(
          name="**Reminder**",
          value=f"{user}, you asked me to remind you to `{reminder}` `{counter}` ago."
        )
      await ctx.send(f"Alright, I will remind you about `{reminder}` in `{counter}`.")
      await asyncio.sleep(seconds)
      await ctx.author.send(embed=embed)
      await channel.send(embed=log)
      return
yujin
  • 45
  • 6

2 Answers2

2

When you do

remind(ctx, time, *, reminder='something')

The * bit is saying that when you call that function any parameters after that point have to be a named ones.

Instead if put the * in front of time then you are triggering a completely different behavior, and time will become a list of all of the different times given to you. Like so.

async def remind(ctx, *times, reminder="something"):
    for time in times:
        # move the code here
        # Getting rid of the return statement at the end

However it will run each timer sequentially, waiting to count down the second one until the first one is finished. If you want to start all of the timers at once, since we're already using asyncio, there is a way we can easily accomplish this with asyncio.gather.

async def remind(ctx, *times, reminder="something"):
    asyncio.gather(*[_remind(ctx, time, reminder) for time in times])

async def _remind(ctx, time, reminder):
    # All of the code that was in your original remind runction
    # would go here instead

Bytheway, once again the star (the one in async.gather) is acting in a different way.

hostingutilities.com
  • 8,894
  • 3
  • 41
  • 51
0

Looks like you are using * for the reminder, meaning all provided times after the first one will be stored in your reminder variable. You can search the reminder variable for and valid times at the very start of the string.

Anthony D
  • 36
  • 4