diff --git a/src/main/java/net/dv8tion/jda/api/JDA.java b/src/main/java/net/dv8tion/jda/api/JDA.java index eabc044f8f..09cfd822f6 100644 --- a/src/main/java/net/dv8tion/jda/api/JDA.java +++ b/src/main/java/net/dv8tion/jda/api/JDA.java @@ -30,6 +30,7 @@ import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.build.CommandData; import net.dv8tion.jda.api.interactions.commands.build.Commands; +import net.dv8tion.jda.api.managers.ApplicationManager; import net.dv8tion.jda.api.managers.AudioManager; import net.dv8tion.jda.api.managers.DirectAudioController; import net.dv8tion.jda.api.managers.Presence; @@ -2214,4 +2215,13 @@ default AuditableRestAction installAuxiliaryPort() else throw new IllegalStateException("No port available"); return new CompletedRestAction<>(this, port); } + + /** + * Returns the {@link net.dv8tion.jda.api.managers.ApplicationManager} that manages the application associated with the bot. + * + * @return The corresponding ApplicationManager + */ + @Nonnull + ApplicationManager getApplicationManager(); + } diff --git a/src/main/java/net/dv8tion/jda/api/managers/ApplicationManager.java b/src/main/java/net/dv8tion/jda/api/managers/ApplicationManager.java new file mode 100644 index 0000000000..cb86f3179e --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/managers/ApplicationManager.java @@ -0,0 +1,104 @@ +package net.dv8tion.jda.api.managers; + +import net.dv8tion.jda.api.entities.ApplicationInfo; +import net.dv8tion.jda.api.entities.Icon; + +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; + +/** + * Implemented only description, icon and cover_image. + *
For more fields check Discord docs: https://discord.com/developers/docs/resources/application#edit-current-application + */ +public interface ApplicationManager extends Manager +{ + + /** + * Used to set description + */ + long DESCRIPTION = 1; + /** + * Used to set icon + */ + long ICON = 1 << 1; + /** + * Used to set cover_image + */ + long COVER_IMAGE = 1 << 2; + + /** + * The {@link net.dv8tion.jda.api.entities.ApplicationInfo ApplicationInfo} associated to the bot. + * + * @return The corresponding ApplicationInfo + */ + @Nonnull + ApplicationInfo getApplicationInfo(); + + /** + * Resets the fields specified by the provided bit-flag pattern. + * You can specify a combination by using a bitwise OR concat of the flag constants. + *
Example: {@code manager.reset(ApplicationManager.ICON | ApplicationManager.COVER_IMAGE);} + *
For all flags, check {@link ApplicationManager} fields. + * @param fields + * Integer value containing the flags to reset. + * + * @return ApplicationManager for chaining convenience + */ + @Nonnull + @Override + @CheckReturnValue + ApplicationManager reset(long fields); + + /** + * Resets the fields specified by the provided bit-flag patterns. + *
Example: {@code manager.reset(ApplicationManager.ICON, ApplicationManager.COVER_IMAGE);} + *
For all flags, check {@link ApplicationManager} fields. + * + * @param fields + * Integer values containing the flags to reset. + * + * @return ApplicationManager for chaining convenience + */ + @Nonnull + @Override + @CheckReturnValue + ApplicationManager reset(long... fields); + + + /** + * Sets the description of the application. + * + * @param description + * The new description + * + * @return ApplicationManager for chaining convenience + */ + @Nonnull + @CheckReturnValue + ApplicationManager setDescription(@Nonnull String description); + + /** + * Sets the icon of the application. + * + * @param icon + * The new icon + * + * @return ApplicationManager for chaining convenience + */ + @Nonnull + @CheckReturnValue + ApplicationManager setIcon(@Nonnull Icon icon); + + /** + * Sets the cover image of the application. + * + * @param coverImage + * The new coverImage + * + * @return ApplicationManager for chaining convenience + */ + @Nonnull + @CheckReturnValue + ApplicationManager setCoverImage(@Nonnull Icon coverImage); + +} diff --git a/src/main/java/net/dv8tion/jda/api/requests/Route.java b/src/main/java/net/dv8tion/jda/api/requests/Route.java index 0e165f9f85..a782c77104 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/Route.java +++ b/src/main/java/net/dv8tion/jda/api/requests/Route.java @@ -43,6 +43,7 @@ public static class Misc public static class Applications { public static final Route GET_BOT_APPLICATION = new Route(GET, "oauth2/applications/@me"); + public static final Route EDIT_BOT_APPLICATION = new Route(PATCH, "applications/@me"); public static final Route GET_ROLE_CONNECTION_METADATA = new Route(GET, "applications/{application_id}/role-connections/metadata"); public static final Route UPDATE_ROLE_CONNECTION_METADATA = new Route(PUT, "applications/{application_id}/role-connections/metadata"); public static final Route GET_ENTITLEMENTS = new Route(GET, "applications/{application_id}/entitlements"); diff --git a/src/main/java/net/dv8tion/jda/internal/JDAImpl.java b/src/main/java/net/dv8tion/jda/internal/JDAImpl.java index 8ef202f4d3..d827b366e4 100644 --- a/src/main/java/net/dv8tion/jda/internal/JDAImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/JDAImpl.java @@ -45,6 +45,7 @@ import net.dv8tion.jda.api.hooks.VoiceDispatchInterceptor; import net.dv8tion.jda.api.interactions.commands.Command; import net.dv8tion.jda.api.interactions.commands.build.CommandData; +import net.dv8tion.jda.api.managers.ApplicationManager; import net.dv8tion.jda.api.managers.AudioManager; import net.dv8tion.jda.api.managers.Presence; import net.dv8tion.jda.api.requests.*; @@ -65,6 +66,7 @@ import net.dv8tion.jda.internal.hooks.EventManagerProxy; import net.dv8tion.jda.internal.interactions.CommandDataImpl; import net.dv8tion.jda.internal.interactions.command.CommandImpl; +import net.dv8tion.jda.internal.managers.ApplicationManagerImpl; import net.dv8tion.jda.internal.managers.AudioManagerImpl; import net.dv8tion.jda.internal.managers.DirectAudioControllerImpl; import net.dv8tion.jda.internal.managers.PresenceImpl; @@ -82,6 +84,7 @@ import net.dv8tion.jda.internal.utils.config.ThreadingConfig; import okhttp3.OkHttpClient; import okhttp3.RequestBody; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.MDC; @@ -142,6 +145,8 @@ public class JDAImpl implements JDA protected final AtomicBoolean requesterShutdown = new AtomicBoolean(false); protected final AtomicReference shutdownEvent = new AtomicReference<>(null); + protected final ApplicationManager applicationManager; + public JDAImpl(AuthorizationConfig authConfig) { this(authConfig, null, null, null, null); @@ -162,6 +167,7 @@ public JDAImpl( this.audioController = new DirectAudioControllerImpl(this); this.eventCache = new EventCache(); this.eventManager = new EventManagerProxy(new InterfacedEventManager(), this.threadConfig.getEventPool()); + this.applicationManager = new ApplicationManagerImpl(this); } public void handleEvent(@Nonnull GenericEvent event) @@ -1154,6 +1160,13 @@ public RestAction retrieveWebhookById(@Nonnull String webhookId) }); } + @Nonnull + @Override + public ApplicationManager getApplicationManager() + { + return this.applicationManager; + } + @Nonnull @Override public RestAction retrieveApplicationInfo() diff --git a/src/main/java/net/dv8tion/jda/internal/managers/ApplicationManagerImpl.java b/src/main/java/net/dv8tion/jda/internal/managers/ApplicationManagerImpl.java new file mode 100644 index 0000000000..90a9cb1422 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/managers/ApplicationManagerImpl.java @@ -0,0 +1,139 @@ +package net.dv8tion.jda.internal.managers; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.ApplicationInfo; +import net.dv8tion.jda.api.entities.Icon; +import net.dv8tion.jda.api.managers.ApplicationManager; +import net.dv8tion.jda.api.requests.Request; +import net.dv8tion.jda.api.requests.Response; +import net.dv8tion.jda.api.requests.Route; +import net.dv8tion.jda.api.utils.data.DataObject; +import okhttp3.RequestBody; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; + +/** + * When implement new fields, update also {@link #reset(long)}, {@link #reset(long...)}, {@link #reset()} and {@link #finalizeData()} + */ +public class ApplicationManagerImpl extends ManagerBase implements ApplicationManager +{ + + protected String description; + protected Icon icon; + protected Icon coverImage; + + public ApplicationManagerImpl(JDA jda) + { + super(jda, Route.Applications.EDIT_BOT_APPLICATION.compile()); + } + + @NotNull + @Override + public ApplicationInfo getApplicationInfo() + { + return this.getJDA().retrieveApplicationInfo().complete(); + } + + @Nonnull + @Override + @CheckReturnValue + public ApplicationManagerImpl reset(long fields) + { + super.reset(fields); + + if((fields & DESCRIPTION) == DESCRIPTION) + description = null; + if((fields & ICON) == ICON) + icon = null; + if((fields & COVER_IMAGE) == COVER_IMAGE) + coverImage = null; + + return this; + } + + @Nonnull + @Override + @CheckReturnValue + public ApplicationManagerImpl reset(long... fields) + { + super.reset(fields); + + for(long field : fields) + { + + if(field == DESCRIPTION) + description = null; + else if(field == ICON) + icon = null; + else if(field == COVER_IMAGE) + coverImage = null; + + } + + return this; + } + + @Nonnull + @Override + @CheckReturnValue + public ApplicationManager reset() + { + super.reset(); + this.description = null; + this.icon = null; + this.coverImage = null; + return this; + } + + @NotNull + @Override + public ApplicationManager setDescription(@NotNull String description) + { + this.description = description.trim(); + set |= DESCRIPTION; + return this; + } + + @NotNull + @Override + public ApplicationManager setIcon(@NotNull Icon icon) + { + this.icon = icon; + set |= ICON; + return this; + } + + @NotNull + @Override + public ApplicationManager setCoverImage(@NotNull Icon coverImage) + { + this.coverImage = coverImage; + set |= COVER_IMAGE; + return this; + } + + @Override + protected RequestBody finalizeData() + { + DataObject body = DataObject.empty(); + + if(shouldUpdate(DESCRIPTION)) + body.put("description", this.description); + if(shouldUpdate(ICON)) + body.put("icon", this.icon == null ? null : this.icon.getEncoding()); + if(shouldUpdate(COVER_IMAGE)) + body.put("cover_image", this.coverImage == null ? null : this.coverImage.getEncoding()); + + reset(); + return getRequestBody(body); + } + + @Override + protected void handleSuccess(Response response, Request request) + { + request.onSuccess(null); + } + +}