diff --git a/src/main/java/net/dv8tion/jda/api/entities/Widget.java b/src/main/java/net/dv8tion/jda/api/entities/Widget.java new file mode 100644 index 0000000000..0d90d85a16 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/Widget.java @@ -0,0 +1,450 @@ +/* + * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.dv8tion.jda.api.entities; + +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.dv8tion.jda.api.OnlineStatus; +import net.dv8tion.jda.api.utils.ImageProxy; +import net.dv8tion.jda.api.utils.WidgetUtil; + +/** + * Represents a guild's widget + * + * @see WidgetUtil#getWidget(long) + * @see WidgetUtil#getWidget(String) + */ +public interface Widget extends ISnowflake +{ + + /** + * Shows whether or not the widget for a guild is available. If this + * method returns false, all other values will be null + * + * @return True, if the widget is available, false otherwise + */ + boolean isAvailable(); + + /** + * Gets the name of the guild + * + * @throws IllegalStateException + * If the widget is not {@link #isAvailable() available} + * + * @return the name of the guild + */ + @Nonnull + String getName(); + + /** + * Gets an invite code for the guild, or null if no invite channel is + * enabled in the widget + * + * @throws IllegalStateException + * If the widget is not {@link #isAvailable() available} + * + * @return an invite code for the guild, if widget invites are enabled + */ + @Nullable + String getInviteCode(); + + /** + * Gets the list of voice channels in the guild + * + * @throws IllegalStateException + * If the widget is not {@link #isAvailable() available} + * + * @return the list of voice channels in the guild + */ + @Nonnull + List getVoiceChannels(); + + /** + * Gets a voice channel with the given ID, or null if the voice channel is not found + * + * @param id + * the ID of the voice channel + * + * @throws IllegalStateException + * If the widget is not {@link #isAvailable() available} + * @throws NumberFormatException + * If the provided {@code id} cannot be parsed by {@link Long#parseLong(String)} + * + * @return possibly-null VoiceChannel with the given ID. + */ + @Nullable + VoiceChannel getVoiceChannelById(String id); + + /** + * Gets a voice channel with the given ID, or {@code null} if the voice channel is not found + * + * @param id + * the ID of the voice channel + * + * @throws IllegalStateException + * If the widget is not {@link #isAvailable() available} + * + * @return possibly-null VoiceChannel with the given ID. + */ + @Nullable + VoiceChannel getVoiceChannelById(long id); + + /** + * Gets a list of online members in the guild + * + * @throws IllegalStateException + * If the widget is not {@link #isAvailable() available} + * + * @return the list of members + */ + @Nonnull + List getMembers(); + + /** + * Gets a member with the given ID, or null if the member is not found + * + * @param id + * the ID of the member + * + * @throws NumberFormatException + * If the provided {@code id} cannot be parsed by {@link Long#parseLong(String)} + * @throws IllegalStateException + * If the widget is not {@link #isAvailable() available} + * + * @return possibly-null Member with the given ID. + */ + @Nullable + Member getMemberById(String id); + + /** + * Gets a member with the given ID, or {@code null} if the member is not found + * + * @param id + * the ID of the member + * + * @throws IllegalStateException + * If the widget is not {@link #isAvailable() available} + * + * @return possibly-null Member with the given ID. + */ + @Nullable + Member getMemberById(long id); + + /** + * Represents a member of a guild + * + * @see Widget#getMembers() + * @see Widget#getMemberById(long) + * @see Widget#getMemberById(String) + * @see VoiceChannel#getMembers() + */ + public interface Member extends IMentionable + { + + /** + * Returns whether or not the given member is a bot account + * + * @return true if the member is a bot, false otherwise + */ + boolean isBot(); + + /** + * Returns the username of the member + * + * @return the username of the member + */ + @Nonnull + String getName(); + + /** + * Gets the discriminator of the member + * + * @return the never-null discriminator of the member + */ + @Nonnull + String getDiscriminator(); + + /** + * Gets the avatar hash of the member, or null if they do not have + * an avatar set. + * + * @return possibly-null String containing the avatar hash of the + * member + */ + @Nullable + String getAvatarId(); + + /** + * Gets the avatar url of the member, or null if they do not have + * an avatar set. + * + * @return possibly-null String containing the avatar url of the + * member + */ + @Nullable + String getAvatarUrl(); + + /** + * Returns an {@link ImageProxy} for this user's avatar image. + * + * @return Possibly-null {@link ImageProxy} of this user's avatar image + * + * @see #getAvatarUrl() + */ + @Nullable + ImageProxy getAvatar(); + + /** + * Gets the asset id of the member's default avatar + * + * @return never-null String containing the asset id of the member's + * default avatar + */ + @Nonnull + String getDefaultAvatarId(); + + /** + * Gets the url of the member's default avatar + * + * @return never-null String containing the url of the member's + * default avatar + */ + @Nonnull + String getDefaultAvatarUrl(); + + /** + * Returns an {@link ImageProxy} for this user's default avatar image. + * + * @return Never-null {@link ImageProxy} of this user's default avatar image + * + * @see #getDefaultAvatarUrl() + */ + @Nonnull + ImageProxy getDefaultAvatar(); + + /** + * The URL for the user's avatar image + *
If they do not have an avatar set, this will return the URL of their + * default avatar + * + * @return Never-null String containing the member's effective avatar url. + */ + @Nonnull + String getEffectiveAvatarUrl(); + + /** + * Returns an {@link ImageProxy} for this user's effective avatar image. + * + * @return Never-null {@link ImageProxy} of this user's effective avatar image + * + * @see #getEffectiveAvatarUrl() + */ + @Nonnull + ImageProxy getEffectiveAvatar(); + + /** + * Gets the nickname of the member. If they do not have a nickname on + * the guild, this will return null; + * + * @return possibly-null String containing the nickname of the member + */ + @Nullable + String getNickname(); + + /** + * Gets the visible name of the member. If they have a nickname set, + * this will be their nickname. Otherwise, it will be their username. + * + * @return never-null String containing the member's effective (visible) name + */ + @Nonnull + String getEffectiveName(); + + /** + * Gets the online status of the member. The widget does not show + * offline members, so this status should never be offline + * + * @return the {@link net.dv8tion.jda.api.OnlineStatus OnlineStatus} of the member + */ + @Nonnull + OnlineStatus getOnlineStatus(); + + /** + * The game that the member is currently playing. + *
This game cannot be a stream. + * If the user is not currently playing a game, this will return null. + * + * @return Possibly-null {@link net.dv8tion.jda.api.entities.Activity Activity} containing the game + * that the member is currently playing. + */ + @Nullable + Activity getActivity(); + + /** + * The current voice state of the member. + *
If the user is not in voice, this will return a VoiceState with a null channel. + * + * @return never-null VoiceState of the member + */ + @Nonnull + VoiceState getVoiceState(); + + /** + * Gets the widget that to which this member belongs + * + * @return the Widget that holds this member + */ + @Nonnull + Widget getWidget(); + + } + + /** + * Represents a voice channel + * + * @see Widget#getVoiceChannels() + * @see Widget#getVoiceChannelById(long) + * @see Widget#getVoiceChannelById(String) + */ + public interface VoiceChannel extends ISnowflake + { + + /** + * Gets the integer position of the channel + * + * @return integer position of the channel + */ + int getPosition(); + + /** + * Gets the name of the channel * + * @return name of the channel + */ + @Nonnull + String getName(); + + /** + * Gets a list of all members in the channel + * + * @return never-null, possibly-empty list of members in the channel + */ + @Nonnull + List getMembers(); + + /** + * Gets the Widget to which this voice channel belongs + * + * @return the Widget object that holds this voice channel + */ + @Nonnull + Widget getWidget(); + } + + /** + * Represents a {@link net.dv8tion.jda.api.entities.Widget.Member Member's} voice state + * + * @see Member#getVoiceState() + */ + public interface VoiceState + { + + /** + * Gets the channel the member is in + * + * @return never-null VoiceChannel + */ + @Nullable + VoiceChannel getChannel(); + + /** + * Used to determine if the member is currently in a voice channel. + *
If this is false, getChannel() will return null + * + * @return True, if the member is in a voice channel + */ + boolean inVoiceChannel(); + + /** + * Whether the member is muted by an admin + * + * @return True, if the member is muted + */ + boolean isGuildMuted(); + + /** + * Whether the member is deafened by an admin + * + * @return True, if the member is deafened + */ + boolean isGuildDeafened(); + + /** + * Whether the member is suppressed + * + * @return True, if the member is suppressed + */ + boolean isSuppressed(); + + /** + * Whether the member is self-muted + * + * @return True, if the member is self-muted + */ + boolean isSelfMuted(); + + /** + * Whether the member is self-deafened + * + * @return True, if the member is self-deafened + */ + boolean isSelfDeafened(); + + /** + * Whether the member is muted, either by an admin or self-muted + * + * @return True, if the member is self-muted or guild-muted + */ + boolean isMuted(); + + /** + * Whether the member is deafened, either by an admin or self-deafened + * + * @return True, if the member is self-deafened or guild-deafened + */ + boolean isDeafened(); + + /** + * Gets the {@link net.dv8tion.jda.api.entities.Widget.Member Member} to which this + * VoiceState belongs + * + * @return the member + */ + @Nonnull + Member getMember(); + + /** + * Gets the {@link net.dv8tion.jda.api.entities.Widget Widget} to which the + * {@link net.dv8tion.jda.api.entities.Widget.Member Member} of this VoiceState belongs + * + * @return the widget + */ + @Nonnull + Widget getWidget(); + } +} \ No newline at end of file diff --git a/src/main/java/net/dv8tion/jda/api/utils/WidgetUtil.java b/src/main/java/net/dv8tion/jda/api/utils/WidgetUtil.java index cb6a4845a4..8750570522 100644 --- a/src/main/java/net/dv8tion/jda/api/utils/WidgetUtil.java +++ b/src/main/java/net/dv8tion/jda/api/utils/WidgetUtil.java @@ -15,33 +15,27 @@ */ package net.dv8tion.jda.api.utils; -import gnu.trove.map.TLongObjectMap; -import gnu.trove.map.hash.TLongObjectHashMap; -import net.dv8tion.jda.api.OnlineStatus; -import net.dv8tion.jda.api.entities.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.HttpURLConnection; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Widget; import net.dv8tion.jda.api.exceptions.RateLimitedException; -import net.dv8tion.jda.api.utils.data.DataArray; import net.dv8tion.jda.api.utils.data.DataObject; -import net.dv8tion.jda.internal.entities.EntityBuilder; +import net.dv8tion.jda.internal.entities.WidgetImpl; import net.dv8tion.jda.internal.requests.Requester; import net.dv8tion.jda.internal.utils.Checks; -import net.dv8tion.jda.internal.utils.EntityString; import net.dv8tion.jda.internal.utils.Helpers; import net.dv8tion.jda.internal.utils.IOUtil; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.net.HttpURLConnection; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - /** * The WidgetUtil is a class for interacting with various facets of Discord's * guild widgets @@ -226,7 +220,7 @@ public static Widget getWidget(long guildId) throws RateLimitedException { try (InputStream stream = data) { - return new Widget(DataObject.fromJson(stream)); + return new WidgetImpl(DataObject.fromJson(stream)); } catch (IOException e) { @@ -237,7 +231,7 @@ public static Widget getWidget(long guildId) throws RateLimitedException case 404: // guild not found return null; case 403: // widget disabled - return new Widget(guildId); + return new WidgetImpl(guildId); case 429: // ratelimited { long retryAfter; @@ -260,7 +254,7 @@ public static Widget getWidget(long guildId) throws RateLimitedException throw new UncheckedIOException(e); } } - + /** * Represents the available banner types *
Each of these has a different appearance: @@ -276,7 +270,7 @@ public enum BannerType { SHIELD, BANNER1, BANNER2, BANNER3, BANNER4 } - + /** * Represents the color scheme of the widget *
These color themes match Discord's dark and light themes @@ -285,788 +279,4 @@ public enum WidgetTheme { LIGHT, DARK } - - public static class Widget implements ISnowflake - { - private final boolean isAvailable; - private final long id; - private final String name; - private final String invite; - private final TLongObjectMap channels; - private final TLongObjectMap members; - - /** - * Constructs an unavailable Widget - */ - private Widget(long guildId) - { - isAvailable = false; - id = guildId; - name = null; - invite = null; - channels = new TLongObjectHashMap<>(); - members = new TLongObjectHashMap<>(); - } - - /** - * Constructs an available Widget - * - * @param json - * The {@link net.dv8tion.jda.api.utils.data.DataObject DataObject} to construct the Widget from - */ - private Widget(@Nonnull DataObject json) - { - String inviteCode = json.getString("instant_invite", null); - if (inviteCode != null) - inviteCode = inviteCode.substring(inviteCode.lastIndexOf("/") + 1); - - isAvailable = true; - id = json.getLong("id"); - name = json.getString("name"); - invite = inviteCode; - channels = MiscUtil.newLongMap(); - members = MiscUtil.newLongMap(); - - DataArray channelsJson = json.getArray("channels"); - for (int i = 0; i < channelsJson.length(); i++) - { - DataObject channel = channelsJson.getObject(i); - channels.put(channel.getLong("id"), new VoiceChannel(channel, this)); - } - - DataArray membersJson = json.getArray("members"); - for (int i = 0; i getVoiceChannels() - { - checkAvailable(); - - return Collections.unmodifiableList(new ArrayList<>(channels.valueCollection())); - } - - /** - * Gets a voice channel with the given ID, or null if the voice channel is not found - * - * @param id - * the ID of the voice channel - * - * @throws IllegalStateException - * If the widget is not {@link #isAvailable() available} - * @throws NumberFormatException - * If the provided {@code id} cannot be parsed by {@link Long#parseLong(String)} - * - * @return possibly-null VoiceChannel with the given ID. - */ - @Nullable - public VoiceChannel getVoiceChannelById(String id) - { - checkAvailable(); - - return channels.get(MiscUtil.parseSnowflake(id)); - } - - /** - * Gets a voice channel with the given ID, or {@code null} if the voice channel is not found - * - * @param id - * the ID of the voice channel - * - * @throws IllegalStateException - * If the widget is not {@link #isAvailable() available} - * - * @return possibly-null VoiceChannel with the given ID. - */ - @Nullable - public VoiceChannel getVoiceChannelById(long id) - { - checkAvailable(); - - return channels.get(id); - } - - /** - * Gets a list of online members in the guild - * - * @throws IllegalStateException - * If the widget is not {@link #isAvailable() available} - * - * @return the list of members - */ - @Nonnull - public List getMembers() - { - checkAvailable(); - - return Collections.unmodifiableList(new ArrayList<>(members.valueCollection())); - } - - /** - * Gets a member with the given ID, or null if the member is not found - * - * @param id - * the ID of the member - * - * @throws NumberFormatException - * If the provided {@code id} cannot be parsed by {@link Long#parseLong(String)} - * @throws IllegalStateException - * If the widget is not {@link #isAvailable() available} - * - * @return possibly-null Member with the given ID. - */ - @Nullable - public Member getMemberById(String id) - { - checkAvailable(); - - return members.get(MiscUtil.parseSnowflake(id)); - } - - /** - * Gets a member with the given ID, or {@code null} if the member is not found - * - * @param id - * the ID of the member - * - * @throws IllegalStateException - * If the widget is not {@link #isAvailable() available} - * - * @return possibly-null Member with the given ID. - */ - @Nullable - public Member getMemberById(long id) - { - checkAvailable(); - - return members.get(id); - } - - @Override - public int hashCode() { - return Long.hashCode(id); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Widget)) - return false; - Widget oWidget = (Widget) obj; - return this == oWidget || this.id == oWidget.getIdLong(); - } - - @Override - public String toString() - { - final EntityString entityString = new EntityString("Widget"); - if (isAvailable()) - entityString.setName(getName()); - return entityString.toString(); - } - - private void checkAvailable() - { - if (!isAvailable) - throw new IllegalStateException("The widget for this Guild is unavailable!"); - } - - public static class Member implements IMentionable - { - private final boolean bot; - private final long id; - private final String username; - private final String discriminator; - private final String avatar; - private final String nickname; - private final OnlineStatus status; - private final Activity game; - private final Widget widget; - private VoiceState state; - - private Member(@Nonnull DataObject json, @Nonnull Widget widget) - { - this.widget = widget; - this.bot = json.getBoolean("bot"); - this.id = json.getLong("id"); - this.username = json.getString("username"); - this.discriminator = json.getString("discriminator"); - this.avatar = json.getString("avatar", null); - this.nickname = json.getString("nick", null); - this.status = OnlineStatus.fromKey(json.getString("status")); - this.game = json.isNull("game") ? null : EntityBuilder.createActivity(json.getObject("game")); - } - - private void setVoiceState(VoiceState voiceState) - { - state = voiceState; - } - - /** - * Returns whether or not the given member is a bot account - * - * @return true if the member is a bot, false otherwise - */ - public boolean isBot() - { - return bot; - } - - /** - * Returns the username of the member - * - * @return the username of the member - */ - @Nonnull - public String getName() - { - return username; - } - - @Override - public long getIdLong() - { - return id; - } - - @Nonnull - @Override - public String getAsMention() - { - return "<@" + getId() + ">"; - } - - /** - * Gets the discriminator of the member - * - * @return the never-null discriminator of the member - */ - @Nonnull - public String getDiscriminator() - { - return discriminator; - } - - /** - * Gets the avatar hash of the member, or null if they do not have - * an avatar set. - * - * @return possibly-null String containing the avatar hash of the - * member - */ - @Nullable - public String getAvatarId() - { - return avatar; - } - - /** - * Gets the avatar url of the member, or null if they do not have - * an avatar set. - * - * @return possibly-null String containing the avatar url of the - * member - */ - @Nullable - public String getAvatarUrl() - { - String avatarId = getAvatarId(); - return avatarId == null ? null : String.format(User.AVATAR_URL, getId(), avatarId, avatarId.startsWith("a_") ? ".gif" : ".png"); - } - - /** - * Returns an {@link ImageProxy} for this user's avatar image. - * - * @return Possibly-null {@link ImageProxy} of this user's avatar image - * - * @see #getAvatarUrl() - */ - @Nullable - public ImageProxy getAvatar() - { - final String avatarUrl = getAvatarUrl(); - return avatarUrl == null ? null : new ImageProxy(avatarUrl); - } - - /** - * Gets the asset id of the member's default avatar - * - * @return never-null String containing the asset id of the member's - * default avatar - */ - @Nonnull - public String getDefaultAvatarId() - { - return String.valueOf(Integer.parseInt(getDiscriminator()) % 5); - } - - /** - * Gets the url of the member's default avatar - * - * @return never-null String containing the url of the member's - * default avatar - */ - @Nonnull - public String getDefaultAvatarUrl() - { - return String.format(User.DEFAULT_AVATAR_URL, getDefaultAvatarId()); - } - - /** - * Returns an {@link ImageProxy} for this user's default avatar image. - * - * @return Never-null {@link ImageProxy} of this user's default avatar image - * - * @see #getDefaultAvatarUrl() - */ - @Nonnull - public ImageProxy getDefaultAvatar() - { - return new ImageProxy(getDefaultAvatarUrl()); - } - - /** - * The URL for the user's avatar image - *
If they do not have an avatar set, this will return the URL of their - * default avatar - * - * @return Never-null String containing the member's effective avatar url. - */ - @Nonnull - public String getEffectiveAvatarUrl() - { - String avatarUrl = getAvatarUrl(); - return avatarUrl == null ? getDefaultAvatarUrl() : avatarUrl; - } - - /** - * Returns an {@link ImageProxy} for this user's effective avatar image. - * - * @return Never-null {@link ImageProxy} of this user's effective avatar image - * - * @see #getEffectiveAvatarUrl() - */ - @Nonnull - public ImageProxy getEffectiveAvatar() - { - return new ImageProxy(getEffectiveAvatarUrl()); - } - - /** - * Gets the nickname of the member. If they do not have a nickname on - * the guild, this will return null; - * - * @return possibly-null String containing the nickname of the member - */ - @Nullable - public String getNickname() - { - return nickname; - } - - /** - * Gets the visible name of the member. If they have a nickname set, - * this will be their nickname. Otherwise, it will be their username. - * - * @return never-null String containing the member's effective (visible) name - */ - @Nonnull - public String getEffectiveName() - { - return nickname == null ? username : nickname; - } - - /** - * Gets the online status of the member. The widget does not show - * offline members, so this status should never be offline - * - * @return the {@link net.dv8tion.jda.api.OnlineStatus OnlineStatus} of the member - */ - @Nonnull - public OnlineStatus getOnlineStatus() - { - return status; - } - - /** - * The game that the member is currently playing. - *
This game cannot be a stream. - * If the user is not currently playing a game, this will return null. - * - * @return Possibly-null {@link net.dv8tion.jda.api.entities.Activity Activity} containing the game - * that the member is currently playing. - */ - @Nullable - public Activity getActivity() - { - return game; - } - - /** - * The current voice state of the member. - *
If the user is not in voice, this will return a VoiceState with a null channel. - * - * @return never-null VoiceState of the member - */ - @Nonnull - public VoiceState getVoiceState() - { - return state == null ? new VoiceState(this, widget) : state; - } - - /** - * Gets the widget that to which this member belongs - * - * @return the Widget that holds this member - */ - @Nonnull - public Widget getWidget() - { - return widget; - } - - @Override - public int hashCode() { - return (widget.getId() + ' ' + id).hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Member)) - return false; - Member oMember = (Member) obj; - return this == oMember || (this.id == oMember.getIdLong() && this.widget.getIdLong() == oMember.getWidget().getIdLong()); - } - - @Override - public String toString() - { - return new EntityString("Widget.Member") - .setName(getName()) - .toString(); - } - } - - public static class VoiceChannel implements ISnowflake - { - private final int position; - private final long id; - private final String name; - private final List members; - private final Widget widget; - - private VoiceChannel(@Nonnull DataObject json, @Nonnull Widget widget) - { - this.widget = widget; - this.position = json.getInt("position"); - this.id = json.getLong("id"); - this.name = json.getString("name"); - this.members = new ArrayList<>(); - } - - private void addMember(@Nonnull Member member) - { - members.add(member); - } - - /** - * Gets the integer position of the channel - * - * @return integer position of the channel - */ - public int getPosition() - { - return position; - } - - @Override - public long getIdLong() - { - return id; - } - - /** - * Gets the name of the channel - * - * @return name of the channel - */ - @Nonnull - public String getName() - { - return name; - } - - /** - * Gets a list of all members in the channel - * - * @return never-null, possibly-empty list of members in the channel - */ - @Nonnull - public List getMembers() - { - return members; - } - - /** - * Gets the Widget to which this voice channel belongs - * - * @return the Widget object that holds this voice channel - */ - @Nonnull - public Widget getWidget() - { - return widget; - } - - @Override - public int hashCode() { - return Long.hashCode(id); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof VoiceChannel)) - return false; - VoiceChannel oVChannel = (VoiceChannel) obj; - return this == oVChannel || this.id == oVChannel.getIdLong(); - } - - @Override - public String toString() - { - return new EntityString("Widget.VoiceChannel") - .setName(getName()) - .toString(); - } - } - - public static class VoiceState - { - private final VoiceChannel channel; - private final boolean muted; - private final boolean deafened; - private final boolean suppress; - private final boolean selfMute; - private final boolean selfDeaf; - private final Member member; - private final Widget widget; - - private VoiceState(@Nonnull Member member, @Nonnull Widget widget) - { - this(null, false, false, false, false, false, member, widget); - } - - private VoiceState(@Nullable VoiceChannel channel, boolean muted, boolean deafened, boolean suppress, boolean selfMute, boolean selfDeaf, @Nonnull Member member, @Nonnull Widget widget) - { - this.channel = channel; - this.muted = muted; - this.deafened = deafened; - this.suppress = suppress; - this.selfMute = selfMute; - this.selfDeaf = selfDeaf; - this.member = member; - this.widget = widget; - } - - /** - * Gets the channel the member is in - * - * @return never-null VoiceChannel - */ - @Nullable - public VoiceChannel getChannel() - { - return channel; - } - - /** - * Used to determine if the member is currently in a voice channel. - *
If this is false, getChannel() will return null - * - * @return True, if the member is in a voice channel - */ - public boolean inVoiceChannel() - { - return channel != null; - } - - /** - * Whether the member is muted by an admin - * - * @return True, if the member is muted - */ - public boolean isGuildMuted() - { - return muted; - } - - /** - * Whether the member is deafened by an admin - * - * @return True, if the member is deafened - */ - public boolean isGuildDeafened() - { - return deafened; - } - - /** - * Whether the member is suppressed - * - * @return True, if the member is suppressed - */ - public boolean isSuppressed() - { - return suppress; - } - - /** - * Whether the member is self-muted - * - * @return True, if the member is self-muted - */ - public boolean isSelfMuted() - { - return selfMute; - } - - /** - * Whether the member is self-deafened - * - * @return True, if the member is self-deafened - */ - public boolean isSelfDeafened() - { - return selfDeaf; - } - - /** - * Whether the member is muted, either by an admin or self-muted - * - * @return True, if the member is self-muted or guild-muted - */ - public boolean isMuted() - { - return selfMute || muted; - } - - /** - * Whether the member is deafened, either by an admin or self-deafened - * - * @return True, if the member is self-deafened or guild-deafened - */ - public boolean isDeafened() - { - return selfDeaf || deafened; - } - - @Nonnull - public Member getMember() - { - return member; - } - - @Nonnull - public Widget getWidget() - { - return widget; - } - - @Override - public int hashCode() { - return member.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof VoiceState)) - return false; - VoiceState oState = (VoiceState) obj; - return this == oState || (this.member.equals(oState.getMember()) && this.widget.equals(oState.getWidget())); - } - - @Override - public String toString() { - return new EntityString("Widget.VoiceState") - .setName(widget.getName()) - .addMetadata("memberName", member.getEffectiveName()) - .toString(); - } - } - } } diff --git a/src/main/java/net/dv8tion/jda/api/utils/package-info.java b/src/main/java/net/dv8tion/jda/api/utils/package-info.java index fa48409ffe..40a7b3298c 100644 --- a/src/main/java/net/dv8tion/jda/api/utils/package-info.java +++ b/src/main/java/net/dv8tion/jda/api/utils/package-info.java @@ -24,7 +24,7 @@ *
Various operations that don't have specific utility classes yet, mostly internals that are accessible from JDA entities * *
  • {@link net.dv8tion.jda.api.utils.WidgetUtil WidgetUtil} - *
    This is not bound to a JDA instance and can view the {@link net.dv8tion.jda.api.utils.WidgetUtil.Widget Widget} + *
    This is not bound to a JDA instance and can view the {@link net.dv8tion.jda.api.entities.Widget Widget} * for a specified Guild. (by id)
  • * *
  • {@link net.dv8tion.jda.api.utils.MarkdownSanitizer MarkdownSanitizer} diff --git a/src/main/java/net/dv8tion/jda/internal/entities/WidgetImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/WidgetImpl.java new file mode 100644 index 0000000000..2c6b524fc7 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/entities/WidgetImpl.java @@ -0,0 +1,601 @@ +/* + * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.dv8tion.jda.internal.entities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import gnu.trove.map.TLongObjectMap; +import gnu.trove.map.hash.TLongObjectHashMap; +import net.dv8tion.jda.api.OnlineStatus; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.Widget; +import net.dv8tion.jda.api.utils.ImageProxy; +import net.dv8tion.jda.api.utils.MiscUtil; +import net.dv8tion.jda.api.utils.data.DataArray; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.internal.utils.EntityString; + +public class WidgetImpl implements Widget +{ + private final boolean isAvailable; + private final long id; + private final String name; + private final String invite; + private final TLongObjectMap channels; + private final TLongObjectMap members; + + /** + * Constructs an unavailable Widget + */ + public WidgetImpl(long guildId) + { + isAvailable = false; + id = guildId; + name = null; + invite = null; + channels = new TLongObjectHashMap<>(); + members = new TLongObjectHashMap<>(); + } + + /** + * Constructs an available Widget + * + * @param json + * The {@link net.dv8tion.jda.api.utils.data.DataObject DataObject} to construct the Widget from + */ + public WidgetImpl(@Nonnull DataObject json) + { + String inviteCode = json.getString("instant_invite", null); + if (inviteCode != null) + inviteCode = inviteCode.substring(inviteCode.lastIndexOf("/") + 1); + + isAvailable = true; + id = json.getLong("id"); + name = json.getString("name"); + invite = inviteCode; + channels = MiscUtil.newLongMap(); + members = MiscUtil.newLongMap(); + + DataArray channelsJson = json.getArray("channels"); + for (int i = 0; i < channelsJson.length(); i++) + { + DataObject channel = channelsJson.getObject(i); + channels.put(channel.getLong("id"), new VoiceChannelImpl(channel, this)); + } + + DataArray membersJson = json.getArray("members"); + for (int i = 0; i getVoiceChannels() + { + checkAvailable(); + + return Collections.unmodifiableList(new ArrayList<>(channels.valueCollection())); + } + + @Override + @Nullable + public VoiceChannel getVoiceChannelById(String id) + { + checkAvailable(); + + return channels.get(MiscUtil.parseSnowflake(id)); + } + + @Override + @Nullable + public VoiceChannel getVoiceChannelById(long id) + { + checkAvailable(); + + return channels.get(id); + } + + @Override + @Nonnull + public List getMembers() + { + checkAvailable(); + + return Collections.unmodifiableList(new ArrayList<>(members.valueCollection())); + } + + @Override + @Nullable + public Member getMemberById(String id) + { + checkAvailable(); + + return members.get(MiscUtil.parseSnowflake(id)); + } + + @Override + @Nullable + public Member getMemberById(long id) + { + checkAvailable(); + + return members.get(id); + } + + @Override + public int hashCode() { + return Long.hashCode(id); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof WidgetImpl)) + return false; + WidgetImpl oWidget = (WidgetImpl) obj; + return this == oWidget || this.id == oWidget.getIdLong(); + } + + @Override + public String toString() + { + final EntityString entityString = new EntityString(this); + if (isAvailable()) + entityString.setName(getName()); + return entityString.toString(); + } + + private void checkAvailable() + { + if (!isAvailable) + throw new IllegalStateException("The widget for this Guild is unavailable!"); + } + + public class MemberImpl implements Member + { + private final boolean bot; + private final long id; + private final String username; + private final String discriminator; + private final String avatar; + private final String nickname; + private final OnlineStatus status; + private final Activity game; + private final WidgetImpl widget; + private VoiceState state; + + private MemberImpl(@Nonnull DataObject json, @Nonnull WidgetImpl widget) + { + this.widget = widget; + this.bot = json.getBoolean("bot"); + this.id = json.getLong("id"); + this.username = json.getString("username"); + this.discriminator = json.getString("discriminator"); + this.avatar = json.getString("avatar", null); + this.nickname = json.getString("nick", null); + this.status = OnlineStatus.fromKey(json.getString("status")); + this.game = json.isNull("game") ? null : EntityBuilder.createActivity(json.getObject("game")); + } + + private void setVoiceState(VoiceState voiceState) + { + state = voiceState; + } + + @Override + public boolean isBot() + { + return bot; + } + + @Override + @Nonnull + public String getName() + { + return username; + } + + @Override + public long getIdLong() + { + return id; + } + + @Nonnull + @Override + public String getAsMention() + { + return "<@" + getId() + ">"; + } + + @Override + @Nonnull + public String getDiscriminator() + { + return discriminator; + } + + @Override + @Nullable + public String getAvatarId() + { + return avatar; + } + + @Override + @Nullable + public String getAvatarUrl() + { + String avatarId = getAvatarId(); + return avatarId == null ? null : String.format(User.AVATAR_URL, getId(), avatarId, avatarId.startsWith("a_") ? ".gif" : ".png"); + } + + @Override + @Nullable + public ImageProxy getAvatar() + { + final String avatarUrl = getAvatarUrl(); + return avatarUrl == null ? null : new ImageProxy(avatarUrl); + } + + @Override + @Nonnull + public String getDefaultAvatarId() + { + return String.valueOf(Integer.parseInt(getDiscriminator()) % 5); + } + + @Override + @Nonnull + public String getDefaultAvatarUrl() + { + return String.format(User.DEFAULT_AVATAR_URL, getDefaultAvatarId()); + } + + @Override + @Nonnull + public ImageProxy getDefaultAvatar() + { + return new ImageProxy(getDefaultAvatarUrl()); + } + + @Override + @Nonnull + public String getEffectiveAvatarUrl() + { + String avatarUrl = getAvatarUrl(); + return avatarUrl == null ? getDefaultAvatarUrl() : avatarUrl; + } + + @Override + @Nonnull + public ImageProxy getEffectiveAvatar() + { + return new ImageProxy(getEffectiveAvatarUrl()); + } + + @Override + @Nullable + public String getNickname() + { + return nickname; + } + + @Override + @Nonnull + public String getEffectiveName() + { + return nickname == null ? username : nickname; + } + + @Override + @Nonnull + public OnlineStatus getOnlineStatus() + { + return status; + } + + @Override + @Nullable + public Activity getActivity() + { + return game; + } + + @Override + @Nonnull + public VoiceState getVoiceState() + { + return state == null ? new VoiceStateImpl(this, widget) : state; + } + + @Override + @Nonnull + public WidgetImpl getWidget() + { + return widget; + } + + @Override + public int hashCode() { + return (widget.getId() + ' ' + id).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Member)) + return false; + Member oMember = (Member) obj; + return this == oMember || (this.id == oMember.getIdLong() && this.widget.getIdLong() == oMember.getWidget().getIdLong()); + } + + @Override + public String toString() + { + return new EntityString(this) + .setName(getName()) + .toString(); + } + } + + public class VoiceChannelImpl implements VoiceChannel + { + private final int position; + private final long id; + private final String name; + private final List members; + private final Widget widget; + + private VoiceChannelImpl(@Nonnull DataObject json, @Nonnull Widget widget) + { + this.widget = widget; + this.position = json.getInt("position"); + this.id = json.getLong("id"); + this.name = json.getString("name"); + this.members = new ArrayList<>(); + } + + private void addMember(@Nonnull Member member) + { + members.add(member); + } + + @Override + public int getPosition() + { + return position; + } + + @Override + public long getIdLong() + { + return id; + } + + @Override + @Nonnull + public String getName() + { + return name; + } + + @Override + @Nonnull + public List getMembers() + { + return members; + } + + @Override + @Nonnull + public Widget getWidget() + { + return widget; + } + + @Override + public int hashCode() { + return Long.hashCode(id); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof VoiceChannel)) + return false; + VoiceChannel oVChannel = (VoiceChannel) obj; + return this == oVChannel || this.id == oVChannel.getIdLong(); + } + + @Override + public String toString() + { + return new EntityString(this) + .setName(getName()) + .toString(); + } + } + + public class VoiceStateImpl implements VoiceState + { + private final VoiceChannel channel; + private final boolean muted; + private final boolean deafened; + private final boolean suppress; + private final boolean selfMute; + private final boolean selfDeaf; + private final Member member; + private final Widget widget; + + private VoiceStateImpl(@Nonnull Member member, @Nonnull Widget widget) + { + this(null, false, false, false, false, false, member, widget); + } + + private VoiceStateImpl(@Nullable VoiceChannel channel, boolean muted, boolean deafened, boolean suppress, boolean selfMute, boolean selfDeaf, @Nonnull Member member, @Nonnull Widget widget) + { + this.channel = channel; + this.muted = muted; + this.deafened = deafened; + this.suppress = suppress; + this.selfMute = selfMute; + this.selfDeaf = selfDeaf; + this.member = member; + this.widget = widget; + } + + @Override + @Nullable + public VoiceChannel getChannel() + { + return channel; + } + + @Override + public boolean inVoiceChannel() + { + return channel != null; + } + + @Override + public boolean isGuildMuted() + { + return muted; + } + + @Override + public boolean isGuildDeafened() + { + return deafened; + } + + @Override + public boolean isSuppressed() + { + return suppress; + } + + @Override + public boolean isSelfMuted() + { + return selfMute; + } + + @Override + public boolean isSelfDeafened() + { + return selfDeaf; + } + + @Override + public boolean isMuted() + { + return selfMute || muted; + } + + @Override + public boolean isDeafened() + { + return selfDeaf || deafened; + } + + @Override + @Nonnull + public Member getMember() + { + return member; + } + + @Override + @Nonnull + public Widget getWidget() + { + return widget; + } + + @Override + public int hashCode() { + return member.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof VoiceState)) + return false; + VoiceState oState = (VoiceState) obj; + return this == oState || (this.member.equals(oState.getMember()) && this.widget.equals(oState.getWidget())); + } + + @Override + public String toString() { + return new EntityString(this) + .setName(widget.getName()) + .addMetadata("memberName", member.getEffectiveName()) + .toString(); + } + } +}