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中引导输入问题,超时未输入自动终止流程
- 管理员回复处理:管理员在指定频道@机器人并带上
[工单代码],机器人自动转发回复给对应用户 - 状态反馈:用户和管理员都会收到操作成功/失败的即时反馈
使用注意事项
- 在Discord开发者后台开启机器人的所有必要Intents
- 替换代码中的
TICKET_CHANNEL_ID为实际的服务器频道ID - 替换
YOUR_BOT_TOKEN为你的机器人TOKEN - 可根据需求调整超时时间、工单代码长度、Embed样式等参数
内容的提问来源于stack exchange,提问作者GiveOff
相关产品推荐
相关产品推荐

