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

Python实现Discord私信工单系统求助:emoji交互及功能完善

修复并完善Discord DM工单系统

原代码的核心问题

  • await bot.add_reaction(emoji="1️⃣" and "2️⃣", message=message) 写法错误,add_reaction一次只能添加一个表情,需分开调用
  • 直接在on_message里判断用户表情点击无效,用户的表情交互需要通过on_raw_reaction_add事件监听
  • 逻辑顺序错误,应该先发送Embed消息,再给这条消息添加表情

完整实现代码

import discord
import random
import string
from discord.ext import commands

# 替换为你的机器人前缀和TOKEN
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
# 替换为接收工单的服务器频道ID
TICKET_CHANNEL_ID = 123456789012345678
# 存储工单映射:{工单代码: 用户ID}
ticket_map = {}

@bot.event
async def on_ready():
    print(f"Logged in as {bot.user}")

@bot.event
async def on_message(message):
    # 忽略机器人自身消息
    if message.author.bot:
        return
    
    # 用户@机器人时,发送工单选择Embed
    if bot.user.mentioned_in(message):
        embedP = discord.Embed(
            title="Benvenuto nel ticket!",
            description="""Come possiamo aiutarti?
                          
                          1️⃣ Reportare una persona
                          2️⃣ Domanda ad un admin""",
            colour=discord.Colour.red()
        )
        # 发送Embed并保存消息对象
        ticket_msg = await message.channel.send(embed=embedP)
        # 分别添加两个交互表情
        await ticket_msg.add_reaction("1️⃣")
        await ticket_msg.add_reaction("2️⃣")
    
    # 处理管理员回复:格式为 @机器人 [工单代码] 回复内容
    if bot.user.mentioned_in(message) and message.guild:
        if message.channel.id == TICKET_CHANNEL_ID:
            content_parts = message.content.split(maxsplit=2)
            if len(content_parts) >=3 and content_parts[1].startswith("[") and content_parts[1].endswith("]"):
                ticket_code = content_parts[1][1:-1]
                if ticket_code in ticket_map:
                    user_id = ticket_map[ticket_code]
                    user = await bot.fetch_user(user_id)
                    reply_embed = discord.Embed(
                        title="Risposta dal team admin",
                        description=content_parts[2],
                        colour=discord.Colour.green()
                    )
                    reply_embed.set_footer(text=f"Codice ticket: [{ticket_code}]")
                    await user.send(embed=reply_embed)
                    await message.reply(f"Risposta inviata al codice ticket {ticket_code}")
                else:
                    await message.reply("Codice ticket non valido!")
    
    await bot.process_commands(message)

@bot.event
async def on_raw_reaction_add(payload):
    # 忽略机器人自身的表情操作
    if payload.user_id == bot.user.id:
        return
    
    # 获取消息和用户对象
    channel = await bot.fetch_channel(payload.channel_id)
    message = await channel.fetch_message(payload.message_id)
    user = await bot.fetch_user(payload.user_id)
    
    # 验证是否是工单选择消息
    if message.embeds and message.embeds[0].title == "Benvenuto nel ticket!":
        # 移除用户的表情(避免重复触发)
        await message.remove_reaction(payload.emoji, user)
        
        # 根据表情类型引导用户输入
        if payload.emoji.name == "1️⃣":
            await user.send("Inserisci la descrizione del report (nome utente + motivo):")
        elif payload.emoji.name == "2️⃣":
            await user.send("Inserisci la tua domanda per gli admin:")
        
        # 等待用户输入问题描述,超时5分钟自动终止
        try:
            response = await bot.wait_for(
                "message",
                check=lambda m: m.author == user and isinstance(m.channel, discord.DMChannel),
                timeout=300
            )
        except TimeoutError:
            await user.send("Timeout! Hai impiegato troppo tempo per rispondere.")
            return
        
        # 生成6位随机工单代码
        ticket_code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
        ticket_map[ticket_code] = user.id
        
        # 发送工单到指定管理员频道
        ticket_channel = bot.get_channel(TICKET_CHANNEL_ID)
        ticket_embed = discord.Embed(
            title=f"Nuovo ticket - {payload.emoji.name}",
            colour=discord.Colour.blue()
        )
        ticket_embed.add_field(name="Utente", value=f"{user.name} ({user.id})", inline=False)
        ticket_embed.add_field(name="Descrizione", value=response.content, inline=False)
        ticket_embed.set_footer(text=f"Codice ticket: [{ticket_code}]")
        await ticket_channel.send(embed=ticket_embed)
        
        # 通知用户工单已创建
        await user.send(f"Grazie! Il tuo ticket è stato creato. Codice: [{ticket_code}]\nTi risponderemo al più presto.")

# 替换为你的机器人TOKEN
bot.run("YOUR_BOT_TOKEN")

关键功能说明

  • 表情交互修复:通过on_raw_reaction_add事件监听用户的表情点击,解决原代码无法捕获用户交互的问题
  • 工单代码生成:用随机字母数字生成6位唯一代码,关联用户ID实现精准回复
  • 用户引导流程:用户选择表情后,机器人在DM中引导输入问题,超时未输入自动终止流程
  • 管理员回复处理:管理员在指定频道@机器人并带上[工单代码],机器人自动转发回复给对应用户
  • 状态反馈:用户和管理员都会收到操作成功/失败的即时反馈

使用注意事项

  1. 在Discord开发者后台开启机器人的所有必要Intents
  2. 替换代码中的TICKET_CHANNEL_ID为实际的服务器频道ID
  3. 替换YOUR_BOT_TOKEN为你的机器人TOKEN
  4. 可根据需求调整超时时间、工单代码长度、Embed样式等参数

内容的提问来源于stack exchange,提问作者GiveOff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 05:45:24