JDA 事件获取器返回 null 并让所有成员在一个角色中只返回机器人本身

Posted

技术标签:

【中文标题】JDA 事件获取器返回 null 并让所有成员在一个角色中只返回机器人本身【英文标题】:JDA Event getters returning null & getting all members in a role returning only the bot itself 【发布时间】:2021-01-04 18:06:47 【问题描述】:

我正在尝试创建一个不和谐机器人,当公会成员从消息中添加/删除反应时添加/删除角色,并在触发发生时从特定角色中删除所有成员。

每次我为onMessageReactionRemove 事件执行event.getmember 时,由于某种原因,我总是得到空值。当我还尝试获取具有特定角色的所有成员并将其放入列表时,我只会将机器人本身放入列表中。当机器人尝试从特定角色中删除所有成员时,我也没有收到任何错误。一天前我让这个机器人工作了,但我不知道为什么它现在不能工作。

在文档上,它说如果用户不再在公会中,它将返回 null,但是当我删除反应时,我仍然在公会中。

这是当机器人试图获取删除反应的成员时的错误消息,当机器人试图从成员中删除角色时会触发此错误:

[JDA MainWS-ReadThread] ERROR JDA - One of the EventListeners had an uncaught exception
java.lang.IllegalArgumentException: Member may not be null
    at net.dv8tion.jda.internal.utils.Checks.notNull(Checks.java:64)
    at net.dv8tion.jda.internal.entities.GuildImpl.removeRoleFromMember(GuildImpl.java:1209)
    at me.david.tskmanager.eventlisteners.EventChannelsEventListener.onMessageReactionRemove(EventChannelsEventListener.java:47)
    at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:440)
    at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:96)
    at net.dv8tion.jda.internal.hooks.EventManagerProxy.handleInternally(EventManagerProxy.java:82)
    at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:69)
    at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:150)
    at net.dv8tion.jda.internal.handle.MessageReactionHandler.onRemove(MessageReactionHandler.java:200)
    at net.dv8tion.jda.internal.handle.MessageReactionHandler.handleInternally(MessageReactionHandler.java:146)
    at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:947)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:834)
    at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:812)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:985)
    at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
    at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
    at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
    at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
    at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
    at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
    at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)

这是我的代码:

@Override
    public void onMessageReactionRemove(@Nonnull MessageReactionRemoveEvent event) 
        System.out.println(event.getMember());
        if (trackedMessages.contains(event.getMessageId()) && event.getReactionEmote().getEmote().equals(event.getGuild().getEmoteById(emoteID))) 
            GuildCache cache = GuildCache.getCache(event.getGuild().getId());
            System.out.println(cache.getAttendingEventRole());
            event.getGuild().removeRoleFromMember(event.getMember(), cache.getAttendingEventRole()).queue();
        
    

    @Override
    public void onMessageUpdate(@Nonnull MessageUpdateEvent event) 
        if (trackedMessages.contains(event.getMessageId()) && event.getMessage().getContentRaw().startsWith("[FINISHED]")) 
            GuildCache cache = GuildCache.getCache(event.getGuild().getId());
            List<Member> members = new ArrayList<>();
            members.addAll(event.getGuild().getMembersWithRoles(cache.getAttendingEventRole()));
            for (Member member : members) 
                event.getGuild().removeRoleFromMember(member, cache.getAttendingEventRole()).queue();
                System.out.println("removed role");
            
            trackedMessages.remove(event.getMessageId());
        
    

如果您需要更多代码 sn-ps,只需注释您需要的内容。

编辑:解决了event.getMember只返回null的问题。

编辑 2:所以 Moorhuhn 在 cmets 中所说的话帮助我解决了另一个问题。问题是机器人只缓存了语音聊天中的成员,因此无法获取具有特定角色的成员。

【问题讨论】:

您可以查看网关意图。 github.com/DV8FromTheWorld/JDA/wiki/… 我不知道这将如何帮助我解决我的问题。 @Moorhuhn 你可以只使用event.getUserId()而不是可以为空的成员。 【参考方案1】:

请改用event.getUserId()。 Discord 不提供用于移除反应的成员信息。 removeRoleFromMember 方法也接受用户 ID:removeRoleFromMember(String, Role)

【讨论】:

好了,问题解决了,我只需要解决getMembersWithRoles方法的问题,只获取bot本身。

以上是关于JDA 事件获取器返回 null 并让所有成员在一个角色中只返回机器人本身的主要内容,如果未能解决你的问题,请参考以下文章

提交 onMessageReceived/onSlashCommand 事件时如何在 JDA 中获取公会 ID

获取 Embed-Discord API (JDA) 的提及用户

JDA:如何检测成员是如何从公会中移除的?

builder.build().getShardManager() 返回 null (JDA Discord Bot) |我如何调用 shardmanager?

“JDA 成员可能不为空”错误的替代解决方案

JDA 获取所有渠道