diff --git a/rest-extensions/build.gradle.kts b/rest-extensions/build.gradle.kts index e8e407a12..0c63a7c13 100644 --- a/rest-extensions/build.gradle.kts +++ b/rest-extensions/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { // Twitch4J Modules api(project(":twitch4j-common")) + api(project(":twitch4j-helix")) } tasks.javadoc { diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/TwitchExtensions.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/TwitchExtensions.java index 737f3de9e..079f43b52 100644 --- a/rest-extensions/src/main/java/com/github/twitch4j/extensions/TwitchExtensions.java +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/TwitchExtensions.java @@ -18,6 +18,9 @@ /** * Twitch - Extensions API + * + * @see Twitch Shutdown Announcement + * @deprecated the Extensions API traditionally uses the decommissioned Kraken API. While the module now forwards calls to Helix, please migrate to using Helix directly as this module will be removed in the future. */ public interface TwitchExtensions { @@ -73,12 +76,14 @@ HystrixCommand getExtensionSecret( * @param clientId The client ID identifying the extension when it is created. * @param jsonWebToken Signed JWT created by the EBS, following the requirements documented in “Signing the JWT” (in Building Extensions) * @return 204 No Content on a successful call + * @deprecated No migration path in the new Helix API. */ @RequestLine("DELETE /{client_id}/auth/secret") @Headers({ "Client-Id: {client_id}", "Authorization: Bearer {token}" }) + @Deprecated HystrixCommand revokeExtensionSecrets( @Param("client_id") String clientId, @Param("token") String jsonWebToken @@ -90,14 +95,28 @@ HystrixCommand revokeExtensionSecrets( * A channel that just went live may take a few minutes to appear in this list, and a channel may continue to appear on this list for a few minutes after it stops broadcasting. * * @param clientId The client ID value assigned to the extension when it is created. + * @param cursor Cursor for forward pagination. * @return ChannelList */ - @RequestLine("GET /{client_id}/live_activated_channels") + @RequestLine("GET /{client_id}/live_activated_channels?cursor={cursor}") @Headers("Client-Id: {client_id}") HystrixCommand getLiveChannelsWithExtensionActivated( - @Param("client_id") String clientId + @Param("client_id") String clientId, + @Param("cursor") String cursor ); + /** + * Returns one page of live channels that have installed and activated a specified extension. + * + * @param clientId The client ID value assigned to the extension when it is created. + * @return ChannelList + * @deprecated use {@link #getLiveChannelsWithExtensionActivated(String, String)} instead (can pass null for cursor) + */ + @Deprecated + default HystrixCommand getLiveChannelsWithExtensionActivated(String clientId) { + return getLiveChannelsWithExtensionActivated(clientId, null); + } + /** * Enable activation of a specified extension, after any required broadcaster configuration is correct. *

diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/TwitchExtensionsBuilder.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/TwitchExtensionsBuilder.java index 40cb2fd9b..27429e0cb 100644 --- a/rest-extensions/src/main/java/com/github/twitch4j/extensions/TwitchExtensionsBuilder.java +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/TwitchExtensionsBuilder.java @@ -4,6 +4,7 @@ import com.github.twitch4j.common.config.ProxyConfig; import com.github.twitch4j.common.config.Twitch4JGlobal; import com.github.twitch4j.common.util.TypeConvert; +import com.github.twitch4j.extensions.compat.TwitchExtensionsCompatibilityLayer; import com.github.twitch4j.extensions.util.TwitchExtensionsClientIdInterceptor; import com.github.twitch4j.extensions.util.TwitchExtensionsErrorDecoder; import com.netflix.config.ConfigurationManager; @@ -22,11 +23,15 @@ /** * Twitch API - Extensions + * + * @see Twitch Shutdown Announcement + * @deprecated the Extensions API traditionally uses the decommissioned Kraken API. While the module now forwards calls to Helix, please migrate to using Helix directly as this module will be removed in the future. */ @Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter +@Deprecated public class TwitchExtensionsBuilder { /** @@ -77,14 +82,36 @@ public class TwitchExtensionsBuilder { @With private ProxyConfig proxyConfig = null; + /** + * Whether the compatibility layer should be used to forward requests to the new Helix API + */ + @With + private boolean helixForwarding = true; + /** * Twitch API Client (Extensions) * * @return TwitchExtensions + * @see Twitch Shutdown Announcement + * @deprecated the Extensions API traditionally uses the decommissioned Kraken API. While the module now forwards calls to Helix, please migrate to using Helix directly as this module will be removed in the future. */ + @Deprecated public TwitchExtensions build() { log.debug("Extensions: Initializing Module ..."); + // Helix Compatibility Layer + if (helixForwarding) { + return TwitchExtensionsCompatibilityLayer.builder() + .clientId(clientId) + .clientSecret(clientSecret) + .userAgent(userAgent) + .timeout(timeout) + .requestQueueSize(requestQueueSize) + .logLevel(logLevel) + .proxyConfig(proxyConfig) + .build(); + } + // Hystrix ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds", timeout); ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.requestCache.enabled", false); @@ -122,7 +149,10 @@ public TwitchExtensions build() { * Initialize the builder * * @return Twitch Extensions Builder + * @see Twitch Shutdown Announcement + * @deprecated the Extensions API traditionally uses the decommissioned Kraken API. While the module now forwards calls to Helix, please migrate to using Helix directly as this module will be removed in the future. */ + @Deprecated public static TwitchExtensionsBuilder builder() { return new TwitchExtensionsBuilder(); } diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/ExtensionsTypeConverters.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/ExtensionsTypeConverters.java new file mode 100644 index 000000000..9aa9a0741 --- /dev/null +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/ExtensionsTypeConverters.java @@ -0,0 +1,187 @@ +package com.github.twitch4j.extensions.compat; + +import com.github.twitch4j.extensions.domain.Channel; +import com.github.twitch4j.extensions.domain.ChannelList; +import com.github.twitch4j.extensions.domain.ConfigurationSegment; +import com.github.twitch4j.extensions.domain.ConfigurationSegmentType; +import com.github.twitch4j.extensions.domain.ExtensionInformation; +import com.github.twitch4j.extensions.domain.ExtensionSecret; +import com.github.twitch4j.extensions.domain.ExtensionSecretList; +import com.github.twitch4j.helix.domain.ExtensionConfigurationSegmentList; +import com.github.twitch4j.helix.domain.ExtensionLiveChannel; +import com.github.twitch4j.helix.domain.ExtensionLiveChannelsList; +import com.github.twitch4j.helix.domain.ExtensionSecrets; +import com.github.twitch4j.helix.domain.ExtensionSecretsList; +import com.github.twitch4j.helix.domain.ExtensionSegment; +import com.github.twitch4j.helix.domain.ExtensionState; +import com.github.twitch4j.helix.domain.ReleasedExtension; +import com.github.twitch4j.helix.domain.ReleasedExtensionList; +import lombok.experimental.UtilityClass; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@UtilityClass +class ExtensionsTypeConverters { + + Function SEGMENT_CONVERTER = configurationSegmentType -> { + switch (configurationSegmentType) { + case GLOBAL: + return ExtensionSegment.GLOBAL; + case DEVELOPER: + return ExtensionSegment.DEVELOPER; + case BROADCASTER: + return ExtensionSegment.BROADCASTER; + default: + return null; + } + }; + + Function HELIX_SEGMENT_CONVERTER = extensionSegment -> { + switch (extensionSegment) { + case BROADCASTER: + return ConfigurationSegmentType.BROADCASTER; + case DEVELOPER: + return ConfigurationSegmentType.DEVELOPER; + case GLOBAL: + return ConfigurationSegmentType.GLOBAL; + default: + return null; + } + }; + + Function STATE_CONVERTER = state -> { + switch (state) { + case IN_TEST: + return "testing"; + case ASSETS_UPLOADED: + return "uploading"; + default: + return state.name().toLowerCase(); + } + }; + + Function> VIEWS_CONVERTER = views -> { + if (views == null) return Collections.emptyMap(); + + final BiConsumer> addView = (v, m) -> { + final BiConsumer addProperty = (s, o) -> { + if (o != null) + m.put(s, o); + }; + + addProperty.accept("can_link_external_content", v.canLinkExternalContent()); + addProperty.accept("viewer_url", v.getViewerUrl()); + addProperty.accept("aspect_width", v.getAspectWidth()); + addProperty.accept("aspect_height", v.getAspectHeight()); + addProperty.accept("aspect_ratio_x", v.getAspectRatioX()); + addProperty.accept("aspect_ratio_y", v.getAspectRatioY()); + addProperty.accept("autoscale", v.getAutoscale()); + addProperty.accept("height", v.getHeight()); + addProperty.accept("scale_pixels", v.getScalePixels()); + addProperty.accept("target_height", v.getTargetHeight()); + addProperty.accept("size", v.getSize()); + addProperty.accept("zoom", v.getZoom()); + addProperty.accept("zoom_pixels", v.getZoomPixels()); + }; + + final Map map = new HashMap<>(); + + final BiConsumer addViewMap = (s, v) -> { + if (v != null) { + final Map m = new HashMap<>(); + addView.accept(v, m); + map.put(s, m); + } + }; + + addViewMap.accept("mobile", views.getMobile()); + addViewMap.accept("panel", views.getPanel()); + addViewMap.accept("video_overlay", views.getVideoOverlay()); + addViewMap.accept("component", views.getComponent()); + return Collections.unmodifiableMap(map); + }; + + Function EXTENSION_CONVERTER = ext -> { + Map viewerUrls = ext.getViews() == null ? null : + Stream.of(Pair.of("component", ext.getViews().getComponent()), Pair.of("mobile", ext.getViews().getMobile()), Pair.of("panel", ext.getViews().getPanel()), Pair.of("video_overlay", ext.getViews().getVideoOverlay())) + .filter(pair -> pair.getRight() != null) + .map(pair -> Pair.of(pair.getLeft(), pair.getRight().getViewerUrl())) + .filter(pair -> pair.getRight() != null) + .collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); + + return ExtensionInformation.builder() + .authorName(ext.getAuthorName()) + .bitsEnabled(ext.bitsEnabled()) + .canInstall(ext.canInstall()) + .configurationLocation(ext.getConfigurationLocation()) + .description(ext.getDescription()) + .eulaTosUrl(ext.getEulaTosUrl()) + .hasChatSupport(ext.hasChatSupport()) + .iconUrl(ext.getIconUrl()) + .iconUrls(ext.getIconUrls()) + .id(ext.getId()) + .name(ext.getName()) + .panelHeight(ext.getViews() != null && ext.getViews().getPanel() != null ? ext.getViews().getPanel().getHeight() : null) + .privacyPolicyUrl(ext.getPrivacyPolicyUrl()) + .requestIdentityLink(ext.requestIdentityLink()) + .screenshotUrls(ext.getScreenshotUrls()) + .state(STATE_CONVERTER.apply(ext.getState())) + .subscriptionsSupportLevel(ext.getSubscriptionsSupportLevel()) + .summary(ext.getSummary()) + .supportEmail(ext.getSupportEmail()) + .version(ext.getVersion()) + .viewerSummary(ext.getViewerSummary()) + .viewerUrl(viewerUrls == null || viewerUrls.isEmpty() ? null : viewerUrls.values().toArray(new String[0])[0]) + .viewerUrls(viewerUrls) + .views(VIEWS_CONVERTER.apply(ext.getViews())) + .whitelistedConfigUrls(ext.getAllowlistedConfigUrls()) + .whitelistedPanelUrls(ext.getAllowlistedPanelUrls()) + .build(); + }; + + Function EXTENSION_LIST_CONVERTER = list -> { + if (list == null || list.getData() == null || list.getData().isEmpty()) return null; + return EXTENSION_CONVERTER.apply(list.getData().get(0)); + }; + + Function LIVE_CHANNEL_CONVERTER = c -> new Channel(c.getBroadcasterId(), c.getBroadcasterName(), c.getGameId(), c.getTitle(), null); + + Function LIVE_CHANNELS_CONVERTER = helixList -> { + if (helixList == null || helixList.getChannels() == null) return null; + return new ChannelList(helixList.getChannels().stream().map(LIVE_CHANNEL_CONVERTER).collect(Collectors.toList()), helixList.getCursor().orElse(null)); + }; + + Function SECRET_CONVERTER = secret -> new ExtensionSecret(secret.getActiveAt(), secret.getContent(), secret.getExpiresAt()); + + Function SECRETS_CONVERTER = helixList -> { + if (helixList == null || helixList.getData() == null || helixList.getData().isEmpty()) return null; + final ExtensionSecrets secrets = helixList.getData().get(0); + return new ExtensionSecretList(secrets.getFormatVersion(), secrets.getSecrets().stream().map(SECRET_CONVERTER).collect(Collectors.toList())); + }; + + Function> CONFIG_SEGMENT_LIST_CONVERTER = list -> { + if (list == null || list.getData() == null) return null; + + final Map map = new HashMap<>(); + + list.getData().forEach(segment -> { + String name = segment.getSegment().toString(); + String broadcasterId = segment.getBroadcasterId() == null ? "" : segment.getBroadcasterId(); + String key = name + ':' + broadcasterId; + + ConfigurationSegment.Segment s = new ConfigurationSegment.Segment(HELIX_SEGMENT_CONVERTER.apply(segment.getSegment()), segment.getBroadcasterId()); + ConfigurationSegment.Record r = new ConfigurationSegment.Record(segment.getContent(), segment.getVersion()); + map.put(key, new ConfigurationSegment(s, r)); + }); + + return Collections.unmodifiableMap(map); + }; + +} diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/HystrixCommandConverter.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/HystrixCommandConverter.java new file mode 100644 index 000000000..868763300 --- /dev/null +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/HystrixCommandConverter.java @@ -0,0 +1,24 @@ +package com.github.twitch4j.extensions.compat; + +import com.netflix.hystrix.HystrixCommand; +import lombok.NonNull; + +import java.util.function.Function; + +class HystrixCommandConverter extends HystrixCommand { + + private final HystrixCommand command; + private final Function converter; + + public HystrixCommandConverter(@NonNull HystrixCommand hystrixCommand, @NonNull Function converter) { + super(hystrixCommand.getCommandGroup()); + this.command = hystrixCommand; + this.converter = converter; + } + + @Override + protected U run() { + return converter.apply(command.execute()); + } + +} diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/TwitchExtensionsCompatibilityLayer.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/TwitchExtensionsCompatibilityLayer.java new file mode 100644 index 000000000..5ec890765 --- /dev/null +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/compat/TwitchExtensionsCompatibilityLayer.java @@ -0,0 +1,160 @@ +package com.github.twitch4j.extensions.compat; + +import com.github.twitch4j.common.config.ProxyConfig; +import com.github.twitch4j.common.config.Twitch4JGlobal; +import com.github.twitch4j.extensions.TwitchExtensions; +import com.github.twitch4j.extensions.domain.ChannelList; +import com.github.twitch4j.extensions.domain.ConfigurationSegment; +import com.github.twitch4j.extensions.domain.ConfigurationSegmentType; +import com.github.twitch4j.extensions.domain.ExtensionConfigurationSegment; +import com.github.twitch4j.extensions.domain.ExtensionInformation; +import com.github.twitch4j.extensions.domain.ExtensionSecretList; +import com.github.twitch4j.helix.TwitchHelix; +import com.github.twitch4j.helix.TwitchHelixBuilder; +import com.github.twitch4j.helix.domain.ExtensionConfigurationSegmentInput; +import com.github.twitch4j.helix.domain.ExtensionSegment; +import com.github.twitch4j.helix.domain.SendPubSubMessageInput; +import com.netflix.hystrix.HystrixCommand; +import feign.Logger; +import lombok.Builder; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; + +import static com.github.twitch4j.extensions.compat.ExtensionsTypeConverters.*; // Must be wildcard import for static: https://github.com/projectlombok/lombok/issues/2044 + +/** + * Forwards twitch extensions api calls to the new helix api + */ +@SuppressWarnings("deprecation") +public final class TwitchExtensionsCompatibilityLayer implements TwitchExtensions { + + private final String clientId; + private final TwitchHelix helix; + + @Builder + public TwitchExtensionsCompatibilityLayer(String clientId, String clientSecret, String userAgent, Long timeout, Integer requestQueueSize, Logger.Level logLevel, ProxyConfig proxyConfig) { + this.clientId = clientId; + this.helix = TwitchHelixBuilder.builder() + .withClientId(clientId) + .withClientSecret(clientSecret) + .withUserAgent(userAgent != null ? userAgent : Twitch4JGlobal.userAgent) + .withTimeout(timeout != null ? timeout.intValue() : 5000) + .withRequestQueueSize(requestQueueSize != null ? requestQueueSize : -1) + .withLogLevel(logLevel != null ? logLevel : Logger.Level.NONE) + .withProxyConfig(proxyConfig) + .build(); + } + + @Override + public HystrixCommand createExtensionSecret(String clientId, String jsonWebToken, int activationDelaySeconds) { + return new HystrixCommandConverter<>( + helix.createExtensionSecret(jsonWebToken, getClientId(clientId), activationDelaySeconds), + SECRETS_CONVERTER + ); + } + + @Override + public HystrixCommand getExtensionSecret(String clientId, String jsonWebToken) { + return new HystrixCommandConverter<>( + helix.getExtensionSecrets(jsonWebToken, getClientId(clientId)), + SECRETS_CONVERTER + ); + } + + @Override + public HystrixCommand revokeExtensionSecrets(String clientId, String jsonWebToken) { + throw new UnsupportedOperationException("There is no direct Helix replacement for this endpoint."); + } + + @Override + public HystrixCommand getLiveChannelsWithExtensionActivated(String clientId, String cursor) { + return new HystrixCommandConverter<>( + helix.getExtensionLiveChannels(null, getClientId(clientId), 100, cursor), + LIVE_CHANNELS_CONVERTER + ); + } + + @Override + public HystrixCommand setExtensionRequiredConfiguration(String clientId, String jsonWebToken, String extensionVersion, String channelId, String requiredConfiguration) { + return helix.setExtensionRequiredConfiguration( + jsonWebToken, + getClientId(clientId), + extensionVersion, + requiredConfiguration, + channelId + ); + } + + @Override + public HystrixCommand setExtensionConfigurationSegment(String clientId, String jsonWebToken, ExtensionConfigurationSegment configurationSegment) { + final String extensionId = getClientId(clientId); + return helix.setExtensionConfigurationSegment( + jsonWebToken, + extensionId, + ExtensionConfigurationSegmentInput.builder() + .extensionId(extensionId) + .segment(SEGMENT_CONVERTER.apply(configurationSegment.getSegment())) + .broadcasterId(configurationSegment.getChannelId()) + .content(configurationSegment.getContent()) + .version(configurationSegment.getVersion()) + .build() + ); + } + + @Override + public HystrixCommand> getExtensionChannelConfiguration(String clientId, String jsonWebToken, String channelId) { + return new HystrixCommandConverter<>( + helix.getExtensionConfigurationSegment(jsonWebToken, getClientId(clientId), Arrays.asList(ExtensionSegment.BROADCASTER, ExtensionSegment.DEVELOPER), channelId), + CONFIG_SEGMENT_LIST_CONVERTER + ); + } + + @Override + public HystrixCommand> getExtensionConfigurationSegment(String clientId, String jsonWebToken, ConfigurationSegmentType segmentType, String channelId) { + return new HystrixCommandConverter<>( + helix.getExtensionConfigurationSegment(jsonWebToken, getClientId(clientId), Collections.singletonList(SEGMENT_CONVERTER.apply(segmentType)), channelId), + CONFIG_SEGMENT_LIST_CONVERTER + ); + } + + @Override + public HystrixCommand sendExtensionPubSubMessage(String clientId, String jsonWebToken, String channelId, String message, String targets) { + return helix.sendExtensionPubSubMessage( + jsonWebToken, + getClientId(clientId), + SendPubSubMessageInput.builder() + .broadcasterId(channelId) + .message(message) + .target(targets) + .globalBroadcast(SendPubSubMessageInput.GLOBAL_TARGET.equals(targets)) + .build() + ); + } + + @Override + public HystrixCommand sendExtensionChatMessage(String clientId, String jsonWebToken, String extensionVersion, String channelId, String text) { + return helix.sendExtensionChatMessage( + jsonWebToken, + getClientId(clientId), + extensionVersion, + channelId, + text + ); + } + + @Override + public HystrixCommand getExtensionInformation(String clientId) { + return new HystrixCommandConverter<>( + helix.getReleasedExtensions(null, getClientId(clientId), null), + EXTENSION_LIST_CONVERTER + ); + } + + private String getClientId(String overrideId) { + return StringUtils.isNotBlank(overrideId) ? overrideId : this.clientId; + } + +} diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/Channel.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/Channel.java index d48434818..20918e275 100644 --- a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/Channel.java +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/Channel.java @@ -1,6 +1,7 @@ package com.github.twitch4j.extensions.domain; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.Setter; @@ -8,16 +9,35 @@ @Data @Setter(AccessLevel.PRIVATE) @NoArgsConstructor +@AllArgsConstructor public class Channel { + /** + * User id of the channel owner. + */ private String id; + /** + * Display name of the channel owner. + */ private String username; + /** + * Game Id. + */ private String game; + /** + * Stream title. + */ private String title; + /** + * Stream view count. + * + * @deprecated No migration path in the new Helix API. + */ + @Deprecated private Long viewCount; } diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ChannelList.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ChannelList.java index 704543794..dec98b70c 100644 --- a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ChannelList.java +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ChannelList.java @@ -1,6 +1,7 @@ package com.github.twitch4j.extensions.domain; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -12,10 +13,13 @@ @Data @Setter(AccessLevel.PRIVATE) @NoArgsConstructor +@AllArgsConstructor @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class ChannelList extends ExtensionsPagination { private List channels; + private String cursor; + } diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ConfigurationSegment.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ConfigurationSegment.java index 2f60c9170..32b411128 100644 --- a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ConfigurationSegment.java +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ConfigurationSegment.java @@ -1,6 +1,7 @@ package com.github.twitch4j.extensions.domain; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.Setter; @@ -8,6 +9,7 @@ @Data @Setter(AccessLevel.PRIVATE) @NoArgsConstructor +@AllArgsConstructor public class ConfigurationSegment { private Segment segment; private Record record; @@ -15,6 +17,7 @@ public class ConfigurationSegment { @Data @Setter(AccessLevel.PRIVATE) @NoArgsConstructor + @AllArgsConstructor public static class Segment { private ConfigurationSegmentType segmentType; private String channelId; @@ -23,6 +26,7 @@ public static class Segment { @Data @Setter(AccessLevel.PRIVATE) @NoArgsConstructor + @AllArgsConstructor public static class Record { private String content; private String version; diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionInformation.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionInformation.java index 8bc0c171a..c2624744b 100644 --- a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionInformation.java +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionInformation.java @@ -2,9 +2,12 @@ import com.github.twitch4j.common.annotation.Unofficial; import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.extern.jackson.Jacksonized; import java.util.List; import java.util.Map; @@ -12,6 +15,9 @@ @Data @Setter(AccessLevel.PRIVATE) @NoArgsConstructor +@AllArgsConstructor +@Builder +@Jacksonized @Unofficial public class ExtensionInformation { diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionSecret.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionSecret.java index a41925606..bd02c9b12 100644 --- a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionSecret.java +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionSecret.java @@ -1,6 +1,7 @@ package com.github.twitch4j.extensions.domain; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.Setter; @@ -10,6 +11,7 @@ @Data @Setter(AccessLevel.PRIVATE) @NoArgsConstructor +@AllArgsConstructor public class ExtensionSecret { private Instant active; diff --git a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionSecretList.java b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionSecretList.java index ca895abaa..4d9d9b916 100644 --- a/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionSecretList.java +++ b/rest-extensions/src/main/java/com/github/twitch4j/extensions/domain/ExtensionSecretList.java @@ -1,6 +1,7 @@ package com.github.twitch4j.extensions.domain; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.Setter; @@ -10,6 +11,7 @@ @Data @Setter(AccessLevel.PRIVATE) @NoArgsConstructor +@AllArgsConstructor public class ExtensionSecretList { private Integer formatVersion; diff --git a/twitch4j/src/main/java/com/github/twitch4j/TwitchClientBuilder.java b/twitch4j/src/main/java/com/github/twitch4j/TwitchClientBuilder.java index 775de6b5f..761c763ee 100644 --- a/twitch4j/src/main/java/com/github/twitch4j/TwitchClientBuilder.java +++ b/twitch4j/src/main/java/com/github/twitch4j/TwitchClientBuilder.java @@ -86,8 +86,12 @@ public class TwitchClientBuilder { /** * Enabled: Extensions + * + * @see Twitch Shutdown Announcement + * @deprecated the Extensions API traditionally uses the decommissioned Kraken API. While the module now forwards calls to Helix, please migrate to using Helix directly as this module will be removed in the future. */ @With + @Deprecated private Boolean enableExtensions = false; /** diff --git a/twitch4j/src/main/java/com/github/twitch4j/TwitchClientPoolBuilder.java b/twitch4j/src/main/java/com/github/twitch4j/TwitchClientPoolBuilder.java index 2f8328cf7..ed9792eb9 100644 --- a/twitch4j/src/main/java/com/github/twitch4j/TwitchClientPoolBuilder.java +++ b/twitch4j/src/main/java/com/github/twitch4j/TwitchClientPoolBuilder.java @@ -95,8 +95,12 @@ public class TwitchClientPoolBuilder { /** * Enabled: Extensions + * + * @see Twitch Shutdown Announcement + * @deprecated the Extensions API traditionally uses the decommissioned Kraken API. While the module now forwards calls to Helix, please migrate to using Helix directly as this module will be removed in the future. */ @With + @Deprecated private Boolean enableExtensions = false; /**