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
13 changes: 13 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 @@ -161,6 +161,7 @@ public interface Role extends IMentionable, IPermissionHolder, Comparable<Role>
* Creates a new {@link net.dv8tion.jda.api.entities.Role Role} in the specified {@link net.dv8tion.jda.api.entities.Guild Guild}
* with the same settings as the given {@link net.dv8tion.jda.api.entities.Role Role}.
* <br>The position of the specified Role does not matter in this case!
* <br><b>If this {@link Role} has an {@link RoleIcon Icon} set, only its emoji can be copied over.</b>
*
* <p>It will be placed at the bottom (just over the Public Role) to avoid permission hierarchy conflicts.
* <br>For this to be successful, the logged in account has to have the {@link net.dv8tion.jda.api.Permission#MANAGE_ROLES MANAGE_ROLES} Permission
Expand Down Expand Up @@ -195,6 +196,7 @@ public interface Role extends IMentionable, IPermissionHolder, Comparable<Role>
* Creates a new {@link net.dv8tion.jda.api.entities.Role Role} in this {@link net.dv8tion.jda.api.entities.Guild Guild}
* with the same settings as the given {@link net.dv8tion.jda.api.entities.Role Role}.
* <br>The position of the specified Role does not matter in this case!
* <br><b>If this {@link Role} has an {@link RoleIcon Icon} set, only its emoji can be copied over.</b>
*
* <p>It will be placed at the bottom (just over the Public Role) to avoid permission hierarchy conflicts.
* <br>For this to be successful, the logged in account has to have the {@link net.dv8tion.jda.api.Permission#MANAGE_ROLES MANAGE_ROLES} Permission
Expand Down Expand Up @@ -291,6 +293,17 @@ default RoleAction createCopy()
@Nonnull
RoleTags getTags();

/**
* The {@link RoleIcon Icon} of this role or {@code null} if no custom image or emoji is set.
* This icon will be displayed next to the role's name in the members tab and in chat.
*
* @return Possibly-null {@link RoleIcon Icon} of this role
*
* @since 4.3.1
*/
@Nullable
RoleIcon getIcon();

/**
* Tags associated with this role.
*
Expand Down
118 changes: 118 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,118 @@
/*
* 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;
sebm253 marked this conversation as resolved.
Show resolved Hide resolved

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

import javax.annotation.Nullable;
import java.util.Objects;

/**
* 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#setIcon(String)}.
*
* @return Possibly-null String containing the Role's Unicode Emoji.
*
* @since 4.3.1
*/
@Nullable
public String getEmoji()
{
return emoji;
}

/**
* Whether this {@link RoleIcon} is an emoji instead of a custom image.
*
* @return True, if this {@link RoleIcon} is an emoji
*/
public boolean isEmoji()
{
return emoji != null;
}

@Override
public boolean equals(Object obj)
{
if (obj == this)
return true;
if (!(obj instanceof RoleIcon))
return false;
RoleIcon icon = (RoleIcon) obj;
return Objects.equals(icon.iconId, iconId)
&& Objects.equals(icon.emoji, emoji);
}

@Override
public int hashCode()
{
return Objects.hash(iconId, 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
*/
@Nullable
public RoleIcon getOldIcon()
{
return getOldValue();
}

/**
* The new icon
*
* @return The new icon
*/
@Nullable
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
31 changes: 31 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,8 @@ 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;

/**
* Resets the fields specified by the provided bit-flag pattern.
Expand All @@ -69,6 +72,7 @@ public interface RoleManager extends Manager<RoleManager>
* <li>{@link #PERMISSION}</li>
* <li>{@link #HOIST}</li>
* <li>{@link #MENTIONABLE}</li>
* <li>{@link #ICON}</li>
* </ul>
*
* @param fields
Expand All @@ -92,6 +96,7 @@ public interface RoleManager extends Manager<RoleManager>
* <li>{@link #PERMISSION}</li>
* <li>{@link #HOIST}</li>
* <li>{@link #MENTIONABLE}</li>
* <li>{@link #ICON}</li>
* </ul>
*
* @param fields
Expand Down Expand Up @@ -273,6 +278,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} instead of a custom image.
*
* @param emoji
* The new 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 setIcon(@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 new 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 setIcon(@Nullable String emoji);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,14 @@ public Role createRole(GuildImpl guild, DataObject roleJson, long guildId)
.setColor(color == 0 ? Role.DEFAULT_COLOR_RAW : color)
.setMentionable(roleJson.getBoolean("mentionable"))
.setTags(roleJson.optObject("tags").orElseGet(DataObject::empty));

final String iconId = roleJson.getString("icon", null);
final String emoji = roleJson.getString("unicode_emoji", null);
if (iconId == null && emoji == null)
role.setIcon(null);
else
role.setIcon(new RoleIcon(iconId, emoji, id));

if (playbackCache)
getJDA().getEventCache().playbackCache(EventCache.Type.ROLE, id);
return role;
Expand Down
Loading