LukeBenVader1
LukeBenVader1

Reputation: 103

discord.py - Assistance with Count-Down Command

I'm trying to create a marriage command for a Discord Bot (don't ask me why) and I can't figure out how to get it to countdown 30 seconds to receive input from a mentioned person. A generalization of what I want:

A user types !marriage in the chat and mentions a person they wish to "marry".

The command is no longer usable by anyone else until the initiated 30 second timer finishes.

The mentioned person must either type "y" or "n" to accept the proposal or deny it within the 30 second countdown.

If the mentioned person does either of these the countdown will stop, a message appears, and the command is usable once more.

If the mentioned person fails to answer within those 30 seconds, a message appears and the command is usable.

I've already tackled most of this, but I'm still kind of new to Python and I simply can't get this to work, and I feel the code I have written is tedious and sloppy. Here it is:

import discord
from discord.ext.commands import Bot
from discord.ext import commands
import asyncio
import time

Client = discord.Client()
client = commands.Bot(command_prefix="!")

@client.event
async def on_message(message):
    author = message.author.mention
    user_mentioned = message.mentions

    if message.content == '!marriage':
        await client.send_message(message.channel, author + " you must tag another user!")

    if message.content.startswith('!marriage '):
        if message.channel.name == "restricted-area":
            if len(user_mentioned) == 1:
                if message.mentions[0].mention == author:
                    await client.send_message(message.channel, author + " you cannot tag yourself!")
                else:
                    # if time_up + 30.0 <= time.time() or marriage_active == 1:
                    global marriage_active
                    marriage_active = 1
                    if marriage_active == 1:
                        global marriage_mention
                        global marriage_author
                        marriage_mention = message.mentions[0].id[:]
                        marriage_author = message.author.id[:]
                        msg = await client.send_message(message.channel, author + " has asked for " + message.mentions[0].mention + "'s hand in marriage!")
                        time.sleep(0.3)
                        await client.edit_message(msg, author + " has asked for " + message.mentions[0].mention + "'s hand in marriage!\n" + message.mentions[0].mention + " if you wish to either accept or deny the request, simply type 'y' for yes or 'n' for no!")
                        time.sleep(0.3)
                        await client.edit_message(msg, author + " has asked for " + message.mentions[0].mention + "'s hand in marriage!\n" + message.mentions[0].mention + " if you wish to either accept or deny the request, simply type 'y' for yes or 'n' for no!\n You have 30 seconds to reply...")

                        marriage_active = 0
                        global time_up
                        time_up = time.time()

                    else:
                        await client.send_message(message.channel, author + " please wait until the current request is finished!")
        else:
            await client.send_message(message.channel, author + " this command is currently in the works!")

    if message.content == "y":
        if message.author.id == marriage_author and marriage_active == 0:
            if time_up + 30.0 > time.time():
                await client.send_message(message.channel, author + " said yes! :heart:")
                marriage_active = 1
            else:
                marriage_active = 1
    if message.content == "n":
        if message.author.id == marriage_author and marriage_active == 0:
            if time_up + 30.0 > time.time():
                await client.send_message(message.channel, author + " denied <@" + marriage_author + ">'s proposal. :cry:")
                marriage_active = 1
            else:
                marriage_active = 1

I can't use a while loop in the !marriage command because it'll never leave the command until the 30 seconds are up, and I can't put the "y" or "n" commands in !marriage either because they won't be picked up by the mentioned person, only the author who originally initiated the command.

If there's a much better way to do this or a simple fix to my problem, any help is greatly appreciated! :-)

Upvotes: 0

Views: 2187

Answers (1)

Patrick Haugh
Patrick Haugh

Reputation: 60954

We can clean this up a lot by using the commands extension. We'll use wait_for_message to wait for the message

from discord.ext import commands
import discord

bot = commands.Bot(command_prefix='!')  # Use Bot instead of Client

@bot.event
async def on_message(message):
    await bot.process_commands(message)  # You need this line if you have an on_message

bot.marriage_active = False
@bot.command(pass_context=True)
async def marriage(ctx, member: discord.Member):
    if bot.marriage_active:
        return  # Do nothing
    bot.marriage_active = True
    await bot.say("{} wanna get hitched?".format(member.mention))
    reply = await bot.wait_for_message(author=member, channel=ctx.message.channel, timeout=30)
    if not reply or reply.content.lower() not in ("y", "yes", "yeah"):
        await bot.say("Too bad")
    else:
        await bot.say("Mazel Tov!")
    bot.marriage_active = False

bot.run("Token")

You may have to replace bot.marriage_active with a global variable instead.

To only accept y or n, we would include a check in wait_for_message that looks for that content

    def check(message):
       return message.content in ('y', 'n')

    reply = await bot.wait_for_message(author=member, channel=ctx.message.channel, 
                                       timeout=30, check=check)
    if not reply or reply.content == 'n':
        await bot.say("Too bad")
    else:
        await bot.say("Mazel Tov!")

Upvotes: 1

Related Questions