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

如何为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()

代码优化说明

  1. 将工具函数(get_weather、create_weather_embed)移到run_discord_bot外部,避免嵌套过深,提升可读性。
  2. 给!hava命令增加参数检查,防止用户未输入城市名导致报错。
  3. 统一消息过滤逻辑,提前判断是否为机器人消息,避免重复判断。
  4. 头像命令使用display_avatar而非avatar,确保获取用户当前使用的头像(包括动态头像)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:07:07