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

Implement user banner & banner color #1736

Merged
merged 25 commits into from
Nov 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c63a55b
Initial pass on user banners
RedDaedalus Jul 19, 2021
d7bd584
Docs
RedDaedalus Jul 19, 2021
fdfb0d9
User update events, undefined state fixes
RedDaedalus Jul 19, 2021
a9542d7
Event docs
RedDaedalus Jul 19, 2021
4f79cd1
Update to accent color
RedDaedalus Jul 19, 2021
43f6a95
Remove old commented code
RedDaedalus Jul 19, 2021
03de1fd
Merge branch 'DV8FromTheWorld:development' into feature/user-banners
RedDaedalus Aug 29, 2021
3522a94
Merge branch 'DV8FromTheWorld:development' into feature/user-banners
RedDaedalus Sep 5, 2021
317bdc2
Apply requested changes
RedDaedalus Sep 5, 2021
be3d041
Fix BANNER_URL docs
RedDaedalus Sep 5, 2021
077057b
Remove profile update events
RedDaedalus Sep 7, 2021
c2a4dcc
Add retriever for user profile (docs needed)
RedDaedalus Sep 7, 2021
a8d0131
Docs
RedDaedalus Sep 7, 2021
2876166
Remove direct profile getters in User, profile optimizations
RedDaedalus Sep 27, 2021
6ed35d8
Docs
RedDaedalus Sep 27, 2021
2874566
Merge branch 'DV8FromTheWorld:development' into feature/user-banners
RedDaedalus Sep 27, 2021
d75aaf0
Fix import
RedDaedalus Oct 1, 2021
29fc83f
Update src/main/java/net/dv8tion/jda/internal/entities/UserImpl.java
RedDaedalus Nov 6, 2021
979c284
Update src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.…
RedDaedalus Nov 6, 2021
6c42d4f
Update src/main/java/net/dv8tion/jda/api/entities/User.java
RedDaedalus Nov 6, 2021
2f7e3a4
Update src/main/java/net/dv8tion/jda/api/entities/User.java
RedDaedalus Nov 6, 2021
2334d31
Update src/main/java/net/dv8tion/jda/api/entities/User.java
RedDaedalus Nov 6, 2021
444090d
Update src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.…
RedDaedalus Nov 6, 2021
de71fda
Update src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.…
RedDaedalus Nov 6, 2021
4d80271
Final cleanup
MinnDevelopment Nov 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions src/main/java/net/dv8tion/jda/api/entities/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.awt.Color;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
Expand Down Expand Up @@ -84,6 +85,11 @@ public interface User extends IMentionable
String AVATAR_URL = "https://cdn.discordapp.com/avatars/%s/%s.%s";
/** Template for {@link #getDefaultAvatarUrl()} */
String DEFAULT_AVATAR_URL = "https://cdn.discordapp.com/embed/avatars/%s.png";
/** Template for {@link Profile#getBannerUrl()} */
String BANNER_URL = "https://cdn.discordapp.com/banners/%s/%s.%s";

/** Used to keep consistency between color values used in the API */
int DEFAULT_ACCENT_COLOR_RAW = 0x1FFFFFFF; // java.awt.Color fills the MSB with FF, we just use 1F to provide better consistency

/**
* Creates a User instance which only wraps an ID.
Expand Down Expand Up @@ -220,6 +226,21 @@ default String getEffectiveAvatarUrl()
return avatarUrl == null ? getDefaultAvatarUrl() : avatarUrl;
}

/**
* Loads the user's {@link User.Profile} data.
* Returns a completed RestAction if this User has been retrieved using {@link JDA#retrieveUserById(long)}.
*
* @throws UnsupportedOperationException
* If this User was created with {@link #fromId(long)}
*
* @return {@link RestAction} - Type: {@link User.Profile}
*
* @since 4.3.0
*/
@Nonnull
@CheckReturnValue
RestAction<Profile> retrieveProfile();

/**
* The "tag" for this user
* <p>This is the equivalent of calling {@link java.lang.String#format(String, Object...) String.format}("%#s", user)
Expand Down Expand Up @@ -344,6 +365,86 @@ default String getEffectiveAvatarUrl()
*/
int getFlagsRaw();

