简体   繁体   中英

How to make a command to stop countdown in Python Discord Bot?

I would like to make this stoppable, by that I mean that a separate command (~cdstop) would cancel the countdown.

import discord
import asyncio

counter_channel = None

async def ex(args, message, client, invoke):

  global counter_channel
  if counter_channel is not None:
    await client.send_message(message.channel, embed=discord.Embed(color=discord.Color.red(), "There is a counter in {}".format(counter_channel.mention)))
    return

  counter_channel = message.channel

  await client.send_message(message.channel, "5 Minutes")
  await asyncio.sleep(60)
  await client.send_message(message.channel, "4 Minutes")
  await asyncio.sleep(60)
  await client.send_message(message.channel, "3 Minutes")
  await asyncio.sleep(60)
  await client.send_message(message.channel, "2 Minutes")
  await asyncio.sleep(60)
  await client.send_message(message.channel, "1 Minutes")
  await asyncio.sleep(30)
  await client.send_message(message.channel, "30 Seconds")
  await asyncio.sleep(15)
  await client.send_message(message.channel, "15 Seconds")
  await asyncio.sleep(10)
  await client.send_message(message.channel, "5 Seconds")

  counter_channel = None

My idea for it is that after every print statement it would check if a user has typed ~cdstop and then break from the function. I think it would work but I don't know if it would be efficient as I know it would mess with the check for double countdown.

Edit

Code that calls the file:

import discord
from discord import Game, Embed

import SECRETS
import STATICS
from commands import cmd_ping, cmd_clear, cmd_help, cmd_userinfo, cmd_cdstart

client = discord.Client()


commands = {

    "ping": cmd_ping,
    "clear": cmd_clear,
    "help": cmd_help,
    "userinfo": cmd_userinfo,
    "cdstart": cmd_cdstart,

}


@client.event
async def on_ready():
    print("Bot is logged in successfully. Running on servers:\n")
    [(lambda s: print("  - %s (%s)" % (s.name, s.id)))(s) for s in client.servers]
    await client.change_presence(game=Game(name="~help"))


@client.event
async def on_message(message):
    if message.content.startswith(STATICS.PREFIX):
        invoke = message.content[len(STATICS.PREFIX):].split(" ")[0]
        args = message.content.split(" ")[1:]
        if commands.__contains__(invoke):
            await commands.get(invoke).ex(args, message, client, invoke)
        else:
            await client.send_message(message.channel, embed=Embed(color=discord.Color.red(), description=("The command `%s` is not valid!" % invoke)))

client.run(SECRETS.TOKEN)

Here's a solution that uses AbstractEventLoop.create_task to create a Task object that you can then Task.cancel at any time.

bot = commands.Bot(command_prefix="!")
counter_channel = None
task = None

async def ex(message):

    global counter_channel
    if counter_channel is not None:
        await bot.send_message(
            message.channel,
            embed=discord.Embed("There is a counter in {}".format(counter_channel.mention), color=discord.Color.red() ))
        return

    counter_channel = message.channel
    # reduced waits for easy testing
    await bot.send_message(message.channel, "5 Minutes")
    await asyncio.sleep(5)
    await bot.send_message(message.channel, "4 Minutes")
    await asyncio.sleep(5)
    await bot.send_message(message.channel, "3 Minutes")
    await asyncio.sleep(5)
    await bot.send_message(message.channel, "2 Minutes")
    await asyncio.sleep(5)
    counter_channel = None

@bot.command(pass_context=True)
async def timer(ctx):
    global task
    task = bot.loop.create_task(ex(ctx.message))

@bot.command(pass_context=True)
async def cancel(ctx):
    global task, counter_channel
    task.cancel()
    task = None
    counter_channel = None

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM