如何为discord.py机器人添加获取提及用户头像的命令
Discord.py机器人添加头像获取命令及代码优化
实现思路
你当前使用discord.Client类,所有逻辑都堆在on_message事件里,代码会随功能增加变得臃肿。下面提供两种实现!pfp @user命令的方案,同时优化代码结构:
方案一:在现有on_message事件中扩展逻辑
无需切换框架,直接在已有的消息处理逻辑里加入头像命令:
修改后的完整代码:
import discord import responses import requests async def send_message(message, user_message, is_private): try: response = responses.handle_response(user_message) await message.author.send(response) if is_private else await message.channel.send(response) except Exception as e: print(e) def get_weather(city, api_key): base_url = 'http://api.openweathermap.org/data/2.5/weather' params = { 'q': city, 'appid': api_key, 'units': 'metric' } responsee = requests.get(base_url, params=params) return responsee.json() if responsee.status_code == 200 else None def create_weather_embed(city, data): embed = discord.Embed(title=f"{city} şehrinde hava durumu:", color=0x00ff00) embed.add_field(name="Hava Durumu", value=data['weather'][0]['description'], inline=False) embed.add_field(name="Sıcaklık", value=f"{data['main']['temp']}°C", inline=True) embed.add_field(name="Hissedilen Sıcaklık", value=f"{data['main']['feels_like']}°C", inline=True) embed.add_field(name="Bulutlar", value=f"{data['clouds']['all']}%", inline=True) embed.add_field(name="Nem Oranı", value=f"{data['main']['humidity']}%", inline=True) embed.set_thumbnail(url=f"http://openweathermap.org/img/w/{data['weather'][0]['icon']}.png") return embed def run_discord_bot(): TOKEN = '' WEATHER_API_KEY = '' intents = discord.Intents.all() client = discord.Client(intents=intents) @client.event async def on_ready(): print(f'{client.user} is now running') @client.event async def on_message(message): # 跳过机器人自身消息 if message.author == client.user: return username = str(message.author) user_message = str(message.content) channel = str(message.channel) print(f'{username} said: {user_message} ({channel})') # 处理私聊命令(?开头) if user_message.startswith('?'): user_message = user_message[1:] await send_message(message, user_message, is_private=True) else: await send_message(message, user_message, is_private=False) # 禁止@everyone if '@everyone' in message.content: await message.channel.send(f"{message.author.mention}, don't ping everyone") # 处理"önemli"消息转发 if 'önemli' in user_message and message.mentions: mentioned_user = message.mentions[0] if mentioned_user != client.user: await mentioned_user.send(f'{message.author} said {message.content}') # 处理天气命令!hava if user_message.startswith('!hava'): if len(user_message.split()) < 2: await message.channel.send("Lütfen şehir adını belirtin: `!hava İstanbul`") return city = user_message.split(' ', 1)[1] weather_data = get_weather(city, WEATHER_API_KEY) if weather_data: embed = create_weather_embed(city, weather_data) await message.channel.send(embed=embed) else: await message.channel.send("Şehir bulunamadı ya da API hatası var.") # 处理头像命令!pfp if user_message.startswith('!pfp'): # 优先取提及用户,无提及则用消息发送者 target_user = message.mentions[0] if message.mentions else message.author # 获取用户当前使用的头像(支持动态头像) avatar_url = target_user.display_avatar.url # 用Embed发送头像更美观 embed = discord.Embed(title=f"{target_user.name} 的头像", color=0x0099ff) embed.set_image(url=avatar_url) await message.channel.send(embed=embed) client.run(TOKEN) if __name__ == "__main__": run_discord_bot()
方案二:改用commands.Bot框架(推荐,便于后续扩展)
commands.Bot是discord.py专为命令开发设计的框架,用装饰器定义命令更简洁,代码结构更清晰:
修改后的完整代码:
import discord from discord.ext import commands import responses import requests async def send_message(message, user_message, is_private): try: response = responses.handle_response(user_message) await message.author.send(response) if is_private else await message.channel.send(response) except Exception as e: print(e) def get_weather(city, api_key): base_url = 'http://api.openweathermap.org/data/2.5/weather' params = { 'q': city, 'appid': api_key, 'units': 'metric' } responsee = requests.get(base_url, params=params) return responsee.json() if responsee.status_code == 200 else None def create_weather_embed(city, data): embed = discord.Embed(title=f"{city} şehrinde hava durumu:", color=0x00ff00) embed.add_field(name="Hava Durumu", value=data['weather'][0]['description'], inline=False) embed.add_field(name="Sıcaklık", value=f"{data['main']['temp']}°C", inline=True) embed.add_field(name="Hissedilen Sıcaklık", value=f"{data['main']['feels_like']}°C", inline=True) embed.add_field(name="Bulutlar", value=f"{data['clouds']['all']}%", inline=True) embed.add_field(name="Nem Oranı", value=f"{data['main']['humidity']}%", inline=True) embed.set_thumbnail(url=f"http://openweathermap.org/img/w/{data['weather'][0]['icon']}.png") return embed def run_discord_bot(): TOKEN = '' WEATHER_API_KEY = '' intents = discord.Intents.all() # 设置命令前缀为!,可自行修改 bot = commands.Bot(command_prefix='!', intents=intents) @bot.event async def on_ready(): print(f'{bot.user} is now running') @bot.event async def on_message(message): # 跳过机器人自身消息 if message.author == bot.user: return username = str(message.author) user_message = str(message.content) channel = str(message.channel) print(f'{username} said: {user_message} ({channel})') # 处理私聊命令(?开头) if user_message.startswith('?'): user_message = user_message[1:] await send_message(message, user_message, is_private=True) else: await send_message(message, user_message, is_private=False) # 禁止@everyone if '@everyone' in message.content: await message.channel.send(f"{message.author.mention}, don't ping everyone") # 处理"önemli"消息转发 if 'önemli' in user_message and message.mentions: mentioned_user = message.mentions[0] if mentioned_user != bot.user: await mentioned_user.send(f'{message.author} said {message.content}') # 必须添加此行,否则命令装饰器不会生效 await bot.process_commands(message) # 天气命令:!hava <城市名> @bot.command(name='hava') async def hava(ctx, *, city): weather_data = get_weather(city, WEATHER_API_KEY) if weather_data: embed = create_weather_embed(city, weather_data) await ctx.send(embed=embed) else: await ctx.send("Şehir bulunamadı ya da API hatası var.") # 头像命令:!pfp [@用户],不@用户则获取自己的头像 @bot.command(name='pfp') async def pfp(ctx, user: discord.User = None): target_user = user or ctx.author avatar_url = target_user.display_avatar.url embed = discord.Embed(title=f"{target_user.name} 的头像", color=0x0099ff) embed.set_image(url=avatar_url) await ctx.send(embed=embed) bot.run(TOKEN) if __name__ == "__main__": run_discord_bot()
代码优化说明
- 将工具函数(
get_weather、create_weather_embed)移到run_discord_bot外部,避免嵌套过深,提升可读性。 - 给
!hava命令增加参数检查,防止用户未输入城市名导致报错。 - 统一消息过滤逻辑,提前判断是否为机器人消息,避免重复判断。
- 头像命令使用
display_avatar而非avatar,确保获取用户当前使用的头像(包括动态头像)。
内容的提问来源于stack exchange,提问作者Vailecia
相关产品推荐
相关产品推荐

