From c894cf926b3d183b59dac306840c74dbc8308469 Mon Sep 17 00:00:00 2001 From: John Grosh Date: Sat, 28 Apr 2018 01:46:17 -0400 Subject: [PATCH 1/5] allow for null user_id added webhooks to AuditLogEntry --- .../dv8tion/jda/core/audit/AuditLogEntry.java | 20 +++++++++-- .../jda/core/entities/EntityBuilder.java | 33 ++++++++++++------- .../pagination/AuditLogPaginationAction.java | 15 +++++++-- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java b/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java index 625ef02154..56186d9f69 100644 --- a/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java +++ b/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java @@ -27,6 +27,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import net.dv8tion.jda.core.entities.Webhook; +import net.dv8tion.jda.core.entities.impl.WebhookImpl; /** * Single entry for an {@link net.dv8tion.jda.core.requests.restaction.pagination.AuditLogPaginationAction @@ -41,20 +43,22 @@ public class AuditLogEntry implements ISnowflake protected final long targetId; protected final GuildImpl guild; protected final UserImpl user; + protected final WebhookImpl webhook; protected final String reason; protected final Map changes; protected final Map options; protected final ActionType type; - public AuditLogEntry(ActionType type, long id, long targetId, GuildImpl guild, UserImpl user, String reason, - Map changes, Map options) + public AuditLogEntry(ActionType type, long id, long targetId, GuildImpl guild, UserImpl user, WebhookImpl webhook, + String reason, Map changes, Map options) { this.type = type; this.id = id; this.targetId = targetId; this.guild = guild; this.user = user; + this.webhook = webhook; this.reason = reason; this.changes = changes != null && !changes.isEmpty() ? Collections.unmodifiableMap(changes) @@ -93,6 +97,16 @@ public String getTargetId() { return Long.toUnsignedString(targetId); } + + /** + * The {@link net.dv8tion.jda.core.entities.Webhook Webhook} that the target id of this audit-log entry refers to + * + * @return Possibly-null Webhook instance + */ + public Webhook getWebhook() + { + return webhook; + } /** * The {@link net.dv8tion.jda.core.entities.Guild Guild} this audit-log entry refers to @@ -108,7 +122,7 @@ public Guild getGuild() * The {@link net.dv8tion.jda.core.entities.User User} responsible * for this action. * - * @return The User instance + * @return Possibly-null User instance */ public User getUser() { diff --git a/src/main/java/net/dv8tion/jda/core/entities/EntityBuilder.java b/src/main/java/net/dv8tion/jda/core/entities/EntityBuilder.java index 83c59d7369..b305f8e132 100644 --- a/src/main/java/net/dv8tion/jda/core/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/core/entities/EntityBuilder.java @@ -1179,17 +1179,25 @@ public Webhook createWebhook(JSONObject object) .put("avatar", avatar); User defaultUser = createFakeUser(fakeUser, false); - JSONObject ownerJson = object.getJSONObject("user"); - final long userId = ownerJson.getLong("id"); - - User owner = api.getUserById(userId); - if (owner == null) + JSONObject ownerJson = object.optJSONObject("user"); + User owner = null; + + if (ownerJson != null) { - ownerJson.put("id", userId); - owner = createFakeUser(ownerJson, false); - } + final long userId = ownerJson.getLong("id"); - return new WebhookImpl(channel, id).setToken(token).setOwner(channel.getGuild().getMember(owner)).setUser(defaultUser); + owner = api.getUserById(userId); + if (owner == null) + { + ownerJson.put("id", userId); + owner = createFakeUser(ownerJson, false); + } + } + + return new WebhookImpl(channel, id) + .setToken(token) + .setOwner(owner==null ? null : channel.getGuild().getMember(owner)) + .setUser(defaultUser); } public Relationship createRelationship(JSONObject relationshipJson) @@ -1366,7 +1374,7 @@ public AuthorizedApplication createAuthorizedApplication(JSONObject object) return new AuthorizedApplicationImpl(api, authId, description, iconId, id, name, scopes); } - public AuditLogEntry createAuditLogEntry(GuildImpl guild, JSONObject entryJson, JSONObject userJson) + public AuditLogEntry createAuditLogEntry(GuildImpl guild, JSONObject entryJson, JSONObject userJson, JSONObject webhookJson) { final long targetId = Helpers.optLong(entryJson, "target_id", 0); final long id = entryJson.getLong("id"); @@ -1375,7 +1383,8 @@ public AuditLogEntry createAuditLogEntry(GuildImpl guild, JSONObject entryJson, final JSONObject options = entryJson.isNull("options") ? null : entryJson.getJSONObject("options"); final String reason = entryJson.optString("reason", null); - final UserImpl user = (UserImpl) createFakeUser(userJson, false); + final UserImpl user = userJson == null ? null : (UserImpl) createFakeUser(userJson, false); + final WebhookImpl webhook = webhookJson == null ? null : (WebhookImpl) createWebhook(webhookJson); final Set changesList; final ActionType type = ActionType.from(typeKey); @@ -1398,7 +1407,7 @@ public AuditLogEntry createAuditLogEntry(GuildImpl guild, JSONObject entryJson, CaseInsensitiveMap optionMap = options != null ? new CaseInsensitiveMap<>(options.toMap()) : null; - return new AuditLogEntry(type, id, targetId, guild, user, reason, changeMap, optionMap); + return new AuditLogEntry(type, id, targetId, guild, user, webhook, reason, changeMap, optionMap); } public AuditLogChange createAuditLogChange(JSONObject change) diff --git a/src/main/java/net/dv8tion/jda/core/requests/restaction/pagination/AuditLogPaginationAction.java b/src/main/java/net/dv8tion/jda/core/requests/restaction/pagination/AuditLogPaginationAction.java index dc686762d0..ac84be9e6f 100644 --- a/src/main/java/net/dv8tion/jda/core/requests/restaction/pagination/AuditLogPaginationAction.java +++ b/src/main/java/net/dv8tion/jda/core/requests/restaction/pagination/AuditLogPaginationAction.java @@ -35,6 +35,7 @@ import java.util.ArrayList; import java.util.List; +import net.dv8tion.jda.core.utils.Helpers; /** * {@link net.dv8tion.jda.core.requests.restaction.pagination.PaginationAction PaginationAction} @@ -193,6 +194,7 @@ protected void handleResponse(Response response, Request> re JSONObject obj = response.getObject(); JSONArray users = obj.getJSONArray("users"); + JSONArray webhooks = obj.getJSONArray("webhooks"); JSONArray entries = obj.getJSONArray("audit_log_entries"); List list = new ArrayList<>(entries.length()); @@ -204,13 +206,22 @@ protected void handleResponse(Response response, Request> re JSONObject user = users.getJSONObject(i); userMap.put(user.getLong("id"), user); } + + TLongObjectMap webhookMap = new TLongObjectHashMap<>(); + for (int i = 0; i < webhooks.length(); i++) + { + JSONObject webhook = webhooks.getJSONObject(i); + webhookMap.put(webhook.getLong("id"), webhook); + } + for (int i = 0; i < entries.length(); i++) { try { JSONObject entry = entries.getJSONObject(i); - JSONObject user = userMap.get(entry.getLong("user_id")); - AuditLogEntry result = builder.createAuditLogEntry((GuildImpl) guild, entry, user); + JSONObject user = userMap.get(Helpers.optLong(entry, "user_id", 0)); + JSONObject webhook = webhookMap.get(Helpers.optLong(entry, "target_id", 0)); + AuditLogEntry result = builder.createAuditLogEntry((GuildImpl) guild, entry, user, webhook); list.add(result); if (this.useCache) this.cached.add(result); From f8cd02ca5461bc2fc2fad595ce32fa13a1b076db Mon Sep 17 00:00:00 2001 From: John Grosh Date: Sat, 28 Apr 2018 01:55:14 -0400 Subject: [PATCH 2/5] Added IllegalStateException when trying to use newClient() on a Webhook with no token --- .../java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java b/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java index f17334ca62..f40841ead0 100644 --- a/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java +++ b/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java @@ -155,6 +155,9 @@ public net.dv8tion.jda.core.managers.WebhookManagerUpdatable getManagerUpdatable @Override public WebhookClientBuilder newClient() { + if (token == null) + throw new IllegalStateException("Webhooks without known tokens (such as those retrieved from Audit Logs) " + + "cannot be used to create a WebhookClient!"); return new WebhookClientBuilder(id, token); } From e09cde185f9419f69044664e83207f37e622e7c1 Mon Sep 17 00:00:00 2001 From: John Grosh Date: Sat, 28 Apr 2018 05:54:48 -0400 Subject: [PATCH 3/5] fixed formatting modified some return types added documentation for Webhook#newClient() --- .../net/dv8tion/jda/core/audit/AuditLogEntry.java | 5 +++-- .../dv8tion/jda/core/entities/EntityBuilder.java | 14 +++++++------- .../net/dv8tion/jda/core/entities/Webhook.java | 3 +++ .../pagination/AuditLogPaginationAction.java | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java b/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java index 56186d9f69..116689d5f2 100644 --- a/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java +++ b/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java @@ -20,15 +20,16 @@ import net.dv8tion.jda.core.entities.Guild; import net.dv8tion.jda.core.entities.ISnowflake; import net.dv8tion.jda.core.entities.User; +import net.dv8tion.jda.core.entities.Webhook; import net.dv8tion.jda.core.entities.impl.GuildImpl; import net.dv8tion.jda.core.entities.impl.UserImpl; +import net.dv8tion.jda.core.entities.impl.WebhookImpl; import net.dv8tion.jda.core.utils.Checks; + import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import net.dv8tion.jda.core.entities.Webhook; -import net.dv8tion.jda.core.entities.impl.WebhookImpl; /** * Single entry for an {@link net.dv8tion.jda.core.requests.restaction.pagination.AuditLogPaginationAction diff --git a/src/main/java/net/dv8tion/jda/core/entities/EntityBuilder.java b/src/main/java/net/dv8tion/jda/core/entities/EntityBuilder.java index b305f8e132..0285d77aa4 100644 --- a/src/main/java/net/dv8tion/jda/core/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/core/entities/EntityBuilder.java @@ -485,9 +485,9 @@ public void createGuildVoiceStatePass(GuildImpl guildObj, JSONArray voiceStates) } } - public User createFakeUser(JSONObject user, boolean modifyCache) { return createUser(user, true, modifyCache); } - public User createUser(JSONObject user) { return createUser(user, false, true); } - private User createUser(JSONObject user, boolean fake, boolean modifyCache) + public UserImpl createFakeUser(JSONObject user, boolean modifyCache) { return createUser(user, true, modifyCache); } + public UserImpl createUser(JSONObject user) { return createUser(user, false, true); } + private UserImpl createUser(JSONObject user, boolean fake, boolean modifyCache) { final long id = user.getLong("id"); UserImpl userObj; @@ -1157,7 +1157,7 @@ public PermissionOverride createPermissionOverride(JSONObject override, Channel return permOverride.setAllow(allow).setDeny(deny); } - public Webhook createWebhook(JSONObject object) + public WebhookImpl createWebhook(JSONObject object) { final long id = object.getLong("id"); final long guildId = object.getLong("guild_id"); @@ -1196,7 +1196,7 @@ public Webhook createWebhook(JSONObject object) return new WebhookImpl(channel, id) .setToken(token) - .setOwner(owner==null ? null : channel.getGuild().getMember(owner)) + .setOwner(owner == null ? null : channel.getGuild().getMember(owner)) .setUser(defaultUser); } @@ -1383,8 +1383,8 @@ public AuditLogEntry createAuditLogEntry(GuildImpl guild, JSONObject entryJson, final JSONObject options = entryJson.isNull("options") ? null : entryJson.getJSONObject("options"); final String reason = entryJson.optString("reason", null); - final UserImpl user = userJson == null ? null : (UserImpl) createFakeUser(userJson, false); - final WebhookImpl webhook = webhookJson == null ? null : (WebhookImpl) createWebhook(webhookJson); + final UserImpl user = userJson == null ? null : createFakeUser(userJson, false); + final WebhookImpl webhook = webhookJson == null ? null : createWebhook(webhookJson); final Set changesList; final ActionType type = ActionType.from(typeKey); diff --git a/src/main/java/net/dv8tion/jda/core/entities/Webhook.java b/src/main/java/net/dv8tion/jda/core/entities/Webhook.java index ba41052007..d2d2d428e1 100644 --- a/src/main/java/net/dv8tion/jda/core/entities/Webhook.java +++ b/src/main/java/net/dv8tion/jda/core/entities/Webhook.java @@ -160,6 +160,9 @@ public interface Webhook extends ISnowflake * *

Remember to close the WebhookClient once you don't need it anymore to free resources! * + * @throws IllegalStateException + * if the Webhook does not have a known token, such as the Webhooks retrieved from Audit Logs + * * @return The new WebhookClientBuilder */ WebhookClientBuilder newClient(); diff --git a/src/main/java/net/dv8tion/jda/core/requests/restaction/pagination/AuditLogPaginationAction.java b/src/main/java/net/dv8tion/jda/core/requests/restaction/pagination/AuditLogPaginationAction.java index ac84be9e6f..aa4d01c61e 100644 --- a/src/main/java/net/dv8tion/jda/core/requests/restaction/pagination/AuditLogPaginationAction.java +++ b/src/main/java/net/dv8tion/jda/core/requests/restaction/pagination/AuditLogPaginationAction.java @@ -29,13 +29,13 @@ import net.dv8tion.jda.core.requests.Request; import net.dv8tion.jda.core.requests.Response; import net.dv8tion.jda.core.requests.Route; +import net.dv8tion.jda.core.utils.Helpers; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; -import net.dv8tion.jda.core.utils.Helpers; /** * {@link net.dv8tion.jda.core.requests.restaction.pagination.PaginationAction PaginationAction} From cf2695478e3abf3da5fb886b0798da430390b440 Mon Sep 17 00:00:00 2001 From: John Grosh Date: Sun, 29 Apr 2018 13:59:35 -0400 Subject: [PATCH 4/5] added @Nullable annotations added more docs modified getURL() method to account for lack of token --- .../net/dv8tion/jda/core/audit/AuditLogEntry.java | 8 ++++++++ .../net/dv8tion/jda/core/entities/Webhook.java | 14 ++++++++++---- .../jda/core/entities/impl/WebhookImpl.java | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java b/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java index 116689d5f2..d6321b646e 100644 --- a/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java +++ b/src/main/java/net/dv8tion/jda/core/audit/AuditLogEntry.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; /** * Single entry for an {@link net.dv8tion.jda.core.requests.restaction.pagination.AuditLogPaginationAction @@ -104,6 +105,7 @@ public String getTargetId() * * @return Possibly-null Webhook instance */ + @Nullable public Webhook getWebhook() { return webhook; @@ -125,6 +127,7 @@ public Guild getGuild() * * @return Possibly-null User instance */ + @Nullable public User getUser() { return user; @@ -135,6 +138,7 @@ public User getUser() * * @return Possibly-null reason String */ + @Nullable public String getReason() { return reason; @@ -172,6 +176,7 @@ public Map getChanges() * * @return Possibly-null value corresponding to the specified key */ + @Nullable public AuditLogChange getChangeByKey(final AuditLogKey key) { return key == null ? null : getChangeByKey(key.getKey()); @@ -186,6 +191,7 @@ public AuditLogChange getChangeByKey(final AuditLogKey key) * * @return Possibly-null value corresponding to the specified key */ + @Nullable public AuditLogChange getChangeByKey(final String key) { return changes.get(key); @@ -246,6 +252,7 @@ public Map getOptions() * * @return Possibly-null value corresponding to the specified key */ + @Nullable @SuppressWarnings("unchecked") public T getOptionByName(String name) { @@ -267,6 +274,7 @@ public T getOptionByName(String name) * * @return Possibly-null value corresponding to the specified option constant */ + @Nullable public T getOption(AuditLogOption option) { Checks.notNull(option, "Option"); diff --git a/src/main/java/net/dv8tion/jda/core/entities/Webhook.java b/src/main/java/net/dv8tion/jda/core/entities/Webhook.java index d2d2d428e1..62690a4de7 100644 --- a/src/main/java/net/dv8tion/jda/core/entities/Webhook.java +++ b/src/main/java/net/dv8tion/jda/core/entities/Webhook.java @@ -23,6 +23,7 @@ import net.dv8tion.jda.webhook.WebhookClientBuilder; import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; /** * An object representing Webhooks in Discord @@ -57,11 +58,12 @@ public interface Webhook extends ISnowflake TextChannel getChannel(); /** - * The owner of this Webhook. + * The owner of this Webhook. This will be null for partial Webhooks, such as those retrieved from Audit Logs. * - * @return A {@link net.dv8tion.jda.core.entities.Member Member} instance - * representing the owner of this Webhook + * @return Possibly-null {@link net.dv8tion.jda.core.entities.Member Member} instance + * representing the owner of this Webhook. */ + @Nullable Member getOwner(); /** @@ -96,15 +98,19 @@ public interface Webhook extends ISnowflake * The execute token for this Webhook. *
This can be used to modify/delete/execute * this Webhook. + * + *

Note: Webhooks retrieved from Audit Logs do not contain a token * * @return The execute token for this Webhook */ + @Nullable String getToken(); /** * The {@code POST} route for this Webhook. *
This contains the {@link #getToken() token} and {@link #getId() id} - * of this Webhook. + * of this Webhook. Webhooks without tokens (such as those retrieved from Audit Logs) + * will return a URL without a token. * *

The route returned by this method does not need permission checks * to be executed. diff --git a/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java b/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java index f40841ead0..5a31aba9d8 100644 --- a/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java +++ b/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java @@ -99,7 +99,7 @@ public String getToken() @Override public String getUrl() { - return Requester.DISCORD_API_PREFIX + "webhooks/" + getId() + "/" + getToken(); + return Requester.DISCORD_API_PREFIX + "webhooks/" + getId() + (getToken() == null ? "" : "/" + getToken()); } @Override From e98ceb59e92bda17d2a326458daa454ec8bf21cc Mon Sep 17 00:00:00 2001 From: John Grosh Date: Tue, 8 May 2018 18:03:04 -0400 Subject: [PATCH 5/5] improved docs, made Webhook extend IFakeable, and added more exceptions --- .../net/dv8tion/jda/core/entities/Webhook.java | 16 +++++++++++----- .../jda/core/entities/impl/WebhookImpl.java | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/core/entities/Webhook.java b/src/main/java/net/dv8tion/jda/core/entities/Webhook.java index 62690a4de7..c61ace308c 100644 --- a/src/main/java/net/dv8tion/jda/core/entities/Webhook.java +++ b/src/main/java/net/dv8tion/jda/core/entities/Webhook.java @@ -30,7 +30,7 @@ * * @since 3.0 */ -public interface Webhook extends ISnowflake +public interface Webhook extends ISnowflake, IFakeable { /** @@ -58,7 +58,7 @@ public interface Webhook extends ISnowflake TextChannel getChannel(); /** - * The owner of this Webhook. This will be null for partial Webhooks, such as those retrieved from Audit Logs. + * The owner of this Webhook. This will be null for fake Webhooks, such as those retrieved from Audit Logs. * * @return Possibly-null {@link net.dv8tion.jda.core.entities.Member Member} instance * representing the owner of this Webhook. @@ -99,7 +99,7 @@ public interface Webhook extends ISnowflake *
This can be used to modify/delete/execute * this Webhook. * - *

Note: Webhooks retrieved from Audit Logs do not contain a token + *

Note: Fake Webhooks, such as those retrieved from Audit Logs, do not contain a token * * @return The execute token for this Webhook */ @@ -109,7 +109,7 @@ public interface Webhook extends ISnowflake /** * The {@code POST} route for this Webhook. *
This contains the {@link #getToken() token} and {@link #getId() id} - * of this Webhook. Webhooks without tokens (such as those retrieved from Audit Logs) + * of this Webhook. Fake Webhooks without tokens (such as those retrieved from Audit Logs) * will return a URL without a token. * *

The route returned by this method does not need permission checks @@ -128,6 +128,9 @@ public interface Webhook extends ISnowflake /** * Deletes this Webhook. * + * @throws IllegalStateException + * if the Webhook is fake, such as the Webhooks retrieved from Audit Logs + * * @return {@link net.dv8tion.jda.core.requests.restaction.AuditableRestAction AuditableRestAction} *
The rest action to delete this Webhook. */ @@ -141,6 +144,9 @@ public interface Webhook extends ISnowflake * @throws net.dv8tion.jda.core.exceptions.InsufficientPermissionException * If the currently logged in account does not have {@link net.dv8tion.jda.core.Permission#MANAGE_WEBHOOKS Permission.MANAGE_WEBHOOKS} * + * @throws IllegalStateException + * if the Webhook is fake, such as the Webhooks retrieved from Audit Logs + * * @return The {@link net.dv8tion.jda.core.managers.WebhookManager WebhookManager} for this Webhook */ WebhookManager getManager(); @@ -167,7 +173,7 @@ public interface Webhook extends ISnowflake *

Remember to close the WebhookClient once you don't need it anymore to free resources! * * @throws IllegalStateException - * if the Webhook does not have a known token, such as the Webhooks retrieved from Audit Logs + * if the Webhook is fake, such as the Webhooks retrieved from Audit Logs * * @return The new WebhookClientBuilder */ diff --git a/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java b/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java index 5a31aba9d8..1dab1cc7ed 100644 --- a/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java +++ b/src/main/java/net/dv8tion/jda/core/entities/impl/WebhookImpl.java @@ -105,6 +105,9 @@ public String getUrl() @Override public AuditableRestAction delete() { + if (isFake()) + throw new IllegalStateException("Fake Webhooks (such as those retrieved from Audit Logs) " + + "cannot be used for deletion!"); Route.CompiledRoute route = Route.Webhooks.DELETE_TOKEN_WEBHOOK.compile(getId(), token); return new AuditableRestAction(getJDA(), route) { @@ -122,6 +125,9 @@ protected void handleResponse(Response response, Request request) @Override public WebhookManager getManager() { + if (isFake()) + throw new IllegalStateException("Fake Webhooks (such as those retrieved from Audit Logs) " + + "cannot provide a WebhookManager!"); WebhookManager mng = manager; if (mng == null) { @@ -155,8 +161,8 @@ public net.dv8tion.jda.core.managers.WebhookManagerUpdatable getManagerUpdatable @Override public WebhookClientBuilder newClient() { - if (token == null) - throw new IllegalStateException("Webhooks without known tokens (such as those retrieved from Audit Logs) " + if (isFake()) + throw new IllegalStateException("Fake Webhooks (such as those retrieved from Audit Logs) " + "cannot be used to create a WebhookClient!"); return new WebhookClientBuilder(id, token); } @@ -167,6 +173,12 @@ public long getIdLong() return id; } + @Override + public boolean isFake() + { + return token == null; + } + /* -- Impl Setters -- */ public WebhookImpl setOwner(Member member)