You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 05:24:08