Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for role icons #1823

Merged
merged 16 commits into from
Nov 23, 2021
Merged
11 changes: 11 additions & 0 deletions src/main/java/net/dv8tion/jda/api/entities/Role.java
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,17 @@ default RoleAction createCopy()
@Nonnull
RoleTags getTags();

/**
* The {@link RoleIcon Icon} of this role.
* This icon will be displayed next to the role's name in the members tab and in chat.
*
* @return The {@link RoleIcon Icon} of this role
*
* @since 4.3.1
*/
@Nonnull
RoleIcon getIcon();

/**
* Tags associated with this role.
*
Expand Down
73 changes: 73 additions & 0 deletions src/main/java/net/dv8tion/jda/api/entities/RoleIcon.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package net.dv8tion.jda.api.entities;
sebm253 marked this conversation as resolved.
Show resolved Hide resolved

import net.dv8tion.jda.api.managers.RoleManager;

import javax.annotation.Nullable;

/**
* An object representing a Role's icon.
*
* @see Role#getIcon
*/
public class RoleIcon
{
/** Template for {@link #getIconUrl()}. */
public static final String ICON_URL = "https://cdn.discordapp.com/role-icons/%s/%s.png";

private final String iconId;
private final String emoji;
private final long roleId;

public RoleIcon(String iconId, String emoji, long roleId)
{
this.iconId = iconId;
this.emoji = emoji;
this.roleId = roleId;
}

/**
* The Discord hash-id of the {@link net.dv8tion.jda.api.entities.Role Role} icon image.
* If no icon has been set or an emoji is used in its place, this returns {@code null}.
* <p>The Role icon can be modified using {@link RoleManager#setIcon(Icon)}.
*
* @return Possibly-null String containing the Role's icon hash-id.
*
* @since 4.3.1
*/
@Nullable
public String getIconId()
{
return iconId;
}

/**
* The URL of the {@link net.dv8tion.jda.api.entities.Role Role} icon image.
* If no icon has been set or an emoji is used in its place, this returns {@code null}.
* <p>The Role icon can be modified using {@link RoleManager#setIcon(Icon)}.
*
* @return Possibly-null String containing the Role's icon URL.
*
* @since 4.3.1
*/
@Nullable
public String getIconUrl()
{
String iconId = getIconId();
return iconId == null ? null : String.format(ICON_URL, roleId, iconId);
}

/**
* The Unicode Emoji of this {@link net.dv8tion.jda.api.entities.Role Role} that is used instead of a custom image.
* If no emoji has been set, this returns {@code null}.
* <p>The Role emoji can be modified using {@link RoleManager#setEmoji(String)}.
*
* @return Possibly-null String containing the Role's Unicode Emoji.
*
* @since 4.3.1
*/
@Nullable
public String getEmoji()
{
return emoji;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* 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.events.role.update;

import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.RoleIcon;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
* Indicates that the Icon of a {@link net.dv8tion.jda.api.entities.Role Role} changed.
*
* <p>Can be used to detect when a role's icon or emoji changes and retrieve the old one
*
* <p>Identifier: {@code icon}
*/
public class RoleUpdateIconEvent extends GenericRoleUpdateEvent<RoleIcon>
{
public static final String IDENTIFIER = "icon";

public RoleUpdateIconEvent(@Nonnull JDA api, long responseNumber, @Nonnull Role role, @Nonnull RoleIcon oldIcon)
{
super(api, responseNumber, role, oldIcon, role.getIcon(), IDENTIFIER);
}

/**
* The old icon
*
* @return The old icon
*/
@Nonnull
public RoleIcon getOldIcon()
{
return getOldValue();
}

/**
* The new icon
*
* @return The new icon
*/
@Nonnull
public RoleIcon getNewIcon()
{
return getNewValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ public void onRoleDelete(@Nonnull RoleDeleteEvent event) {}
//Role Update Events
public void onRoleUpdateColor(@Nonnull RoleUpdateColorEvent event) {}
public void onRoleUpdateHoisted(@Nonnull RoleUpdateHoistedEvent event) {}
public void onRoleUpdateIcon(@Nonnull RoleUpdateIconEvent event) {}
public void onRoleUpdateMentionable(@Nonnull RoleUpdateMentionableEvent event) {}
public void onRoleUpdateName(@Nonnull RoleUpdateNameEvent event) {}
public void onRoleUpdatePermissions(@Nonnull RoleUpdatePermissionsEvent event) {}
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/net/dv8tion/jda/api/managers/RoleManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Icon;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.internal.utils.Checks;

Expand Down Expand Up @@ -56,6 +57,10 @@ public interface RoleManager extends Manager<RoleManager>
long HOIST = 0x8;
/** Used to reset the mentionable field */
long MENTIONABLE = 0x10;
/** Used to reset the icon field */
long ICON = 0x20;
/** Used to reset the unicode_emoji field */
long EMOJI = 0x40;

/**
* Resets the fields specified by the provided bit-flag pattern.
Expand All @@ -69,6 +74,8 @@ public interface RoleManager extends Manager<RoleManager>
* <li>{@link #PERMISSION}</li>
* <li>{@link #HOIST}</li>
* <li>{@link #MENTIONABLE}</li>
* <li>{@link #ICON}</li>
* <li>{@link #EMOJI}</li>
* </ul>
*
* @param fields
Expand All @@ -92,6 +99,8 @@ public interface RoleManager extends Manager<RoleManager>
* <li>{@link #PERMISSION}</li>
* <li>{@link #HOIST}</li>
* <li>{@link #MENTIONABLE}</li>
* <li>{@link #ICON}</li>
* <li>{@link #EMOJI}</li>
* </ul>
*
* @param fields
Expand Down Expand Up @@ -273,6 +282,32 @@ default RoleManager setColor(@Nullable Color color)
@CheckReturnValue
RoleManager setMentionable(boolean mentionable);

/**
* Sets the {@link net.dv8tion.jda.api.entities.Icon Icon} of this {@link net.dv8tion.jda.api.entities.Role Role}.
*
* @param icon
* The new icon for this {@link net.dv8tion.jda.api.entities.Role Role}
* or {@code null} to reset
*
* @return RoleManager for chaining convenience
*/
@Nonnull
@CheckReturnValue
RoleManager setIcon(@Nullable Icon icon);

/**
* Sets the Unicode Emoji of this {@link net.dv8tion.jda.api.entities.Role Role}.
sebm253 marked this conversation as resolved.
Show resolved Hide resolved
*
* @param emoji
* The Unicode Emoji for this {@link net.dv8tion.jda.api.entities.Role Role}
* or {@code null} to reset
*
* @return RoleManager for chaining convenience
*/
@Nonnull
@CheckReturnValue
RoleManager setEmoji(@Nullable String emoji);

/**
* Adds the specified {@link net.dv8tion.jda.api.Permission Permissions} to the selected {@link net.dv8tion.jda.api.entities.Role Role}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Icon;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.internal.utils.Checks;

Expand Down Expand Up @@ -208,4 +209,32 @@ default RoleAction setPermissions(@Nullable Collection<Permission> permissions)
@Nonnull
@CheckReturnValue
RoleAction setPermissions(@Nullable Long permissions);

/**
* Sets the {@link net.dv8tion.jda.api.entities.Icon Icon} of this {@link net.dv8tion.jda.api.entities.Role Role}.
* This icon will be displayed next to the role's name in the members tab and in chat.
*
* @param icon
* The new icon for this {@link net.dv8tion.jda.api.entities.Role Role}
* or {@code null} to reset
*
* @return RoleManager for chaining convenience
*/
@Nonnull
@CheckReturnValue
RoleAction setIcon(@Nullable Icon icon);

/**
* Sets the Unicode Emoji of this {@link net.dv8tion.jda.api.entities.Role Role} instead of a custom image.
* This emoji will be displayed next to the role's name in the members tab and in chat.
*
* @param emoji
* The Unicode Emoji for this {@link net.dv8tion.jda.api.entities.Role Role}
* or {@code null} to reset
*
* @return RoleManager for chaining convenience
*/
@Nonnull
@CheckReturnValue
RoleAction setEmoji(@Nullable String emoji);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,8 @@ public Role createRole(GuildImpl guild, DataObject roleJson, long guildId)
.setHoisted(roleJson.getBoolean("hoist"))
.setColor(color == 0 ? Role.DEFAULT_COLOR_RAW : color)
.setMentionable(roleJson.getBoolean("mentionable"))
.setTags(roleJson.optObject("tags").orElseGet(DataObject::empty));
.setTags(roleJson.optObject("tags").orElseGet(DataObject::empty))
.setIcon(new RoleIcon(roleJson.getString("icon", null), roleJson.getString("unicode_emoji", null), id));
if (playbackCache)
getJDA().getEventCache().playbackCache(EventCache.Type.ROLE, id);
return role;
Expand Down
23 changes: 18 additions & 5 deletions src/main/java/net/dv8tion/jda/internal/entities/RoleImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
import gnu.trove.map.TLongObjectMap;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildChannel;
import net.dv8tion.jda.api.entities.PermissionOverride;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.exceptions.HierarchyException;
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
import net.dv8tion.jda.api.managers.RoleManager;
Expand All @@ -39,6 +36,7 @@
import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.awt.*;
import java.time.OffsetDateTime;
import java.util.Collection;
Expand All @@ -61,6 +59,7 @@ public class RoleImpl implements Role
private long rawPermissions;
private int color;
private int rawPosition;
private RoleIcon icon;

public RoleImpl(long id, Guild guild)
{
Expand Down Expand Up @@ -288,7 +287,8 @@ public RoleAction createCopy(@Nonnull Guild guild)
.setHoisted(hoisted)
.setMentionable(mentionable)
.setName(name)
.setPermissions(rawPermissions);
.setPermissions(rawPermissions)
.setEmoji(icon.getEmoji());
}

@Nonnull
Expand Down Expand Up @@ -330,6 +330,13 @@ public RoleTags getTags()
return tags == null ? RoleTagsImpl.EMPTY : tags;
}

@Nonnull
@Override
public RoleIcon getIcon()
{
return icon;
}

@Nonnull
@Override
public String getAsMention()
Expand Down Expand Up @@ -444,6 +451,12 @@ public RoleImpl setTags(DataObject tags)
return this;
}

public RoleImpl setIcon(RoleIcon icon)
{
this.icon = icon;
return this;
}

public static class RoleTagsImpl implements RoleTags
{
public static final RoleTags EMPTY = new RoleTagsImpl();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package net.dv8tion.jda.internal.handle;

import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.RoleIcon;
import net.dv8tion.jda.api.events.role.update.*;
import net.dv8tion.jda.api.utils.data.DataObject;
import net.dv8tion.jda.internal.JDAImpl;
Expand Down Expand Up @@ -64,6 +65,8 @@ protected Long handleInternally(DataObject content)
long permissions = rolejson.getLong("permissions");
boolean hoisted = rolejson.getBoolean("hoist");
boolean mentionable = rolejson.getBoolean("mentionable");
String iconId = rolejson.getString("icon", null);
String emoji = rolejson.getString("unicode_emoji", null);

if (!Objects.equals(name, role.getName()))
{
Expand Down Expand Up @@ -121,6 +124,16 @@ protected Long handleInternally(DataObject content)
getJDA(), responseNumber,
role, wasMentionable));
}

RoleIcon oldIcon = role.getIcon();
if (!Objects.equals(oldIcon.getIconId(), iconId) || !Objects.equals(oldIcon.getEmoji(), emoji))
DV8FromTheWorld marked this conversation as resolved.
Show resolved Hide resolved
{
role.setIcon(new RoleIcon(iconId, emoji, roleId));
getJDA().handleEvent(
new RoleUpdateIconEvent(
getJDA(), responseNumber,
role, oldIcon));
}
return null;
}
}
Loading