From 2bef42d977edba9a12f1767f2814533f2b1fff72 Mon Sep 17 00:00:00 2001 From: iProdigy Date: Tue, 30 Aug 2022 12:19:59 -0700 Subject: [PATCH] feat: implement beta charity api (#628) * feat(eventsub): add charity campaign donate type * feat(helix): add get charity campaign endpoint * feat(chat): add charity donation event * feat(pubsub): add unofficial charity topic * refactor(pubsub): avoid wildcard import --- .../twitch4j/auth/domain/TwitchScopes.java | 1 + .../twitch4j/chat/events/IRCEventHandler.java | 8 ++ .../events/channel/CharityDonationEvent.java | 60 +++++++++++++++ .../twitch4j/common/util/DonationAmount.java | 58 +++++++++++++++ .../ChannelCharityCampaignCondition.java | 12 +++ .../events/ChannelCharityDonateEvent.java | 30 ++++++++ .../ChannelCharityDonateType.java | 39 ++++++++++ .../subscriptions/SubscriptionTypes.java | 3 + .../github/twitch4j/pubsub/ITwitchPubSub.java | 7 +- .../github/twitch4j/pubsub/TwitchPubSub.java | 19 ++++- .../pubsub/domain/CharityCampaignStatus.java | 27 +++++++ .../pubsub/domain/CharityDonationData.java | 32 ++++++++ .../events/CharityCampaignDonationEvent.java | 13 ++++ .../events/CharityCampaignStatusEvent.java | 13 ++++ .../github/twitch4j/helix/TwitchHelix.java | 21 ++++++ .../helix/domain/CharityCampaign.java | 73 +++++++++++++++++++ .../helix/domain/CharityCampaignWrapper.java | 32 ++++++++ 17 files changed, 446 insertions(+), 2 deletions(-) create mode 100644 chat/src/main/java/com/github/twitch4j/chat/events/channel/CharityDonationEvent.java create mode 100644 common/src/main/java/com/github/twitch4j/common/util/DonationAmount.java create mode 100644 eventsub-common/src/main/java/com/github/twitch4j/eventsub/condition/ChannelCharityCampaignCondition.java create mode 100644 eventsub-common/src/main/java/com/github/twitch4j/eventsub/events/ChannelCharityDonateEvent.java create mode 100644 eventsub-common/src/main/java/com/github/twitch4j/eventsub/subscriptions/ChannelCharityDonateType.java create mode 100644 pubsub/src/main/java/com/github/twitch4j/pubsub/domain/CharityCampaignStatus.java create mode 100644 pubsub/src/main/java/com/github/twitch4j/pubsub/domain/CharityDonationData.java create mode 100644 pubsub/src/main/java/com/github/twitch4j/pubsub/events/CharityCampaignDonationEvent.java create mode 100644 pubsub/src/main/java/com/github/twitch4j/pubsub/events/CharityCampaignStatusEvent.java create mode 100644 rest-helix/src/main/java/com/github/twitch4j/helix/domain/CharityCampaign.java create mode 100644 rest-helix/src/main/java/com/github/twitch4j/helix/domain/CharityCampaignWrapper.java diff --git a/auth/src/main/java/com/github/twitch4j/auth/domain/TwitchScopes.java b/auth/src/main/java/com/github/twitch4j/auth/domain/TwitchScopes.java index a0384bab8..c30f1403d 100644 --- a/auth/src/main/java/com/github/twitch4j/auth/domain/TwitchScopes.java +++ b/auth/src/main/java/com/github/twitch4j/auth/domain/TwitchScopes.java @@ -15,6 +15,7 @@ public enum TwitchScopes { HELIX_BITS_READ("bits:read"), HELIX_CLIPS_EDIT("clips:edit"), HELIX_CHANNEL_BROADCAST_MANAGE("channel:manage:broadcast"), + HELIX_CHANNEL_CHARITY_READ("channel:read:charity"), HELIX_CHANNEL_COMMERCIALS_EDIT("channel:edit:commercial"), HELIX_CHANNEL_EXTENSION_MANAGE("channel:manage:extensions"), HELIX_CHANNEL_EDITORS_READ("channel:read:editors"), diff --git a/chat/src/main/java/com/github/twitch4j/chat/events/IRCEventHandler.java b/chat/src/main/java/com/github/twitch4j/chat/events/IRCEventHandler.java index 1c57d1985..bf6952ec6 100644 --- a/chat/src/main/java/com/github/twitch4j/chat/events/IRCEventHandler.java +++ b/chat/src/main/java/com/github/twitch4j/chat/events/IRCEventHandler.java @@ -78,6 +78,7 @@ public IRCEventHandler(TwitchChat twitchChat) { eventManager.onEvent("twitch4j-chat-roomstate-trigger", IRCMessageEvent.class, this::onChannelState); eventManager.onEvent("twitch4j-chat-gift-trigger", IRCMessageEvent.class, this::onGiftReceived); eventManager.onEvent("twitch4j-chat-payforward-trigger", IRCMessageEvent.class, this::onPayForward); + eventManager.onEvent("twitch4j-chat-charity-trigger", IRCMessageEvent.class, this::onCharityDonation); eventManager.onEvent("twitch4j-chat-raid-trigger", IRCMessageEvent.class, this::onRaid); eventManager.onEvent("twitch4j-chat-unraid-trigger", IRCMessageEvent.class, this::onUnraid); eventManager.onEvent("twitch4j-chat-rewardgift-trigger", IRCMessageEvent.class, this::onRewardGift); @@ -348,6 +349,13 @@ public void onPayForward(IRCMessageEvent event) { } } + @Unofficial + public void onCharityDonation(IRCMessageEvent event) { + if ("USERNOTICE".equals(event.getCommandType()) && "charitydonation".equalsIgnoreCase(event.getTags().get("msg-id"))) { + eventManager.publish(new CharityDonationEvent(event)); + } + } + /** * ChatChannel Raid Event (receiving) * @param event IRCMessageEvent diff --git a/chat/src/main/java/com/github/twitch4j/chat/events/channel/CharityDonationEvent.java b/chat/src/main/java/com/github/twitch4j/chat/events/channel/CharityDonationEvent.java new file mode 100644 index 000000000..09e68fff9 --- /dev/null +++ b/chat/src/main/java/com/github/twitch4j/chat/events/channel/CharityDonationEvent.java @@ -0,0 +1,60 @@ +package com.github.twitch4j.chat.events.channel; + +import com.github.twitch4j.chat.events.AbstractChannelEvent; +import com.github.twitch4j.common.annotation.Unofficial; +import com.github.twitch4j.common.enums.CommandPermission; +import com.github.twitch4j.common.events.domain.EventUser; +import com.github.twitch4j.common.util.DonationAmount; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +@Value +@Unofficial +@EqualsAndHashCode(callSuper = true) +public class CharityDonationEvent extends AbstractChannelEvent { + + @NotNull + @EqualsAndHashCode.Exclude + IRCMessageEvent messageEvent; + + String userId; + + String userLogin; + + String userName; + + Set badges; + + String charityName; + + DonationAmount amount; + + String systemMessage; + + public CharityDonationEvent(@NotNull IRCMessageEvent rawEvent) { + super(rawEvent.getChannel()); + this.messageEvent = rawEvent; + this.userId = rawEvent.getTagValue("user-id").orElse(null); + this.userLogin = rawEvent.getTagValue("login").orElse(null); + this.userName = rawEvent.getTagValue("display-name").orElse(userLogin); + this.badges = rawEvent.getClientPermissions(); + this.charityName = rawEvent.getTagValue("msg-param-charity-name").orElse(null); + + Long amount = Long.parseLong(rawEvent.getTags().get("msg-param-donation-amount")); + String currency = rawEvent.getTagValue("msg-param-donation-currency").orElse("USD"); + Integer decimals = Integer.parseInt(rawEvent.getTags().getOrDefault("msg-param-exponent", "2")); + this.amount = new DonationAmount(amount, decimals, currency); + + this.systemMessage = rawEvent.getTagValue("system-msg").orElseGet( + () -> String.format("%s donated %s %s to support %s", userName, currency, this.amount.getParsedValue().toPlainString(), charityName) + ); + } + + public EventUser getUser() { + return new EventUser(userId, userLogin); + } + +} diff --git a/common/src/main/java/com/github/twitch4j/common/util/DonationAmount.java b/common/src/main/java/com/github/twitch4j/common/util/DonationAmount.java new file mode 100644 index 000000000..d04991c9a --- /dev/null +++ b/common/src/main/java/com/github/twitch4j/common/util/DonationAmount.java @@ -0,0 +1,58 @@ +package com.github.twitch4j.common.util; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.math.BigDecimal; +import java.util.Currency; + +@Data +@Setter(AccessLevel.PRIVATE) +@NoArgsConstructor +@AllArgsConstructor +public class DonationAmount { + + /** + * The monetary amount. + *

+ * The amount is specified in the currency’s minor unit. + *

+ * For example, the minor units for USD is cents, so if the amount is $5.50 USD, value is set to 550. + */ + private Long value; + + /** + * The number of decimal places used by the currency. + *

+ * For example, USD uses two decimal places. + */ + private Integer decimalPlaces; + + /** + * The ISO-4217 three-letter currency code that identifies the type of currency in {@link #getValue()}. + */ + private String currency; + + /** + * The {@link Currency} corresponding to the ISO-4217 code contained in {@link #getCurrency()}. + */ + @JsonIgnore + @Getter(lazy = true) + @EqualsAndHashCode.Exclude + private final Currency parsedCurrency = Currency.getInstance(getCurrency()); + + /** + * The donation amount, with the appropriate decimals, based on {@link #getValue()}. + */ + @JsonIgnore + @Getter(lazy = true) + @EqualsAndHashCode.Exclude + private final BigDecimal parsedValue = BigDecimal.valueOf(getValue(), getDecimalPlaces()); + +} diff --git a/eventsub-common/src/main/java/com/github/twitch4j/eventsub/condition/ChannelCharityCampaignCondition.java b/eventsub-common/src/main/java/com/github/twitch4j/eventsub/condition/ChannelCharityCampaignCondition.java new file mode 100644 index 000000000..43cf8a292 --- /dev/null +++ b/eventsub-common/src/main/java/com/github/twitch4j/eventsub/condition/ChannelCharityCampaignCondition.java @@ -0,0 +1,12 @@ +package com.github.twitch4j.eventsub.condition; + +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.SuperBuilder; +import lombok.extern.jackson.Jacksonized; + +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Jacksonized +public class ChannelCharityCampaignCondition extends ChannelEventSubCondition {} diff --git a/eventsub-common/src/main/java/com/github/twitch4j/eventsub/events/ChannelCharityDonateEvent.java b/eventsub-common/src/main/java/com/github/twitch4j/eventsub/events/ChannelCharityDonateEvent.java new file mode 100644 index 000000000..4be3e36e6 --- /dev/null +++ b/eventsub-common/src/main/java/com/github/twitch4j/eventsub/events/ChannelCharityDonateEvent.java @@ -0,0 +1,30 @@ +package com.github.twitch4j.eventsub.events; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.twitch4j.common.util.DonationAmount; +import lombok.AccessLevel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Data +@Setter(AccessLevel.PRIVATE) +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class ChannelCharityDonateEvent extends EventSubUserChannelEvent { + + /** + * An ID that uniquely identifies the charity campaign. + */ + @JsonProperty("id") + private String campaignId; + + /** + * An object that contains the amount of the user’s donation. + */ + private DonationAmount amount; + +} diff --git a/eventsub-common/src/main/java/com/github/twitch4j/eventsub/subscriptions/ChannelCharityDonateType.java b/eventsub-common/src/main/java/com/github/twitch4j/eventsub/subscriptions/ChannelCharityDonateType.java new file mode 100644 index 000000000..916a0c12e --- /dev/null +++ b/eventsub-common/src/main/java/com/github/twitch4j/eventsub/subscriptions/ChannelCharityDonateType.java @@ -0,0 +1,39 @@ +package com.github.twitch4j.eventsub.subscriptions; + +import com.github.twitch4j.common.annotation.Unofficial; +import com.github.twitch4j.eventsub.condition.ChannelCharityCampaignCondition; +import com.github.twitch4j.eventsub.events.ChannelCharityDonateEvent; + +/** + * Channel Charity Campaign Donate + *

+ * Sends an event notification when a user donates to the broadcaster’s charity campaign. + *

+ * This subscription type is currently in open beta. + * + * @see com.github.twitch4j.auth.domain.TwitchScopes#HELIX_CHANNEL_CHARITY_READ + */ +@Unofficial +public class ChannelCharityDonateType implements SubscriptionType, ChannelCharityDonateEvent> { + + @Override + public String getName() { + return "channel.charity_campaign.donate"; + } + + @Override + public String getVersion() { + return "1"; + } + + @Override + public ChannelCharityCampaignCondition.ChannelCharityCampaignConditionBuilder getConditionBuilder() { + return ChannelCharityCampaignCondition.builder(); + } + + @Override + public Class getEventClass() { + return ChannelCharityDonateEvent.class; + } + +} diff --git a/eventsub-common/src/main/java/com/github/twitch4j/eventsub/subscriptions/SubscriptionTypes.java b/eventsub-common/src/main/java/com/github/twitch4j/eventsub/subscriptions/SubscriptionTypes.java index 464531a51..0e7d9ec8a 100644 --- a/eventsub-common/src/main/java/com/github/twitch4j/eventsub/subscriptions/SubscriptionTypes.java +++ b/eventsub-common/src/main/java/com/github/twitch4j/eventsub/subscriptions/SubscriptionTypes.java @@ -12,7 +12,9 @@ @UtilityClass public class SubscriptionTypes { private final Map> SUBSCRIPTION_TYPES; + public final ChannelBanType CHANNEL_BAN; + @Unofficial public final ChannelCharityDonateType CHANNEL_CHARITY_DONATE; public final ChannelCheerType CHANNEL_CHEER; public final ChannelFollowType CHANNEL_FOLLOW; public final ChannelGoalBeginType CHANNEL_GOAL_BEGIN; @@ -58,6 +60,7 @@ public class SubscriptionTypes { SUBSCRIPTION_TYPES = Collections.unmodifiableMap( Stream.of( CHANNEL_BAN = new ChannelBanType(), + CHANNEL_CHARITY_DONATE = new ChannelCharityDonateType(), CHANNEL_CHEER = new ChannelCheerType(), CHANNEL_FOLLOW = new ChannelFollowType(), CHANNEL_GOAL_BEGIN = new ChannelGoalBeginType(), diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/ITwitchPubSub.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/ITwitchPubSub.java index fd03e6da1..9e1c6c0d7 100644 --- a/pubsub/src/main/java/com/github/twitch4j/pubsub/ITwitchPubSub.java +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/ITwitchPubSub.java @@ -300,7 +300,7 @@ default PubSubSubscription listenForLeaderboardMonthlyEvents(OAuth2Credential cr @Unofficial default PubSubSubscription listenForLeaderboardAllTimeEvents(OAuth2Credential credential, String channelId) { - return listenForLeaderboardEvents(credential, channelId, "ALLTIME"); + return listenForLeaderboardEvents(credential, channelId, "ALLTIME"); } @Unofficial @@ -355,6 +355,11 @@ default PubSubSubscription listenForChannelExtensionEvents(OAuth2Credential cred return listenOnTopic(PubSubType.LISTEN, credential, "channel-ext-v1." + channelId); } + @Unofficial + default PubSubSubscription listenForCharityCampaignEvents(OAuth2Credential credential, String channelId) { + return listenOnTopic(PubSubType.LISTEN, credential, "charity-campaign-donation-events-v1." + channelId); + } + @Unofficial @Deprecated default PubSubSubscription listenForExtensionControlEvents(OAuth2Credential credential, String channelId) { diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/TwitchPubSub.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/TwitchPubSub.java index da8757eb1..901405c78 100644 --- a/pubsub/src/main/java/com/github/twitch4j/pubsub/TwitchPubSub.java +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/TwitchPubSub.java @@ -22,6 +22,8 @@ import com.github.twitch4j.pubsub.domain.ChannelPointsRedemption; import com.github.twitch4j.pubsub.domain.ChannelPointsReward; import com.github.twitch4j.pubsub.domain.ChannelTermsAction; +import com.github.twitch4j.pubsub.domain.CharityCampaignStatus; +import com.github.twitch4j.pubsub.domain.CharityDonationData; import com.github.twitch4j.pubsub.domain.ChatModerationAction; import com.github.twitch4j.pubsub.domain.CheerbombData; import com.github.twitch4j.pubsub.domain.ClaimData; @@ -73,6 +75,8 @@ import com.github.twitch4j.pubsub.events.ChannelTermsEvent; import com.github.twitch4j.pubsub.events.ChannelUnbanRequestCreateEvent; import com.github.twitch4j.pubsub.events.ChannelUnbanRequestUpdateEvent; +import com.github.twitch4j.pubsub.events.CharityCampaignDonationEvent; +import com.github.twitch4j.pubsub.events.CharityCampaignStatusEvent; import com.github.twitch4j.pubsub.events.ChatModerationEvent; import com.github.twitch4j.pubsub.events.CheerbombEvent; import com.github.twitch4j.pubsub.events.ClaimAvailableEvent; @@ -514,7 +518,20 @@ protected void onTextMessage(String text) { log.warn("Unparsable Message: " + message.getType() + "|" + message.getData()); break; } - + } else if ("charity-campaign-donation-events-v1".equals(topicName) && topicParts.length > 1) { + switch (type) { + case "charity_campaign_donation": + CharityDonationData donation = TypeConvert.jsonToObject(rawMessage, CharityDonationData.class); + eventManager.publish(new CharityCampaignDonationEvent(lastTopicIdentifier, donation)); + break; + case "charity_campaign_status": + CharityCampaignStatus status = TypeConvert.jsonToObject(rawMessage, CharityCampaignStatus.class); + eventManager.publish(new CharityCampaignStatusEvent(lastTopicIdentifier, status)); + break; + default: + log.warn("Unparsable Message: " + message.getType() + "|" + message.getData()); + break; + } } else if ("chat_moderator_actions".equals(topicName) && topicParts.length > 1) { switch (type) { case "moderation_action": diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/CharityCampaignStatus.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/CharityCampaignStatus.java new file mode 100644 index 000000000..39c4cd493 --- /dev/null +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/CharityCampaignStatus.java @@ -0,0 +1,27 @@ +package com.github.twitch4j.pubsub.domain; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AccessLevel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Accessors; + +@Data +@Setter(AccessLevel.PRIVATE) +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CharityCampaignStatus extends CharityDonationData { + + @Accessors(fluent = true) + @JsonProperty("is_active") + private Boolean isActive; + + @JsonProperty("campaign_name") + private String charityName; + + @JsonProperty("campaign_description") + private String charityDescription; + +} diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/CharityDonationData.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/CharityDonationData.java new file mode 100644 index 000000000..513433ccd --- /dev/null +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/domain/CharityDonationData.java @@ -0,0 +1,32 @@ +package com.github.twitch4j.pubsub.domain; + +import com.github.twitch4j.common.util.DonationAmount; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +import java.util.Optional; + +@Data +@Setter(AccessLevel.PRIVATE) +public class CharityDonationData { + + private String campaignId; + + private String campaignCurrency = "USD"; + + private Long donationTotal; + + private Long goalTarget; + + public DonationAmount getTotal() { + return new DonationAmount(donationTotal, 2, campaignCurrency); + } + + public Optional getTarget() { + return Optional.ofNullable(goalTarget) + .filter(l -> l > 0) + .map(target -> new DonationAmount(target, 2, campaignCurrency)); + } + +} diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/events/CharityCampaignDonationEvent.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/events/CharityCampaignDonationEvent.java new file mode 100644 index 000000000..3fea98a72 --- /dev/null +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/events/CharityCampaignDonationEvent.java @@ -0,0 +1,13 @@ +package com.github.twitch4j.pubsub.events; + +import com.github.twitch4j.common.events.TwitchEvent; +import com.github.twitch4j.pubsub.domain.CharityDonationData; +import lombok.EqualsAndHashCode; +import lombok.Value; + +@Value +@EqualsAndHashCode(callSuper = false) +public class CharityCampaignDonationEvent extends TwitchEvent { + String channelId; + CharityDonationData data; +} diff --git a/pubsub/src/main/java/com/github/twitch4j/pubsub/events/CharityCampaignStatusEvent.java b/pubsub/src/main/java/com/github/twitch4j/pubsub/events/CharityCampaignStatusEvent.java new file mode 100644 index 000000000..416bee2d5 --- /dev/null +++ b/pubsub/src/main/java/com/github/twitch4j/pubsub/events/CharityCampaignStatusEvent.java @@ -0,0 +1,13 @@ +package com.github.twitch4j.pubsub.events; + +import com.github.twitch4j.common.events.TwitchEvent; +import com.github.twitch4j.pubsub.domain.CharityCampaignStatus; +import lombok.EqualsAndHashCode; +import lombok.Value; + +@Value +@EqualsAndHashCode(callSuper = false) +public class CharityCampaignStatusEvent extends TwitchEvent { + String channelId; + CharityCampaignStatus data; +} diff --git a/rest-helix/src/main/java/com/github/twitch4j/helix/TwitchHelix.java b/rest-helix/src/main/java/com/github/twitch4j/helix/TwitchHelix.java index 81230b926..1b4140aa4 100644 --- a/rest-helix/src/main/java/com/github/twitch4j/helix/TwitchHelix.java +++ b/rest-helix/src/main/java/com/github/twitch4j/helix/TwitchHelix.java @@ -324,6 +324,27 @@ HystrixCommand updateRedemptionStatus( @Param("status") RedemptionStatus newStatus ); + /** + * Gets information about the charity campaign that a broadcaster is running, + * such as their fundraising goal and the amount that’s been donated so far. + *

+ * The ID in the broadcaster_id query parameter must match the user ID in the access token. + *

+ * To receive events as donations occur, use {@link com.github.twitch4j.eventsub.subscriptions.SubscriptionTypes#CHANNEL_CHARITY_DONATE}. + * + * @param authToken Broadcaster user access token with the channel:read:charity scope. + * @param broadcasterId The ID of the broadcaster that’s actively running a charity campaign. + * @return CharityCampaignWrapper + * @see com.github.twitch4j.auth.domain.TwitchScopes#HELIX_CHANNEL_CHARITY_READ + */ + @Unofficial // in open beta + @RequestLine("GET /charity/campaigns?broadcaster_id={broadcaster_id}") + @Headers("Authorization: Bearer {token}") + HystrixCommand getCharityCampaign( + @Param("token") String authToken, + @Param("broadcaster_id") String broadcasterId + ); + /** * Sends an announcement to the broadcaster’s chat room. * diff --git a/rest-helix/src/main/java/com/github/twitch4j/helix/domain/CharityCampaign.java b/rest-helix/src/main/java/com/github/twitch4j/helix/domain/CharityCampaign.java new file mode 100644 index 000000000..b7802219d --- /dev/null +++ b/rest-helix/src/main/java/com/github/twitch4j/helix/domain/CharityCampaign.java @@ -0,0 +1,73 @@ +package com.github.twitch4j.helix.domain; + +import com.github.twitch4j.common.util.DonationAmount; +import lombok.AccessLevel; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.jetbrains.annotations.Nullable; + +/** + * The charity campaign that the broadcaster is currently running. + */ +@Data +@Setter(AccessLevel.PRIVATE) +@NoArgsConstructor +public class CharityCampaign { + + /** + * An ID that uniquely identifies the charity campaign. + */ + private String id; + + /** + * An ID that uniquely identifies the broadcaster that’s running the campaign. + */ + private String broadcasterId; + + /** + * The broadcaster’s display name. + */ + private String broadcasterName; + + /** + * The broadcaster’s login name. + */ + private String broadcasterLogin; + + /** + * The charity’s name. + */ + private String charityName; + + /** + * A description of the charity. + */ + private String charityDescription; + + /** + * A URL to an image of the charity’s logo. + *

+ * The image’s type is PNG and its size is 100px X 100px. + */ + private String charityLogo; + + /** + * A URL to the charity’s website. + */ + private String charityWebsite; + + /** + * An object that contains the current amount of donations that the campaign has received. + */ + private DonationAmount currentAmount; + + /** + * An object that contains the amount of money that the campaign is trying to raise. + *

+ * This field may be null if the broadcaster has not defined a target goal. + */ + @Nullable + private DonationAmount targetAmount; + +} diff --git a/rest-helix/src/main/java/com/github/twitch4j/helix/domain/CharityCampaignWrapper.java b/rest-helix/src/main/java/com/github/twitch4j/helix/domain/CharityCampaignWrapper.java new file mode 100644 index 000000000..c339843f0 --- /dev/null +++ b/rest-helix/src/main/java/com/github/twitch4j/helix/domain/CharityCampaignWrapper.java @@ -0,0 +1,32 @@ +package com.github.twitch4j.helix.domain; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; +import java.util.Optional; + +@Data +@Setter(AccessLevel.PRIVATE) +@NoArgsConstructor +public class CharityCampaignWrapper { + + /** + * A list that contains the charity campaign that the broadcaster is currently running. + *

+ * The array is empty if the broadcaster is not running a charity campaign; + * the campaign information is no longer available as soon as the campaign ends. + */ + private List data; + + /** + * @return the currently running charity campaign, in an optional wrapper. + */ + public Optional getCurrentCampaign() { + if (data == null || data.isEmpty()) return Optional.empty(); + return Optional.ofNullable(data.get(0)); + } + +}