/**
* Represents the information contained in a {@link User User}'s profile.
*
* @since 4.3.0
*/
class Profile
{
private final long userId;
private final String bannerId;
private final int accentColor;

public Profile(long userId, String bannerId, int accentColor)
{
this.userId = userId;
this.bannerId = bannerId;
this.accentColor = accentColor;
}

/**
* The Discord Id for this user's banner image.
* If the user has not set a banner, this will return null.
*
* @return Possibly-null String containing the {@link User User} banner id.
*/
@Nullable
public String getBannerId()
RedDaedalus marked this conversation as resolved.
Show resolved Hide resolved
{
return bannerId;
}

/**
* The URL for the user's banner image.
* If the user has not set a banner, this will return null.
*
* @return Possibly-null String containing the {@link User User} banner url.
*
* @see User#BANNER_URL
*/
@Nullable
public String getBannerUrl()
{
return bannerId == null ? null : String.format(BANNER_URL, Long.toUnsignedString(userId), bannerId, bannerId.startsWith("a_") ? "gif" : "png");
}

/**
* The user's accent color.
* If the user has not set an accent color, this will return null.
* The automatically calculated color is not returned.
* The accent color is not shown in the client if the user has set a banner.
*
* @return Possibly-null {@link java.awt.Color} containing the {@link User User} accent color.
*/
@Nullable
public Color getAccentColor()
RedDaedalus marked this conversation as resolved.
Show resolved Hide resolved
{
return accentColor == DEFAULT_ACCENT_COLOR_RAW ? null : new Color(accentColor);
}

/**
* The raw RGB value of this user's accent color.
* <br>Defaults to {@link #DEFAULT_ACCENT_COLOR_RAW} if this user's banner color is not available.
*
* @return The raw RGB color value or {@link User#DEFAULT_ACCENT_COLOR_RAW}
*/
public int getAccentColorRaw()
{
return accentColor;
}

@Override
public String toString()
{
return "UserProfile(" +
"userId=" + userId +
", bannerId='" + bannerId + "'" +
", accentColor=" + accentColor +
')';
}
}

/**
* Represents the bit offsets used by Discord for public flags
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ public UserImpl createUser(DataObject user)
}
}

User.Profile profile = user.hasKey("banner")
? new User.Profile(id, user.getString("banner", null), user.getInt("accent_color", User.DEFAULT_ACCENT_COLOR_RAW))
: null;

if (newUser)
{
// Initial creation
Expand All @@ -353,7 +357,8 @@ public UserImpl createUser(DataObject user)
.setAvatarId(user.getString("avatar", null))
.setBot(user.getBoolean("bot"))
.setSystem(user.getBoolean("system"))
.setFlags(user.getInt("public_flags", 0));
.setFlags(user.getInt("public_flags", 0))
.setProfile(profile);
}
else
{
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/net/dv8tion/jda/internal/entities/UserById.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ public String getAvatarId()
return null;
}

@Nonnull
@Override
public RestAction<Profile> retrieveProfile()
{
unsupported();
return null;
}

@Nonnull
@Override
public String getDefaultAvatarId()
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/net/dv8tion/jda/internal/entities/UserImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class UserImpl extends UserById implements User
protected short discriminator;
protected String name;
protected String avatarId;
protected Profile profile;
protected long privateChannel = 0L;
protected boolean bot;
protected boolean system;
Expand Down Expand Up @@ -73,6 +74,28 @@ public String getAvatarId()
return avatarId;
}

@Nonnull
@Override
public RestAction<Profile> retrieveProfile()
{
return new DeferredRestAction<>(getJDA(), Profile.class, this::getProfile, () -> {
Route.CompiledRoute route = Route.Users.GET_USER.compile(getId());
return new RestActionImpl<>(getJDA(), route, (response, request) -> {
DataObject json = response.getObject();

String bannerId = json.getString("banner", null);
int accentColor = json.getInt("accent_color", User.DEFAULT_ACCENT_COLOR_RAW);

return new Profile(getIdLong(), bannerId, accentColor);
});
});
}

public Profile getProfile()
{
return profile;
}

@Nonnull
@Override
public String getDefaultAvatarId()
Expand Down Expand Up @@ -182,6 +205,12 @@ public UserImpl setAvatarId(String avatarId)
return this;
}

public UserImpl setProfile(Profile profile)
{
this.profile = profile;
return this;
}

public UserImpl setPrivateChannel(PrivateChannel privateChannel)
{
if (privateChannel != null)
Expand Down