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

discord.py中通过用户ID发送服务器邀请的命令实现问题

解决Discord机器人发送私信邀请时的InvalidArgument错误

这个错误很典型——你之所以遇到InvalidArgument: Destination must be Channel, PrivateChannel, User, or Object. Received str,是因为你直接把用户ID的字符串传给了发送消息的方法,但Discord.js要求的是User对象/私有频道对象,不是纯文本ID。下面分步骤帮你解决这个问题,同时实现跨服务器可用的临时邀请功能:

核心思路

  1. 先将用户提供的ID/提及转化为Discord.js能识别的User对象
  2. 在当前服务器创建一个临时、一次性的邀请链接(避免永久链接)
  3. 通过User对象给目标用户发送私信邀请

完整代码实现(以Discord.js v14为例)

方案1:使用Slash命令(推荐,更符合Discord现代规范)

const { SlashCommandBuilder } = require('discord.js');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('send-invite')
        .setDescription('Send a server invite to a user via DM')
        .addUserOption(option =>
            option.setName('target')
                .setDescription('The user to send the invite to')
                .setRequired(true)),
    async execute(interaction) {
        try {
            // 从命令选项直接获取User对象(无需手动处理ID)
            const targetUser = interaction.options.getUser('target');
            
            // 找一个机器人有创建邀请权限的文本频道
            const inviteChannel = interaction.guild.channels.cache.find(channel => 
                channel.type === 0 && // 0代表文本频道(对应Discord.js v14的ChannelType.GuildText)
                channel.permissionsFor(interaction.guild.members.me).has('CreateInstantInvite')
            );
            
            if (!inviteChannel) {
                return interaction.reply({ 
                    content: '我没有在这个服务器创建邀请的权限,请检查我的频道权限!', 
                    ephemeral: true 
                });
            }
            
            // 创建临时邀请:1小时过期,仅可使用1次
            const invite = await inviteChannel.createInvite({
                maxAge: 3600, // 过期时间(秒),设为0则永久,这里按需求设为1小时
                maxUses: 1,   // 最大使用次数
                unique: true  // 生成唯一链接
            });
            
            // 发送私信
            await targetUser.send(`这是你加入${interaction.guild.name}的邀请链接:${invite.url}`);
            
            await interaction.reply({ 
                content: `邀请已成功发送给${targetUser.tag}!`, 
                ephemeral: true 
            });
        } catch (error) {
            console.error(error);
            // 针对性处理常见错误
            if (error.code === 50007) {
                interaction.reply({ 
                    content: `无法给${targetUser.tag}发送私信,对方可能关闭了服务器成员的私信权限!`, 
                    ephemeral: true 
                });
            } else {
                interaction.reply({ 
                    content: '发送邀请时出现错误,请稍后重试!', 
                    ephemeral: true 
                });
            }
        }
    },
};

方案2:使用前缀命令(适合习惯旧版命令的场景)

如果你的机器人用的是前缀触发(比如!sendinvite @用户),需要手动把用户提及/ID转化为User对象:

client.on('messageCreate', async (message) => {
    // 过滤非命令消息和机器人消息
    if (!message.content.startsWith('!sendinvite') || message.author.bot) return;
    
    const args = message.content.slice('!sendinvite'.length).trim().split(' ');
    const targetInput = args[0];
    
    if (!targetInput) {
        return message.reply('请指定要发送邀请的用户(可以@用户或输入用户ID)!');
    }
    
    try {
        // 提取用户ID:处理@提及的格式(比如<@123456789>)
        const targetUserId = targetInput.startsWith('<@') && targetInput.endsWith('>') 
            ? targetInput.slice(2, -1).replace('!', '') 
            : targetInput;
        
        // 全局获取用户对象(即使用户不在当前服务器也能拿到)
        const targetUser = await client.users.fetch(targetUserId);
        
        // 找可创建邀请的频道
        const inviteChannel = message.guild.channels.cache.find(channel => 
            channel.type === 0 && 
            channel.permissionsFor(message.guild.members.me).has('CreateInstantInvite')
        );
        
        if (!inviteChannel) {
            return message.reply('我没有在这个服务器创建邀请的权限!');
        }
        
        // 创建临时邀请
        const invite = await inviteChannel.createInvite({
            maxAge: 3600,
            maxUses: 1,
            unique: true
        });
        
        // 发送私信
        await targetUser.send(`这是你加入${message.guild.name}的邀请链接:${invite.url}`);
        
        message.reply(`邀请已成功发送给${targetUser.tag}!`);
    } catch (error) {
        console.error(error);
        if (error.code === 10013) {
            message.reply('找不到这个用户,请检查用户ID是否正确!');
        } else if (error.code === 50007) {
            message.reply('无法发送私信,对方可能关闭了私信权限!');
        } else {
            message.reply('发送邀请时出现错误,请稍后重试!');
        }
    }
});

关键注意事项

  • 获取用户对象的正确方式:别用字符串ID直接传,一定要用client.users.fetch()来获取全局用户对象——guild.members.fetch()只能获取当前服务器的成员,如果目标用户不在服务器就会失败。
  • 机器人权限:确保机器人在目标服务器有CreateInstantInvite权限,否则无法创建邀请。
  • 临时邀请参数:通过maxAge和maxUses控制邀请的有效期和使用次数,完美解决你不能用永久链接的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:22:43