From 8aa241a56df3355efb2f2effb0bc9f0a3d582b36 Mon Sep 17 00:00:00 2001 From: pascal Date: Thu, 12 Sep 2024 17:55:27 +0200 Subject: [PATCH 01/10] implement get voice state feature --- .../net/dv8tion/jda/api/entities/Guild.java | 85 +++++++++++++++++++ .../net/dv8tion/jda/api/requests/Route.java | 1 + .../jda/internal/entities/EntityBuilder.java | 46 +++++----- .../jda/internal/entities/GuildImpl.java | 26 ++++++ 4 files changed, 139 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java index 8c07ec5325..961af368dc 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -2584,6 +2584,91 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) @Nonnull List getVoiceStates(); + /** + * Load the member's voice state for the specified user. + *
If the member is already loaded it will be retrieved from {@link #getMemberById(long)} and + * the voice state is immediately provided by {@link Member#getVoiceState()}. + * The cache consistency directly relies on the enabled {@link GatewayIntent GatewayIntents} as {@link GatewayIntent#GUILD_MEMBERS GatewayIntent.GUILD_MEMBERS} + * and {@link GatewayIntent#GUILD_VOICE_STATES GatewayIntent.GUILD_VOICE_STATES} are required to keep the cache updated with the latest information. + * You can use {@link CacheRestAction#useCache(boolean) useCache(false)} to always + * make a new request, which is the default behavior if the required intents are disabled. + * + *

Possible {@link net.dv8tion.jda.api.exceptions.ErrorResponseException ErrorResponseExceptions} include: + *

    + *
  • {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_VOICE_STATE} + *
    The specified user does not exist, is not a member of this guild or is not connected to a voice channel
  • + *
+ * + * @param id + * The user id to load the voice state from + * + * @return {@link RestAction} - Type: {@link GuildVoiceState} + */ + @Nonnull + CacheRestAction retrieveMemberVoiceStateById(long id); + + /** + * Load the member's voice state for the specified user. + *
If the member is already loaded it will be retrieved from {@link #getMemberById(long)} and + * the voice state is immediately provided by {@link Member#getVoiceState()}. + * The cache consistency directly relies on the enabled {@link GatewayIntent GatewayIntents} as {@link GatewayIntent#GUILD_MEMBERS GatewayIntent.GUILD_MEMBERS} + * and {@link GatewayIntent#GUILD_VOICE_STATES GatewayIntent.GUILD_VOICE_STATES} are required to keep the cache updated with the latest information. + * You can use {@link CacheRestAction#useCache(boolean) useCache(false)} to always + * make a new request, which is the default behavior if the required intents are disabled. + * + *

Possible {@link net.dv8tion.jda.api.exceptions.ErrorResponseException ErrorResponseExceptions} include: + *

    + *
  • {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_VOICE_STATE} + *
    The specified user does not exist, is not a member of this guild or is not connected to a voice channel
  • + *
+ * + * @param id + * The user id to load the voice state from + * + * @throws IllegalArgumentException + * If the provided id is empty or null + * @throws NumberFormatException + * If the provided id is not a snowflake + * + * @return {@link RestAction} - Type: {@link GuildVoiceState} + */ + @Nonnull + default CacheRestAction retrieveMemberVoiceStateById(@Nonnull String id) + { + return retrieveMemberVoiceStateById(MiscUtil.parseSnowflake(id)); + } + + /** + * Load the member's voice state for the specified {@link UserSnowflake}. + *
If the member is already loaded it will be retrieved from {@link #getMemberById(long)} and + * the voice state is immediately provided by {@link Member#getVoiceState()}. + * The cache consistency directly relies on the enabled {@link GatewayIntent GatewayIntents} as {@link GatewayIntent#GUILD_MEMBERS GatewayIntent.GUILD_MEMBERS} + * and {@link GatewayIntent#GUILD_VOICE_STATES GatewayIntent.GUILD_VOICE_STATES} are required to keep the cache updated with the latest information. + * You can use {@link CacheRestAction#useCache(boolean) useCache(false)} to always + * make a new request, which is the default behavior if the required intents are disabled. + * + *

Possible {@link net.dv8tion.jda.api.exceptions.ErrorResponseException ErrorResponseExceptions} include: + *

    + *
  • {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_VOICE_STATE} + *
    The specified user does not exist, is not a member of this guild or is not connected to a voice channel
  • + *
+ * + * @param user + * The {@link UserSnowflake} for the member's voice state to retrieve. + * This can be a member or user instance or {@link User#fromId(long)}. + * + * @throws IllegalArgumentException + * If provided with null + * + * @return {@link RestAction} - Type: {@link GuildVoiceState} + */ + @Nonnull + default CacheRestAction retrieveMemberVoiceState(UserSnowflake user) + { + Checks.notNull(user, "User"); + return retrieveMemberVoiceStateById(user.getId()); + } + /** * Returns the verification-Level of this Guild. Verification level is one of the factors that determines if a Member * can send messages in a Guild. diff --git a/src/main/java/net/dv8tion/jda/api/requests/Route.java b/src/main/java/net/dv8tion/jda/api/requests/Route.java index 0e165f9f85..ff9e95e800 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/Route.java +++ b/src/main/java/net/dv8tion/jda/api/requests/Route.java @@ -122,6 +122,7 @@ public static class Guilds public static final Route GET_GUILD_EMOJIS = new Route(GET, "guilds/{guild_id}/emojis"); public static final Route GET_AUDIT_LOGS = new Route(GET, "guilds/{guild_id}/audit-logs"); public static final Route GET_VOICE_REGIONS = new Route(GET, "guilds/{guild_id}/regions"); + public static final Route GET_VOICE_STATE = new Route(GET, "guilds/{guild_id}/voice-states/{user_id}"); public static final Route UPDATE_VOICE_STATE = new Route(PATCH, "guilds/{guild_id}/voice-states/{user_id}"); public static final Route GET_INTEGRATIONS = new Route(GET, "guilds/{guild_id}/integrations"); diff --git a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java index 687b1df795..b63d60a6ca 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -616,13 +616,13 @@ public MemberImpl createMember(GuildImpl guild, DataObject memberJson, DataObjec member.setFlags(memberJson.getInt("flags")); long boostTimestamp = memberJson.isNull("premium_since") - ? 0 - : Helpers.toTimestamp(memberJson.getString("premium_since")); + ? 0 + : Helpers.toTimestamp(memberJson.getString("premium_since")); member.setBoostDate(boostTimestamp); long timeOutTimestamp = memberJson.isNull("communication_disabled_until") - ? 0 - : Helpers.toTimestamp(memberJson.getString("communication_disabled_until")); + ? 0 + : Helpers.toTimestamp(memberJson.getString("communication_disabled_until")); member.setTimeOutEnd(timeOutTimestamp); if (!memberJson.isNull("pending")) @@ -658,39 +658,47 @@ public MemberImpl createMember(GuildImpl guild, DataObject memberJson, DataObjec // Load voice state and presence if necessary if (voiceStateJson != null && member.getVoiceState() != null) - createVoiceState(guild, voiceStateJson, user, member); + createGuildVoiceState(member, voiceStateJson); if (presence != null) createPresence(member, presence); return member; } - private void createVoiceState(GuildImpl guild, DataObject voiceStateJson, User user, MemberImpl member) - { + public GuildVoiceState createGuildVoiceState(MemberImpl member, DataObject voiceStateJson) { GuildVoiceStateImpl voiceState = (GuildVoiceStateImpl) member.getVoiceState(); + if (voiceState == null) + voiceState = new GuildVoiceStateImpl(member); + updateGuildVoiceState(voiceState, voiceStateJson, member); + return voiceState; + } + + private void updateGuildVoiceState(GuildVoiceStateImpl oldVoiceState, DataObject newVoiceStateJson, MemberImpl member) + { + Guild guild = member.getGuild(); - final long channelId = voiceStateJson.getLong("channel_id"); + final long channelId = newVoiceStateJson.getLong("channel_id"); AudioChannel audioChannel = (AudioChannel) guild.getGuildChannelById(channelId); if (audioChannel != null) ((AudioChannelMixin) audioChannel).getConnectedMembersMap().put(member.getIdLong(), member); else LOG.error("Received a GuildVoiceState with a channel ID for a non-existent channel! ChannelId: {} GuildId: {} UserId: {}", - channelId, guild.getId(), user.getId()); + channelId, guild.getId(), member.getId()); - String requestToSpeak = voiceStateJson.getString("request_to_speak_timestamp", null); + String requestToSpeak = newVoiceStateJson.getString("request_to_speak_timestamp", null); OffsetDateTime timestamp = null; if (requestToSpeak != null) timestamp = OffsetDateTime.parse(requestToSpeak); // VoiceState is considered volatile so we don't expect anything to actually exist - voiceState.setSelfMuted(voiceStateJson.getBoolean("self_mute")) - .setSelfDeafened(voiceStateJson.getBoolean("self_deaf")) - .setGuildMuted(voiceStateJson.getBoolean("mute")) - .setGuildDeafened(voiceStateJson.getBoolean("deaf")) - .setSuppressed(voiceStateJson.getBoolean("suppress")) - .setSessionId(voiceStateJson.getString("session_id")) - .setStream(voiceStateJson.getBoolean("self_stream")) - .setRequestToSpeak(timestamp) - .setConnectedChannel(audioChannel); + oldVoiceState.setSelfMuted(newVoiceStateJson.getBoolean("self_mute")) + .setSelfDeafened(newVoiceStateJson.getBoolean("self_deaf")) + .setGuildMuted(newVoiceStateJson.getBoolean("mute")) + .setGuildDeafened(newVoiceStateJson.getBoolean("deaf")) + .setSuppressed(newVoiceStateJson.getBoolean("suppress")) + .setSessionId(newVoiceStateJson.getString("session_id")) + .setStream(newVoiceStateJson.getBoolean("self_stream")) + .setRequestToSpeak(timestamp) + .setConnectedChannel(audioChannel); } public void updateMember(GuildImpl guild, MemberImpl member, DataObject content, List newRoles) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java index 2ab78beceb..363d8d0039 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -1153,6 +1153,32 @@ public List getVoiceStates() .collect(Helpers.toUnmodifiableList()); } + @Nonnull + @Override + public CacheRestAction retrieveMemberVoiceStateById(long id) + { + JDAImpl jda = getJDA(); + return new DeferredRestAction<>(jda, GuildVoiceState.class, + () -> + { + MemberImpl member = (MemberImpl) getMemberById(id); + return member == null ? null : member.getVoiceState(); + }, + () -> + { + Route.CompiledRoute route = Route.Guilds.GET_VOICE_STATE.compile(getId(), Long.toUnsignedString(id)); + return new RestActionImpl<>(jda, route, (response, request) -> + { + EntityBuilder entityBuilder = jda.getEntityBuilder(); + DataObject voiceStateData = response.getObject(); + //Creates voice state if VOICE_STATE cache flag is set + MemberImpl member = entityBuilder.createMember(this, voiceStateData.getObject("member"), voiceStateData, null); + entityBuilder.updateMemberCache(member); + return entityBuilder.createGuildVoiceState(member, voiceStateData); + }); + }).useCache(jda.isIntent(GatewayIntent.GUILD_MEMBERS) && jda.isIntent(GatewayIntent.GUILD_VOICE_STATES)); + } + @Nonnull @Override public VerificationLevel getVerificationLevel() From ba348e06c6cff0703a62ee1ca8f404a3c1545449 Mon Sep 17 00:00:00 2001 From: Pascal Bakker <54892083+PascalNB@users.noreply.github.com> Date: Tue, 8 Oct 2024 00:49:20 +0200 Subject: [PATCH 02/10] Update src/main/java/net/dv8tion/jda/api/entities/Guild.java Co-authored-by: Austin Keener --- src/main/java/net/dv8tion/jda/api/entities/Guild.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java index 961af368dc..c99812a712 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -2586,6 +2586,7 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) /** * Load the member's voice state for the specified user. + * *
If the member is already loaded it will be retrieved from {@link #getMemberById(long)} and * the voice state is immediately provided by {@link Member#getVoiceState()}. * The cache consistency directly relies on the enabled {@link GatewayIntent GatewayIntents} as {@link GatewayIntent#GUILD_MEMBERS GatewayIntent.GUILD_MEMBERS} From dcaa56d6c4cb499a211c0cc9116dc0047ec76640 Mon Sep 17 00:00:00 2001 From: Pascal Bakker <54892083+PascalNB@users.noreply.github.com> Date: Tue, 8 Oct 2024 00:49:49 +0200 Subject: [PATCH 03/10] Update src/main/java/net/dv8tion/jda/api/entities/Guild.java Co-authored-by: Austin Keener --- src/main/java/net/dv8tion/jda/api/entities/Guild.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java index c99812a712..06c80216b4 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -2667,7 +2667,7 @@ default CacheRestAction retrieveMemberVoiceStateById(@Nonnull S default CacheRestAction retrieveMemberVoiceState(UserSnowflake user) { Checks.notNull(user, "User"); - return retrieveMemberVoiceStateById(user.getId()); + return retrieveMemberVoiceStateById(user.getIdLong()); } /** From 5a49e10b4b45fb2ea9b4776a791701641881e877 Mon Sep 17 00:00:00 2001 From: pascal Date: Tue, 8 Oct 2024 00:51:17 +0200 Subject: [PATCH 04/10] remove unneeded change --- .../net/dv8tion/jda/internal/entities/EntityBuilder.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java index b63d60a6ca..0a67f4a184 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -616,13 +616,13 @@ public MemberImpl createMember(GuildImpl guild, DataObject memberJson, DataObjec member.setFlags(memberJson.getInt("flags")); long boostTimestamp = memberJson.isNull("premium_since") - ? 0 - : Helpers.toTimestamp(memberJson.getString("premium_since")); + ? 0 + : Helpers.toTimestamp(memberJson.getString("premium_since")); member.setBoostDate(boostTimestamp); long timeOutTimestamp = memberJson.isNull("communication_disabled_until") - ? 0 - : Helpers.toTimestamp(memberJson.getString("communication_disabled_until")); + ? 0 + : Helpers.toTimestamp(memberJson.getString("communication_disabled_until")); member.setTimeOutEnd(timeOutTimestamp); if (!memberJson.isNull("pending")) From 0b95631828b202b6f162c937fdac59f26ac5990d Mon Sep 17 00:00:00 2001 From: Pascal Bakker <54892083+PascalNB@users.noreply.github.com> Date: Tue, 8 Oct 2024 00:51:35 +0200 Subject: [PATCH 05/10] Update src/main/java/net/dv8tion/jda/api/entities/Guild.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Florian Spieß --- src/main/java/net/dv8tion/jda/api/entities/Guild.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java index 06c80216b4..1b5da7e7ce 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -2664,7 +2664,7 @@ default CacheRestAction retrieveMemberVoiceStateById(@Nonnull S * @return {@link RestAction} - Type: {@link GuildVoiceState} */ @Nonnull - default CacheRestAction retrieveMemberVoiceState(UserSnowflake user) + default CacheRestAction retrieveMemberVoiceState(@Nonnull UserSnowflake user) { Checks.notNull(user, "User"); return retrieveMemberVoiceStateById(user.getIdLong()); From 682e731906c4406adcb18fb6af19f36da794be1c Mon Sep 17 00:00:00 2001 From: pascal Date: Tue, 8 Oct 2024 01:58:56 +0200 Subject: [PATCH 06/10] change to normal RestAction instead of cached --- .../net/dv8tion/jda/api/entities/Guild.java | 25 ++-------------- .../jda/internal/entities/GuildImpl.java | 30 +++++++------------ 2 files changed, 13 insertions(+), 42 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java index 1b5da7e7ce..b79f4153cd 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -2587,13 +2587,6 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) /** * Load the member's voice state for the specified user. * - *
If the member is already loaded it will be retrieved from {@link #getMemberById(long)} and - * the voice state is immediately provided by {@link Member#getVoiceState()}. - * The cache consistency directly relies on the enabled {@link GatewayIntent GatewayIntents} as {@link GatewayIntent#GUILD_MEMBERS GatewayIntent.GUILD_MEMBERS} - * and {@link GatewayIntent#GUILD_VOICE_STATES GatewayIntent.GUILD_VOICE_STATES} are required to keep the cache updated with the latest information. - * You can use {@link CacheRestAction#useCache(boolean) useCache(false)} to always - * make a new request, which is the default behavior if the required intents are disabled. - * *

Possible {@link net.dv8tion.jda.api.exceptions.ErrorResponseException ErrorResponseExceptions} include: *

    *
  • {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_VOICE_STATE} @@ -2606,16 +2599,10 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) * @return {@link RestAction} - Type: {@link GuildVoiceState} */ @Nonnull - CacheRestAction retrieveMemberVoiceStateById(long id); + RestAction retrieveMemberVoiceStateById(long id); /** * Load the member's voice state for the specified user. - *
    If the member is already loaded it will be retrieved from {@link #getMemberById(long)} and - * the voice state is immediately provided by {@link Member#getVoiceState()}. - * The cache consistency directly relies on the enabled {@link GatewayIntent GatewayIntents} as {@link GatewayIntent#GUILD_MEMBERS GatewayIntent.GUILD_MEMBERS} - * and {@link GatewayIntent#GUILD_VOICE_STATES GatewayIntent.GUILD_VOICE_STATES} are required to keep the cache updated with the latest information. - * You can use {@link CacheRestAction#useCache(boolean) useCache(false)} to always - * make a new request, which is the default behavior if the required intents are disabled. * *

    Possible {@link net.dv8tion.jda.api.exceptions.ErrorResponseException ErrorResponseExceptions} include: *

      @@ -2634,19 +2621,13 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) * @return {@link RestAction} - Type: {@link GuildVoiceState} */ @Nonnull - default CacheRestAction retrieveMemberVoiceStateById(@Nonnull String id) + default RestAction retrieveMemberVoiceStateById(@Nonnull String id) { return retrieveMemberVoiceStateById(MiscUtil.parseSnowflake(id)); } /** * Load the member's voice state for the specified {@link UserSnowflake}. - *
      If the member is already loaded it will be retrieved from {@link #getMemberById(long)} and - * the voice state is immediately provided by {@link Member#getVoiceState()}. - * The cache consistency directly relies on the enabled {@link GatewayIntent GatewayIntents} as {@link GatewayIntent#GUILD_MEMBERS GatewayIntent.GUILD_MEMBERS} - * and {@link GatewayIntent#GUILD_VOICE_STATES GatewayIntent.GUILD_VOICE_STATES} are required to keep the cache updated with the latest information. - * You can use {@link CacheRestAction#useCache(boolean) useCache(false)} to always - * make a new request, which is the default behavior if the required intents are disabled. * *

      Possible {@link net.dv8tion.jda.api.exceptions.ErrorResponseException ErrorResponseExceptions} include: *

        @@ -2664,7 +2645,7 @@ default CacheRestAction retrieveMemberVoiceStateById(@Nonnull S * @return {@link RestAction} - Type: {@link GuildVoiceState} */ @Nonnull - default CacheRestAction retrieveMemberVoiceState(@Nonnull UserSnowflake user) + default RestAction retrieveMemberVoiceState(@Nonnull UserSnowflake user) { Checks.notNull(user, "User"); return retrieveMemberVoiceStateById(user.getIdLong()); diff --git a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java index 363d8d0039..b67553d4cd 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -1155,28 +1155,18 @@ public List getVoiceStates() @Nonnull @Override - public CacheRestAction retrieveMemberVoiceStateById(long id) + public RestAction retrieveMemberVoiceStateById(long id) { JDAImpl jda = getJDA(); - return new DeferredRestAction<>(jda, GuildVoiceState.class, - () -> - { - MemberImpl member = (MemberImpl) getMemberById(id); - return member == null ? null : member.getVoiceState(); - }, - () -> - { - Route.CompiledRoute route = Route.Guilds.GET_VOICE_STATE.compile(getId(), Long.toUnsignedString(id)); - return new RestActionImpl<>(jda, route, (response, request) -> - { - EntityBuilder entityBuilder = jda.getEntityBuilder(); - DataObject voiceStateData = response.getObject(); - //Creates voice state if VOICE_STATE cache flag is set - MemberImpl member = entityBuilder.createMember(this, voiceStateData.getObject("member"), voiceStateData, null); - entityBuilder.updateMemberCache(member); - return entityBuilder.createGuildVoiceState(member, voiceStateData); - }); - }).useCache(jda.isIntent(GatewayIntent.GUILD_MEMBERS) && jda.isIntent(GatewayIntent.GUILD_VOICE_STATES)); + Route.CompiledRoute route = Route.Guilds.GET_VOICE_STATE.compile(getId(), Long.toUnsignedString(id)); + return new RestActionImpl<>(jda, route, (response, request) -> + { + EntityBuilder entityBuilder = jda.getEntityBuilder(); + DataObject voiceStateData = response.getObject(); + MemberImpl member = entityBuilder.createMember(this, voiceStateData.getObject("member"), voiceStateData, null); + entityBuilder.updateMemberCache(member); + return entityBuilder.createGuildVoiceState(member, voiceStateData); + }); } @Nonnull From a2bd654d4571d84e12cc3ce95205382c452e31c2 Mon Sep 17 00:00:00 2001 From: pascal Date: Tue, 8 Oct 2024 02:01:17 +0200 Subject: [PATCH 07/10] add CheckReturnValue --- src/main/java/net/dv8tion/jda/api/entities/Guild.java | 3 +++ src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java | 1 + 2 files changed, 4 insertions(+) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java index b79f4153cd..fc8aef66eb 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -2599,6 +2599,7 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) * @return {@link RestAction} - Type: {@link GuildVoiceState} */ @Nonnull + @CheckReturnValue RestAction retrieveMemberVoiceStateById(long id); /** @@ -2621,6 +2622,7 @@ default RestAction retrieveEmoji(@Nonnull CustomEmoji emoji) * @return {@link RestAction} - Type: {@link GuildVoiceState} */ @Nonnull + @CheckReturnValue default RestAction retrieveMemberVoiceStateById(@Nonnull String id) { return retrieveMemberVoiceStateById(MiscUtil.parseSnowflake(id)); @@ -2645,6 +2647,7 @@ default RestAction retrieveMemberVoiceStateById(@Nonnull String * @return {@link RestAction} - Type: {@link GuildVoiceState} */ @Nonnull + @CheckReturnValue default RestAction retrieveMemberVoiceState(@Nonnull UserSnowflake user) { Checks.notNull(user, "User"); diff --git a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java index b67553d4cd..632bd552ca 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -1155,6 +1155,7 @@ public List getVoiceStates() @Nonnull @Override + @CheckReturnValue public RestAction retrieveMemberVoiceStateById(long id) { JDAImpl jda = getJDA(); From a2b888c4e3f7fda18a96b9fc930396d203fe79f0 Mon Sep 17 00:00:00 2001 From: Pascal Bakker <54892083+PascalNB@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:11:47 +0100 Subject: [PATCH 08/10] Update src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Florian Spieß --- .../java/net/dv8tion/jda/internal/entities/EntityBuilder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java index 0a67f4a184..51f838f8cc 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -664,7 +664,8 @@ public MemberImpl createMember(GuildImpl guild, DataObject memberJson, DataObjec return member; } - public GuildVoiceState createGuildVoiceState(MemberImpl member, DataObject voiceStateJson) { + public GuildVoiceState createGuildVoiceState(MemberImpl member, DataObject voiceStateJson) + { GuildVoiceStateImpl voiceState = (GuildVoiceStateImpl) member.getVoiceState(); if (voiceState == null) voiceState = new GuildVoiceStateImpl(member); From aee58573feaf7c7dfe0a3189741f91068b6bc772 Mon Sep 17 00:00:00 2001 From: pascal Date: Sat, 9 Nov 2024 23:06:26 +0100 Subject: [PATCH 09/10] avoid updating channel's member cache if voice states aren't cached --- .../net/dv8tion/jda/internal/entities/EntityBuilder.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java index 0a67f4a184..c93b6b89d7 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -679,7 +679,10 @@ private void updateGuildVoiceState(GuildVoiceStateImpl oldVoiceState, DataObject final long channelId = newVoiceStateJson.getLong("channel_id"); AudioChannel audioChannel = (AudioChannel) guild.getGuildChannelById(channelId); if (audioChannel != null) - ((AudioChannelMixin) audioChannel).getConnectedMembersMap().put(member.getIdLong(), member); + { + if (member.getVoiceState() != null) + ((AudioChannelMixin) audioChannel).getConnectedMembersMap().put(member.getIdLong(), member); + } else LOG.error("Received a GuildVoiceState with a channel ID for a non-existent channel! ChannelId: {} GuildId: {} UserId: {}", channelId, guild.getId(), member.getId()); From 5143e61aae3b1fc9cb7a973e6f56f322cd9c6b10 Mon Sep 17 00:00:00 2001 From: pascal Date: Sat, 9 Nov 2024 23:07:47 +0100 Subject: [PATCH 10/10] avoid updating voice state twice --- src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java index 632bd552ca..f3781b885b 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -1164,7 +1164,7 @@ public RestAction retrieveMemberVoiceStateById(long id) { EntityBuilder entityBuilder = jda.getEntityBuilder(); DataObject voiceStateData = response.getObject(); - MemberImpl member = entityBuilder.createMember(this, voiceStateData.getObject("member"), voiceStateData, null); + MemberImpl member = entityBuilder.createMember(this, voiceStateData.getObject("member"), null, null); entityBuilder.updateMemberCache(member); return entityBuilder.createGuildVoiceState(member, voiceStateData); });