diff --git a/gradle.properties b/gradle.properties index ea841d676d..0cab430220 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ org.gradle.caching = true -version = 3.3.3-SNAPSHOT +version = 3.4.0-SNAPSHOT diff --git a/javacord-api/src/main/java/org/javacord/api/DiscordApiBuilder.java b/javacord-api/src/main/java/org/javacord/api/DiscordApiBuilder.java index ba822e1cbf..9ef85802fa 100644 --- a/javacord-api/src/main/java/org/javacord/api/DiscordApiBuilder.java +++ b/javacord-api/src/main/java/org/javacord/api/DiscordApiBuilder.java @@ -439,6 +439,28 @@ public DiscordApiBuilder setAllIntentsWhere(Predicate condition) { return this; } + /** + * Sets whether or not the user cache should be enabled. + * + *

By default, the user cache is disabled. + * + * @param enabled Whether or not the user cache should be enabled. + * @return The current instance in order to chain call methods. + */ + public DiscordApiBuilder setUserCacheEnabled(boolean enabled) { + delegate.setUserCacheEnabled(enabled); + return this; + } + + /** + * Gets whether or not the user cache is enabled. + * + * @return Whether or not the user cache is enabled. + */ + public boolean isUserCachedEnabled() { + return delegate.isUserCacheEnabled(); + } + /** * Retrieves the recommended shards count from the Discord API and sets it in this builder. * Sharding allows you to split your bot into several independent instances. diff --git a/javacord-api/src/main/java/org/javacord/api/internal/DiscordApiBuilderDelegate.java b/javacord-api/src/main/java/org/javacord/api/internal/DiscordApiBuilderDelegate.java index 48f2e8b80d..95b5691c99 100644 --- a/javacord-api/src/main/java/org/javacord/api/internal/DiscordApiBuilderDelegate.java +++ b/javacord-api/src/main/java/org/javacord/api/internal/DiscordApiBuilderDelegate.java @@ -178,6 +178,22 @@ public interface DiscordApiBuilderDelegate { */ void setAllIntentsWhere(Predicate condition); + /** + * Sets whether or not the user cache should be enabled. + * + *

By default, the user cache is disabled. + * + * @param enabled Whether or not the user cache should be enabled. + */ + void setUserCacheEnabled(boolean enabled); + + /** + * Gets whether or not the user cache is enabled. + * + * @return Whether or not the user cache is enabled. + */ + boolean isUserCacheEnabled(); + /** * Logs the bot in. * diff --git a/javacord-core/src/main/java/org/javacord/core/DiscordApiBuilderDelegateImpl.java b/javacord-core/src/main/java/org/javacord/core/DiscordApiBuilderDelegateImpl.java index cf83c07540..dcc4389a6c 100644 --- a/javacord-core/src/main/java/org/javacord/core/DiscordApiBuilderDelegateImpl.java +++ b/javacord-core/src/main/java/org/javacord/core/DiscordApiBuilderDelegateImpl.java @@ -129,6 +129,11 @@ public class DiscordApiBuilderDelegateImpl implements DiscordApiBuilderDelegate private Set intents = Arrays.stream(Intent.values()) .filter(intent -> !intent.isPrivileged()).collect(Collectors.toCollection(HashSet::new)); + /** + * Whether the user cache should be enabled or not. + */ + private boolean userCacheEnabled = false; + /** * The globally attachable listeners to register for every created DiscordApi instance. */ @@ -194,7 +199,7 @@ public CompletableFuture login() { new DiscordApiImpl(accountType, token, currentShard.get(), totalShards.get(), intents, waitForServersOnStartup, waitForUsersOnStartup, registerShutdownHook, globalRatelimiter, gatewayIdentifyRatelimiter, proxySelector, proxy, proxyAuthenticator, trustAllCertificates, - future, null, preparedListeners, preparedUnspecifiedListeners); + future, null, preparedListeners, preparedUnspecifiedListeners, userCacheEnabled); } return future; } @@ -395,6 +400,16 @@ public void setAllIntentsWhere(Predicate condition) { } } + @Override + public void setUserCacheEnabled(boolean enabled) { + userCacheEnabled = enabled; + } + + @Override + public boolean isUserCacheEnabled() { + return userCacheEnabled; + } + @Override public CompletableFuture setRecommendedTotalShards() { CompletableFuture future = new CompletableFuture<>(); diff --git a/javacord-core/src/main/java/org/javacord/core/DiscordApiImpl.java b/javacord-core/src/main/java/org/javacord/core/DiscordApiImpl.java index 4b10131c13..57616a25eb 100644 --- a/javacord-core/src/main/java/org/javacord/core/DiscordApiImpl.java +++ b/javacord-core/src/main/java/org/javacord/core/DiscordApiImpl.java @@ -462,7 +462,7 @@ public DiscordApiImpl( ) { this(accountType, token, currentShard, totalShards, intents, waitForServersOnStartup, waitForUsersOnStartup, true, globalRatelimiter, gatewayIdentifyRatelimiter, proxySelector, proxy, proxyAuthenticator, - trustAllCertificates, ready, null, Collections.emptyMap(), Collections.emptyList()); + trustAllCertificates, ready, null, Collections.emptyMap(), Collections.emptyList(), false); } /** @@ -509,7 +509,7 @@ private DiscordApiImpl( Dns dns) { this(accountType, token, currentShard, totalShards, intents, waitForServersOnStartup, waitForUsersOnStartup, true, globalRatelimiter, gatewayIdentifyRatelimiter, proxySelector, proxy, proxyAuthenticator, - trustAllCertificates, ready, dns, Collections.emptyMap(), Collections.emptyList()); + trustAllCertificates, ready, dns, Collections.emptyMap(), Collections.emptyList(), false); } /** @@ -532,13 +532,14 @@ private DiscordApiImpl( * websocket. * @param proxyAuthenticator The authenticator that should be used to authenticate against proxies that * require it. - * @param trustAllCertificates Whether to trust all SSL certificates. + * @param trustAllCertificates Whether to trust all SSL certificates. * @param ready The future which will be completed when the connection to Discord was * successful. * @param dns The DNS instance to use in the OkHttp client. This should only be used in * testing. * @param listenerSourceMap The functions to create listeners for pre-registration. - * @param unspecifiedListeners The listeners of unspecified types to pre-register. + * @param unspecifiedListeners The listeners of unspecified types to pre-register. + * @param userCacheEnabled Whether or not the user cache should be enabled. */ @SuppressWarnings("unchecked") public DiscordApiImpl( @@ -561,7 +562,9 @@ public DiscordApiImpl( Map, List> > listenerSourceMap, - List> unspecifiedListeners) { + List> unspecifiedListeners, + boolean userCacheEnabled + ) { this.accountType = accountType; this.token = token; this.currentShard = currentShard; @@ -575,7 +578,7 @@ public DiscordApiImpl( this.proxyAuthenticator = proxyAuthenticator; this.trustAllCertificates = trustAllCertificates; this.intents = intents; - userCacheEnabled = intents.contains(Intent.GUILD_MEMBERS); + this.userCacheEnabled = userCacheEnabled; this.reconnectDelayProvider = x -> (int) Math.round(Math.pow(x, 1.5) - (1 / (1 / (0.1 * x) + 1)) * Math.pow(x, 1.5)); @@ -940,6 +943,9 @@ public void removeChannelFromCache(long channelId) { * @param member The member to add. */ public void addMemberToCacheOrReplaceExisting(Member member) { + if (!isUserCacheEnabled()) { + return; + } entityCache.getAndUpdate(cache -> { Member oldMember = cache.getMemberCache() .getMemberByIdAndServer(member.getId(), member.getServer().getId()) diff --git a/javacord-core/src/main/java/org/javacord/core/entity/server/ServerImpl.java b/javacord-core/src/main/java/org/javacord/core/entity/server/ServerImpl.java index 29eecf677d..46ef63a371 100644 --- a/javacord-core/src/main/java/org/javacord/core/entity/server/ServerImpl.java +++ b/javacord-core/src/main/java/org/javacord/core/entity/server/ServerImpl.java @@ -420,10 +420,8 @@ && getMembers().size() < getMemberCount() .orElse(null); if (user == null) { - // In theory, every user in "presences" should also be in "members", but Discord is weird - // sometimes. This happens very rarely, but when it happens, we should ignore the presence. + // Ignore rogue presences. // It might be a similar issue than https://github.com/discordapp/discord-api-docs/issues/855 - logger.debug("Found rogue presence. Ignoring it. ({})", presenceJson); continue; }