如何在discord.py v2中通过数据库限制/apply指令仅单次使用?
限制discord.py v2中/apply指令重复提交的实现方案
核心思路
用Python自带的SQLite轻量数据库记录已提交申请的用户ID,触发/apply指令时先查询数据库:若用户已提交过申请则阻止弹出模态框,否则正常展示表单;用户提交表单成功后,将其ID存入数据库。
具体实现步骤
1. 初始化数据库
先写初始化函数,创建存储用户提交记录的表:
import sqlite3 from datetime import datetime import discord from discord import app_commands, Interaction, ui def init_db(): conn = sqlite3.connect('applications.db') c = conn.cursor() # 用user_id作为主键,确保每个用户只能有一条记录 c.execute('''CREATE TABLE IF NOT EXISTS applications (user_id INTEGER PRIMARY KEY, submitted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''') conn.commit() conn.close()
2. 修改/apply指令逻辑
在指令触发时先检查数据库,判断用户是否已提交过申请:
@app_commands.command(name="apply", description="提交你的申请") async def apply(interaction: Interaction): # 连接数据库查询用户记录 conn = sqlite3.connect('applications.db') c = conn.cursor() c.execute("SELECT user_id FROM applications WHERE user_id = ?", (interaction.user.id,)) existing_record = c.fetchone() conn.close() # 若已提交过,直接回复阻止操作 if existing_record: await interaction.response.send_message("你已经提交过申请,无法重复提交!", ephemeral=True) return # 未提交过则弹出模态框 class ApplyModal(ui.Modal, title="申请表单"): # 自定义你的模态框字段,示例如下 game_id = ui.TextInput(label="游戏ID", placeholder="输入你的游戏ID", required=True) apply_reason = ui.TextInput(label="申请理由", placeholder="说明你想要加入的原因", style=discord.TextStyle.paragraph, required=True) async def on_submit(self, interaction: Interaction): # 这里可以添加表单内容的后续处理,比如发送到审核频道 await interaction.response.send_message("申请提交成功,等待审核!", ephemeral=True) # 提交成功后,将用户ID存入数据库 conn = sqlite3.connect('applications.db') c = conn.cursor() c.execute("INSERT INTO applications (user_id) VALUES (?)", (interaction.user.id,)) conn.commit() conn.close() await interaction.response.send_modal(ApplyModal())
3. 启动Bot时初始化数据库
在Bot启动的钩子函数中调用初始化函数,确保表存在:
class MyBot(discord.Client): def __init__(self, *, intents: discord.Intents): super().__init__(intents=intents) self.tree = app_commands.CommandTree(self) async def setup_hook(self): await self.tree.sync() init_db() # 启动时初始化数据库 # 配置Bot权限并启动 intents = discord.Intents.default() intents.message_content = True bot = MyBot(intents=intents) # 替换成你的Bot Token bot.run("YOUR_BOT_TOKEN")
扩展:允许用户定期重新提交
如果需要让用户在一段时间后(比如24小时)可再次提交,修改表结构添加过期时间字段,并调整检查逻辑:
# 修改init_db中的表结构 c.execute('''CREATE TABLE IF NOT EXISTS applications (user_id INTEGER PRIMARY KEY, submitted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expire_at TIMESTAMP DEFAULT DATETIME(CURRENT_TIMESTAMP, '+1 day'))''') # 修改指令中的检查逻辑 c.execute("SELECT expire_at FROM applications WHERE user_id = ?", (interaction.user.id,)) result = c.fetchone() if result: expire_time = datetime.fromisoformat(result[0]) if datetime.now() < expire_time: remaining_hours = int((expire_time - datetime.now()).total_seconds() // 3600) await interaction.response.send_message(f"你已提交过申请,请在{remaining_hours}小时后再尝试!", ephemeral=True) return else: # 记录已过期,删除旧记录允许重新提交 c.execute("DELETE FROM applications WHERE user_id = ?", (interaction.user.id,)) conn.commit()
内容的提问来源于stack exchange,提问作者gab
相关产品推荐
相关产品推荐

