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

JDA框架getUsersByName()方法调用问题求助:Discord机器人实现用户@提及的用户ID获取方案

解决JDA机器人中调用getUsersByName的问题

嗨,我来帮你理清这个问题!其实你遇到的核心点是JDA实例的获取和传递——你不需要去实例化抽象的JDA类,也不用纠结静态方法的问题,因为JDA实例在你启动机器人的时候就已经创建好了,你只需要把它传到需要用的地方就行。

核心思路

JDA实例是通过JDABuilder创建的(它会帮你处理抽象类的实例化逻辑),你可以通过两种方式拿到它:

  1. 在消息事件监听中直接通过event.getJDA()获取(推荐,因为命令处理本身就应该放在消息事件里)
  2. 在Main类中保存JDA实例,通过静态方法提供访问入口

下面给你具体的代码示例:


方案1:用事件监听器处理命令(推荐)

这种方式最符合JDA的设计逻辑,命令处理本身就是响应消息事件的一部分,不需要额外开线程(当然你要开线程也可以,后面会说)。

第一步:Main类启动机器人并注册监听器

public class Main {
    public static void main(String[] args) {
        try {
            // 通过JDABuilder创建JDA实例,这里会自动处理抽象类的实例化
            JDABuilder.createDefault("你的机器人令牌")
                    .addEventListeners(new CommandHandler()) // 注册命令处理监听器
                    .build()
                    .awaitReady(); // 等待机器人完成初始化
        } catch (LoginException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

第二步:编写命令处理监听器

public class CommandHandler extends ListenerAdapter {
    @Override
    public void onMessageReceived(MessageReceivedEvent event) {
        String messageContent = event.getContentRaw();
        // 拆分命令前缀、指令和目标用户
        String[] commandParts = messageContent.split(" ", 2);
        
        // 检查是否是!harass命令
        if (commandParts.length >= 2 && commandParts[0].equals("!harass")) {
            String targetUserName = commandParts[1];
            
            // 从事件中直接获取JDA实例,完美解决非静态方法的问题
            JDA jda = event.getJDA();
            // 查找匹配的用户,ignoreCase设为true支持大小写模糊匹配
            List<User> matchedUsers = jda.getUsersByName(targetUserName, true);
            
            if (!matchedUsers.isEmpty()) {
                User targetUser = matchedUsers.get(0); // 取第一个匹配的用户
                // 在频道中提及目标用户
                event.getChannel().sendMessage(targetUser.getAsMention() + " 收到了你的召唤!").queue();
            } else {
                event.getChannel().sendMessage("找不到用户 " + targetUserName + " 哦~").queue();
            }
        }
    }
}

方案2:如果你坚持要用Harass线程类

如果你的业务逻辑确实需要单独开线程处理,那只需要把JDA实例和必要的参数通过构造函数传递给Harass类即可:

修改Harass线程类

public class Harass extends Thread {
    private final JDA jda;
    private final String targetUserName;
    private final MessageChannel channel;

    // 通过构造函数传入需要的实例和参数
    public Harass(JDA jda, String targetUserName, MessageChannel channel) {
        this.jda = jda;
        this.targetUserName = targetUserName;
        this.channel = channel;
    }

    @Override
    public void run() {
        List<User> matchedUsers = jda.getUsersByName(targetUserName, true);
        if (!matchedUsers.isEmpty()) {
            User targetUser = matchedUsers.get(0);
            channel.sendMessage(targetUser.getAsMention() + " 被线程点名啦!").queue();
        } else {
            channel.sendMessage("线程中找不到用户 " + targetUserName + "!").queue();
        }
    }
}

在监听器中调用线程

回到CommandHandler的onMessageReceived方法里,把原来的发送逻辑替换成:

if (commandParts.length >= 2 && commandParts[0].equals("!harass")) {
    String targetUserName = commandParts[1];
    JDA jda = event.getJDA();
    MessageChannel channel = event.getChannel();
    // 启动Harass线程,传入必要的实例
    new Harass(jda, targetUserName, channel).start();
}

额外提示

  • getUsersByName返回的是用户列表,因为服务器里可能有重名用户,建议你可以在找不到用户的时候提示用户使用用户ID(更精确),或者显示所有匹配的用户让用户选择。
  • 尽量避免用静态变量存储JDA实例(虽然可行,但容易引发线程安全问题),优先用事件中的event.getJDA()获取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 22:07:45