如何在Discord.py机器人的私信(DM)中获取用户回复以收集邮箱?
Hey there! Let's work through this problem step by step—you're closer than you think to getting this sorted.
First, Fix the Contradiction in Your Current Code
I noticed you added no_pm=True to your !key command, which blocks users from running the command in DMs, but then you try to check if the command was sent in a DM. That’s why your DM logic isn’t working as expected—first, remove the no_pm=True parameter from your command decorator.
How to Listen for User Replies in DMs
Discord.py has a built-in wait_for() method that lets your bot pause and wait for a specific user’s message response. This is perfect for collecting the user’s email after you send the initial prompt.
Also, note that client.get_user_info() was removed in Discord.py v1.0+. Instead, you can use bot.fetch_user(user_id) (an async method requiring await) if you need to retrieve a user by ID, but in your case, you already have access to the user via ctx.author, so you won’t need that here.
Updated Working Code
Here’s a revised version of your code with proper DM reply handling, plus fixes for common pitfalls:
import discord from discord.ext import commands import datetime import asyncio # Initialize key array (example data) keyArray = ["ABC123-XYZ789", "DEF456-GHI012"] # Enable required intents (critical for message access in Discord.py v2.x+) intents = discord.Intents.default() intents.message_content = True bot = commands.Bot(command_prefix='!', intents=intents) @bot.command(name='key', help="I give you a key—just share your valid email first!") async def key_giver(ctx): command_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(f"!key command triggered at {command_time} by {ctx.author}") # Define a check to filter only the correct user's DM replies def dm_reply_check(message): return message.author == ctx.author and isinstance(message.channel, discord.DMChannel) # If command is run in a server, redirect to DM if not isinstance(ctx.channel, discord.DMChannel): await ctx.send("I've sent you a DM to collect your email!") initial_prompt = "Hello friend! To get your game key, please share your valid email address." await ctx.author.send(initial_prompt) # If command is run directly in DM else: initial_prompt = "Hello friend! To get your game key, please share your valid email address." await ctx.send(initial_prompt) try: # Wait 60 seconds for the user to reply in DM email_message = await bot.wait_for('message', check=dm_reply_check, timeout=60.0) user_email = email_message.content.strip() # Optional: Add email validation logic here (e.g., regex to check format) # For example: # import re # if not re.match(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", user_email): # await ctx.author.send("That doesn't look like a valid email. Please try again!") # return # If valid, send the key and remove it from the array if keyArray: await ctx.author.send(f"Thanks for your email! Here's your game key: {keyArray[0]}") keyArray.pop(0) else: await ctx.author.send("Sorry, we're out of keys right now!") except asyncio.TimeoutError: await ctx.author.send("Whoops, you took too long to respond. Run the `!key` command again when you're ready!") # Run the bot (replace with your token) bot.run("YOUR_BOT_TOKEN_HERE")
Key Details Explained
- Intents: The
message_contentintent is required in Discord.py v2.x+ to read message content—without it, your bot won’t see the user’s email reply. wait_for(): This method listens for themessageevent, uses thedm_reply_checkfunction to ensure only the original user’s DM replies are processed, and times out after 60 seconds (adjustable).- Key Management: We pop the first key from
keyArrayafter sending it to avoid duplicate key issues.
内容的提问来源于stack exchange,提问作者AON




